ViRCScript Documentation (for Visual IRC '97 1.00 and above) - Revision 20
==========================================================================

This is the documentation for ViRCScript, ViRC '97's advanced scripting
language. At over 4000 lines long, this is one heavyweight document!! This is
not intended as an introduction to IRC commands or to programming languages in
general. Rather, it is for people who wish to use ViRCScript to extend the
functionality of ViRC '97 in any way imaginable.

If you are having scripting problems, the people on EFnet #virc will be glad to
help, although please try to read this file thoroughly first!!

Features new in this release of ViRCScript are marked with an * in the index.

Index
=====

[1.0] Introduction
  [1.1] What's new in this release of ViRCScript?
  [1.2] Syntax (read this ;)
  [1.3] Variables
  [1.4] Variables within variables (don't necessarily read this ;)
[2.0] ViRCScript language reference
  [2.1] Flow control statements
    [2.1.1] If/Else/EndIf
    [2.1.2] For/EndFor
    [2.1.3] ForEach/EndForEach *
    [2.1.4] Switch/Case/EndSwitch *
      [2.1.3.1] Expr directive *
      [2.1.3.2] Is directive *
      [2.1.3.3] Matches directive *
      [2.1.3.4] Multi directive *
      [2.1.3.5] Range directive *
    [2.1.4] While/EndWhile
  [2.2] Alias/event/menu definition statements
    [2.2.1] Alias/EndAlias
    [2.2.2] Event/EndEvent
    [2.2.3] MenuTree/EndMenuTree
    [2.2.4] MenuItem/EndMenuItem
  [2.3] Parsing statements
    [2.3.1] Parse/EndParse (obsolete - use list-handling functions instead)
  [2.4] Commands
    [2.4.1] Formatted text output commands
      [2.4.1.1] FlushBitmapCache *
      [2.4.1.2] TextOut
      [2.4.1.3] TextOutBitmap *
    [2.4.2] Flow control commands
      [2.4.2.1] Break
      [2.4.2.2] Continue
      [2.4.2.4] FallThrough
      [2.4.2.3] Halt
      [2.4.2.5] Yield
    [2.4.3] Alias/event/menu control commands
      [2.4.3.1] DisableEvent
      [2.4.3.2] EnableEvent
      [2.4.3.3] FireEvent
      [2.4.3.4] SetAlias
      [2.4.3.5] UnAlias
      [2.4.3.6] UnEvent
      [2.4.3.7] UpdateMenus
    [2.4.4] Window manipulation commands
      [2.4.4.1] Close
      [2.4.4.2] Max
      [2.4.4.3] Min
      [2.4.4.4] Restore
      [2.4.4.5] SetFocus
    [2.4.5] File I/O commands
      [2.4.5.2] AppendText
      [2.4.5.1] CreateFile
      [2.4.5.5] ChDir
      [2.4.5.4] MkDir
      [2.4.5.6] RmDir
      [2.4.5.3] RmFile
    [2.4.6] Registry I/O commands
      [2.4.6.1] RehashRegistry
      [2.4.6.2] WriteRegistry
    [2.4.7] Sound and multimedia commands
      [2.4.7.1] Beep
      [2.4.7.2] MCI
    [2.4.8] Server (and IRC) commands
      [2.4.8.1] Say
      [2.4.8.2] ASay
      [2.4.8.3] AMe
      [2.4.8.4] SimulateServerData
      [2.4.8.5] Using regular IRC commands
    [2.4.9] Inter-server communication commands
      [2.4.9.1] OnServer *
    [2.4.10] Miscellaneous commands
      [2.4.10.1] AcceptDCC *
      [2.4.10.2] AddToIAL *
      [2.4.10.3] CancelDCC *
      [2.4.10.4] DDE
      [2.4.10.5] DisableInternalXDCCEvents *
      [2.4.10.6] DNS
      [2.4.10.7] EnableInternalXDCCEvents *
      [2.4.10.8] Eval
      [2.4.10.9] Name
      [2.4.10.10] NoAttribs
      [2.4.10.11] MessageBox
      [2.4.10.12] SetInputLine
      [2.4.10.13] UserAdd
      [2.4.10.14] UserDelete
      [2.4.10.15] UserDeleteWithWildcards
    [2.4.11] Debugging commands
      [2.4.11.1] EvaluateWindow
  [2.5] Functions
    [2.5.1] String manipulation functions
      [2.5.1.1] Asc
      [2.5.1.2] Char
      [2.5.1.3] IsNumeric *
      [2.5.1.4] IsChannel *
      [2.5.1.5] IsURL *
      [2.5.1.6] Length
      [2.5.1.7] Lower
      [2.5.1.8] MaskMatch
      [2.5.1.9] RStrPos
      [2.5.1.10] RStrTokL
      [2.5.1.11] RStrTokR
      [2.5.1.12] StrPos
      [2.5.1.13] StrPosFrom
      [2.5.1.14] StrTokL
      [2.5.1.15] StrTokR
      [2.5.1.16] StrTrim
      [2.5.1.17] SubStr
      [2.5.1.18] Upper
      [2.5.1.19] WildMatch
      [2.5.1.20] WordCount
    [2.5.2] List manipulation functions
      [2.5.2.1] listElementCount *
      [2.5.2.2] listIndex *
      [2.5.2.3] listIndexOf *
      [2.5.2.4] listInsert *
      [2.5.2.5] listJoin *
      [2.5.2.6] listRange *
      [2.5.2.7] listRemove *
      [2.5.2.8] listReplace *
      [2.5.2.9] listSearch *
      [2.5.2.10] listSearchReplace *
      [2.5.2.11] listSplit *
    [2.5.3] Set manipulation functions
      [2.5.3.1] IsInSet
      [2.5.3.2] AddToSet
      [2.5.3.3] RemoveFromSet
    [2.5.4] Alias/event manipulation functions
      [2.5.4.1] AliasExists
      [2.5.4.2] EventExists
      [2.5.4.3] IsEventEnabled
    [2.5.5] Formatted text output functions
      [2.5.5.1] Bitmap *
    [2.5.6] Time and clock functions
      [2.5.6.1] CTime
      [2.5.6.2] Date
      [2.5.6.3] DecodeInterval
      [2.5.6.4] DecodePingInterval
      [2.5.6.5] IdleMTime
      [2.5.6.6] IdleTime
      [2.5.6.7] MTime
      [2.5.6.8] Time
      [2.5.6.9] TimeConnected
      [2.5.6.10] UnixTime
    [2.5.7] File I/O functions
      [2.5.7.1] FileExists
      [2.5.7.2] GetCurrentDir
      [2.5.7.3] GetFileDateTime
      [2.5.7.4] GetFileSize
      [2.5.7.5] GetLinesInFile
      [2.5.7.6] GetPath
      [2.5.7.7] PathExists
      [2.5.7.8] RandomRead
      [2.5.7.9] ReadLine
    [2.5.8] Registry I/O functions
      [2.5.8.1] ReadRegistry
      [2.5.8.2] GetSetting
    [2.5.9] Common dialogs
      [2.5.9.1] OpenDialog
      [2.5.9.2] OpenPictureDialog *
      [2.5.9.3] SaveDialog
      [2.5.9.4] SavePictureDialog *
    [2.5.10] IRC-specific functions
      [2.5.10.1] ActiveWindow
      [2.5.10.2] ChannelCount
      [2.5.10.3] Channels
      [2.5.10.4] ChannelList *
      [2.5.10.5] CurrentServer_ActiveWindow
      [2.5.10.6] GetAddress
      [2.5.10.7] GetBanLevel
      [2.5.10.8] GetCustomLevel *
      [2.5.10.9] GetLag
      [2.5.10.10] GetUser
      [2.5.10.11] GetUserLevel
      [2.5.10.12] GetProtLevel
      [2.5.10.13] IsDCCChatting
      [2.5.10.14] IsOn
      [2.5.10.15] IsOp
      [2.5.10.16] IsQuerying
      [2.5.10.17] IsVoice *
      [2.5.10.18] IsWatchdogActive
      [2.5.10.19] Nicks
      [2.5.10.20] NickCount
      [2.5.10.21] NickList *
      [2.5.10.22] Ops
      [2.5.10.23] OpCount
      [2.5.10.24] OpList *
      [2.5.10.25] OpStrip
      [2.5.10.26] Peons
      [2.5.10.27] PeonCount
      [2.5.10.28] PeonList *
      [2.5.10.29] QueryList *
      [2.5.10.30] SelectedNick
      [2.5.10.31] VoiceList *
    [2.5.11] XDCC (file offer server) functions
      [2.5.11.1] GetXDCCPackCount
      [2.5.11.2] GetXDCCPackDesc
      [2.5.11.3] GetXDCCPackFileCount
      [2.5.11.4] GetXDCCPackFiles
      [2.5.11.5] GetXDCCPackGets
      [2.5.11.6] GetXDCCPackSize
    [2.5.12] DCC (chat and file transfer) functions
      [2.5.12.1] DCCChatList *
      [2.5.12.2] DCCGetList *
      [2.5.12.3] DCCSendList *
      [2.5.12.4] GetDCCSize *
      [2.5.12.5] GetDCCSpeed *
      [2.5.12.6] GetDCCPercent *
      [2.5.12.7] GetDCCProgress *
      [2.5.12.8] GetDCCTimeLeft *
    [2.5.13] Inter-server communication functions
      [2.5.13.1] CurrentServer *
      [2.5.13.2] ServerCount *
      [2.5.13.3] ServerList *
    [2.5.14] Miscellaneous functions
      [2.5.14.1] $? (text input dialog)
      [2.5.14.2] DecodeIP
      [2.5.14.3] DNS
      [2.5.14.4] EncodeIP
      [2.5.14.5] GetAlias
      [2.5.14.6] GetInputLine
      [2.5.14.7] GetWindowID
      [2.5.14.8] MessageDlg
      [2.5.14.9] Rand

[1.0] Introduction
==================

What is ViRCScript? ViRCScript (from now on abbreviated to VS) is the scripting
language supported by ViRC '97. VS is similar to BASIC, C, VPL, and ircII's
scripting language. You use VS to write code for events and aliases. In 1.00rc1,
the ViRCScript interpreter is around 99% complete. Newer versions will add more
functionality, however, I will endeavour to ensure that these new changes don't
break your old code.

VS is 100% written by myself. I've used no code from anywhere else or custom
controls in my parser, numerical evaluator, or anything else. This means that
if you have any problems, you have no-one to blame them on but me. >:-> (That
said, no-one has reported any real problems in ViRCScript. It seems to be the
most stable portion of V97 I've written so far).

[1.1] What's new in this release of ViRCScript?
-----------------------------------------------

Note that this list also includes the stuff new in 0.80, 0.82 and 0.82a.

The ^^ (raise to a power) operator now works properly. Deleting array variables
with a variable as the index (e.g. -@ $array.$x) now works properly
(finally!! ;). Added C-style += and -= operators. Added date/time formatting
capabilities to the TIME function. Corrected some documentation inaccuracies
(e.g. the built-in variables, and in the sample code for the IDLETIME
function). New built-in <OnNewInactiveText> event. New BEEP command. New
OPENDIALOG and SAVEDIALOG functions to encapsulate the common dialogs. Fixed
bugs where pseudovariables could be lost after TextOut and Yield statements.
New built-in DCC events (<OnDCCChatConnect>, <OnDCCChatText>,
<OnDCCChatDisconnect>). Minor performance improvements. HALT statement now
breaks out of all loops correctly (previous versions had problems with breaking
out of nested code blocks). MIN, MAX, RESTORE, CLOSE, SETFOCUS window-handling
functions. New file I/O stuff (READLINE, GETLINESINFILE commands). Directory
I/O stuff (MKDIR, CHDIR, RMDIR commands, GETCURRENTDIR function). UNALIAS and
UNEVENT commands added. ObjectViRCScript extensions added (see OBJECTVS.TXT).
New MESSAGEDLG function added.

New in 0.82: SIMULATESERVERDATA command. New OPTIMIZED keyword for FOR and
WHILE statements. New set-handling functions (ADDTOSET, REMOVEFROMSET and
ISINSET). New ALIASEXISTS and EVENTEXISTS functions. New GETUSER function.
Documented event templates (they were implemented in 0.80, but were documented
only in 0.82). Severely-broken BREAK command fixed. CONTINUE command added.
Conditional execution parameters added to BREAK and HALT commands (and CONTINUE
too). Corrected documentation inaccuracies (e.g. the code sample given in the
local variables section (the LOCALTEST and LOCALLOOP aliases) did not work at
all ;). New OPSTRIP and SELECTEDNICK functions.

New in 0.82a: Buggy string comparisons with == fixed. WILDMATCH function
improved to handle a*c-style wildcards. New === (exactly equals) operator
added.

New in 0.91: Completely rewritten parser - should now be around 5x faster.
However, there is a _VERY_ small chance that some of your old scripts
(especially if they are badly written) will break. If this occurs let me know
and I'll see what I can do. New modulus (%) operator added. New WORDCOUNT
function. New SETALIAS command to set the contents of an alias from a variable.
Corresponding new GETALIAS function. New READREGISTRY function and
WRITEREGISTRY command. New GETXDCCPACKCOUNT, GETXDCCPACKSIZE, GETXDCCPACKGETS,
GETXDCCPACKDESC, GETXDCCPACKFILES, and GETXDCCPACKFILECOUNT functions. New
GETWINDOWID function. New UNIXTIME function. New DECODEIP function. Added
bitwise XOR operator (^) to be compatible with C. Old && and || operators were
really bitwise and not comparative, and so failed sometimes, so I made them
comparative and added the bitwise & and | operators which correspond to the old
&& and ||. VS now supports an indentical lot of operators to C. New GETFILESIZE
and GETFILEDATETIME functions. Local array variables now supported. Made !=
case-insensitive and made new !== operator for case-sensitive comparisons. New
DISABLEEVENT and ENABLEEVENT commands. New PATHEXISTS function. New
ISEVENTENABLED function.

New in 0.92: Rewritten script loading code - large scripts now load in 5
seconds, rather than 5 minutes. Added new STRPOSFROM function. New
EVALUATEWINDOW command for debugging. New STRTOKL and STRTOKR functions. RMFILE
(added ages ago) finally documented. New RSTRPOS, RSTRTOKL and RSTRTOKR
functions. New NOATTRIBS command. EVAL command can now be called as a function.

New in 0.92b: DNS function added to perform a DNS lookup.

New in 0.94pre8: ISNUMERIC function added. SWITCH statement added. TCL-like
lists added. FOREACH statement added. New LISTREMOVE TCL-like list function.
Added CASE ELSE to SWITCH statement.

New in 0.94pre10c: New LISTINDEXOF TCL-like list function. New CANCELDCC and
ACCEPTDCC statements. Many problems with SWITCH/CASE statements fixed.

New in 1.00rc1: New \k attribute code for doing mIRC colours easily. Documented
assignment of variables within variables.

New in 1.00rc4: Added OPENPICTUREDIALOG and SAVEPICTUREDIALOG functions.

New in 1.00rc5: Greatly extended functionality of SWITCH/CASE. Added bitshift
operators (<< and >>).

New in 1.00rc5b: The GETFILESIZE function now returns -1 if the file doesn't
exist or cannot be accessed, instead of 0.

New in 1.00rc6: Added new DCCCHATLIST, DCCGETLIST, DCCSENDLIST, GETDCCSIZE,
GETDCCSPEED, GETDCCPROGRESS, GETDCCPOSITION and GETDCCTIMELEFT functions.
ACCEPTDCC command now accepts a filename as a parameter.

New in 1.00rc6b: Added new ONSERVER command and SERVERLIST, SERVERCOUNT and
CURRENTSERVER function. Added new \o and \r attributes. Added support for
query window popups (MT_QueryTextPopup) and corrected a number of documentation
inaccuracies in VSCRIPT.TXT (including documentation errors in the MenuTree and
MenuItem statements).

New in 1.00almost-final2: Added new GETCUSTOMLEVEL function. ISVOICE and
VOICELIST functions and the USERADD command are now documented.

New in 1.00almost-final3b: Added new ADDTOIAL command. Added new USERDELETE and
USERDELETEBYMASK commands.

[1.2] Syntax
------------

Place one VS instruction on each line. Lines beginning with # or // are assumed
to be comments, and are ignored. Otherwise the line is parsed and executed.
Statements and functions are case-insensitive, except for variables, which are
case-sensitive, i.e. $x is not the same as $X. Numerical parameters to
functions can be supplied in decimal, or in hex by prefixing with a $. For
example, to get a random number between 0 and 254, you could use:

        $rand(255)

    Or:

        $rand($FF)

[1.3] Variables
---------------

Variables are allocated and assigned with the @ operator, and deallocated with
the -@ operator. Examples:

        @ $x = Hello everybody!!
        -@ $x

Wildcards are supported when using -@, and this is very useful with arrays.
Say, for example, you defined the following array:

        @ $greeting.0 = Hello
        @ $greeting.1 = Hi
        @ $greeting.2 = Yo
        @ $greeting.3 = Greetings
        @ $greeting.4 = Howdy

You could delete the whole thing in one go with the single statement:

        -@ $greeting.*

Or, as the array element numbers are only 1 figure long:

        -@ $greeting.?

You should always deallocate used variables at the end of your scripts, as
"dangling" variables will make script parsing slower and take up memory.

In addition, ViRC '97 0.34 and above support stored variables. These are like
regular variables, except their values are stored in the registry, and hence
are retained if V97 is closed down and then restarted. Define a stored
variable exactly like a regular variable, except use @s instead of @. Undefine
a stored variable by using -@s instead of -@. For example:

        @s $script_ver = YTooLZ for ViRC '97 version 4.91

The value of $script_ver will not be lost when V97 is closed down.

The third type of variable (new in V96 0.80) is the local variable. This type
of variable is the recommended type to use inside your aliases and events.
Local variables are only accessible from the scope that they were created in.
In addition, you can have more than one local variable with the same name,
provided they are in different scope blocks. ViRC '97's garbage collector
automatically deallocates local variables when they fall out of scope - you
cannot deallocate them yourself. Local variables are created with @l instead of
@. V96 0.91 and above support local array variables, too. Simple example:

        @l $x = hello

Here's a good example of where global (@) variables will not work, and you have
to use locals. Just type /localtest, and observe the (correct, expected)
output:

Alias LOCALTEST
  for (@l $i = 0; $i < 10; $i++)
    TextOut > . clBlue Variable $$i in LOCALTEST: $i
    LocalLoop
  endfor
EndAlias

Alias LOCALLOOP
  for (@l $i = 0; $i < 10; $i++)
    TextOut > . clBlue Variable $$i in LOCALLOOP: $i
  endfor
EndAlias

This code will work correctly, despite the fact that two local variables called
$i are used at the same time, as they are defined as local (@l) variables. If
the @l was changed to @ to make them global variables, typing /localtest would
produce incorrect output as the $i defined in LOCALTEST would be accessible in
LOCALLOOP.

Bear in mind speed considerations when using the different types of variables.
Local variables (e.g. @l $x = 0) are the fastest. Global variables (e.g.
@ $x = 0) are almost, but not quite, as fast as local variables. Local array
variables (e.g. @l $x.0 = 0) and global array variables (e.g. @ $x.0 = 0) are
much slower, so don't use them heavily in tight loops! (that said, they're not
_that_ slow ... even a slow PC should have no problem executing several
thousand complex array operations every second).

You can evaluate a numeric expression by enclosing it in $( and ). For example:

        @ $x = $(1+1)

As opposed to @ $x = 1+1, which will assign the string "1+1" to the variable
$x, and so _WILL_NOT_WORK_.

You can evaluate expressions as complex as you want, including variables and
functions, for example:

        @ $x = $((((16/2)*$strpos(xt $3-))+(18/$dfactor))-1)

$() is not required in if/while/for statements, as the conditions are evaluated
numerically anyway.

In addition, V96 0.60 and above support the C-style ++ and -- operators. What's
more, they're not just a pretty face - they execute a LOT, LOT faster than the
equivalent code @ $i = $($i + 1), and are ideal for loops and things. For
example, to increment $x by one, you could use:

        $x++

Please note that, unlike variable assignments, you DO NOT prefix this with an
@. V96 0.80 and above support the C-style += and -= operators (BUT NOT *= and
/= etc. yet), e.g.

        $x += 4
        $y -= 16

Again, these are much faster than the equivalent @ $x = $($x + 4) etc.
ViRCScript doesn't care about spacing when using any of these operators.

Pseudovariables (Pvars) are also supported in aliases and events. A typical
Pvar looks like $0, or $7-, and represents a parameter supplied to the alias or
event. $n means the n'th parameter. With events, the first word of the line of
text received from the server is $0, the second word $1, and so on. With
aliases, the alias command is $0, the first parameter supplied is $1, the
second parameter supplied is $2, and so on. In addition, an expression like
$2- means "the second parameter and all subsequent parameters". So, $2- is
equal to $2 $3 $4 $5 $6 $7 $8 .... $n. More about this later.

V97 also maintains a number of built-in variables. These are as follows:

        $ver    The current version of V97, e.g. 0.60
        $build  The current version V97 in integer form, e.g. 60
        $N      Your nickname
        $U      Your username
        $H      Your hostname
        $ip     Your IP address
        $server The server you're connected to
        $C      The channel the user types the alias in. If the alias
                is typed in a server window, $C is set to . (a period).
                If the alias is typed in a query window, $C contains the
                nick of the person you are querying.
        $null   Equals nothing. Use to set variables to nothing, e.g.
                @ $x = $null

A number of constants are also maintained:

        \b      Bold
        \u      Underline
        \i      Italic
        \o      Clear bold, underline and italic attributes (does NOT clear
                mIRC colour and reverse video)
        \r      Reverse video (interchange background and foreground colours
                of text)
        \k      mIRC colour (format is \kFOREGROUND,BACKGROUND, e.g. \k1,9 is
                black text on a yellow background)
        \A      ASCII character 1 -  (used for CTCPs), also used for web
                hyperlinks (e.g. \Ahttp://click-here.com\A)
        \t      Tab character (a certain number of spaces, as set in Client
                setup/ViRC '97 options/Text output settings)

Note that V97 supports a number of simultaneous server connections, even if
you're on the same channel on both servers!! And you can have a different
nickname on each server. So what nickname does $N correspond to? The answer is,
the active context's nickname. If you use $N from an event, $N is the nickname
on the server which caused the event. $N in an alias refers to the nickname of
the current server connection relating to the window you typed the alias in.
For example, $N in a channel window would be your nick on the server that
you're on that channel on. Sounds confusing? Just use $N and it should work as
you expect it to every time. =]

What about $+ you may ask. As most of you know, in mIRC, PIRCH etc. you need
$+ to trim spaces ... in other words, you'd need something like this:

        *** $nick ( $+ $user $+ @ $+ $host $+ ) has joined channel $3

To display this:

        *** MeGALiTH (megalith@jimc.demon.co.uk) has joined channel #quake

In V97, spaces are not required before variables and functions, because of its
intelligent parser. So you could do something like this, which looks much
neater:

        *** $nick ($user@$host) has joined channel $3

The above would totally foul up mIRC and PIRCH. In fact, V97 doesn't care what
you have before or after a variable. This would work:

        alkjdsjkadjka$nickjhdakajsdakjdhkjadhk

So, the skeptic asks, in this case, how does V97 know whether you want the
variable $nick, $nickj, $nickjhdak, or what? The answer is, it reads your mind.
Well, almost ... the new parser takes care of it in a different, and rather
more complex way, than the old one ... but it should work properly every time.

[1.4] Variables within variables
--------------------------------

In V96 0.91 and later, VS supports variables within variables. This is achieved
with the new $'$var' syntax. It's best demonstrated as follows:

        @ $blah = hello
        @ $foo = blah

        TextOut > . clBlue $'$foo'

This will print hello on the screen. $'$foo' basically means "the value of the
variable whose name is the value of $foo". So $'$foo' means the value of
the variable whose name is $blah, which is hello.

You can also assign variables within variables in a similar way. For example:

        @ $blah = hello
        @ $'$blah' = goodbye

This would assign goodbye to the variable $hello.

If this doesn't make any sense, email me and let me know!!

[2.0] ViRCScript language reference
===================================

[2.1] Flow control statements
-----------------------------

[2.1.1] If/Else/EndIf statements
--------------------------------

Usage: if (condition)
          ...
       [else]
          [...]
       endif

Executes a block of code only if a given condition is true. Multiple conditions
can be specified, and are separated with && (boolean AND) or || (boolean OR)
operators. If the condition is false and an ELSE block exists, this code is
executed. The following operators are supported:

        Op  | Meaning
      ------+--------------------------
        ==  | Equal to (case-insensitive)
        === | Equal to (same as == only case-sensitive when comparing strings)
        !=  | Not equal to (case-insensitive)
        !== | Not equal to (case-sensitive)
        >   | Greater than
        <   | Less than
        >=  | Greater than or equal to
        <=  | Less than or equal to
        &&  | Boolean AND
        ||  | Boolean OR
        !   | Boolean NOT
        +   | Plus
        -   | Minus
        *   | Multiply
        /   | Divide
        %   | Modulus (remainder after division)
        ^^  | Power
        &   | Bitwise AND
        |   | Bitwise OR
        ^   | Bitwise XOR
        <<  | Bitshift left
        >>  | Bitshift right

If you're used to C, you'll have no problems. Expressions can be as simple or
as complex as you like - you can nest many levels of brackets if you need to.

IF can be used to compare numeric expressions or string expressions. All string
expressions must be enclosed in []'s, just as in ircII.

Numeric expression example:

        if (2+3 == 5)
           TextOut clBlue Of course it does!!
        endif

String expression example:

        if ([hello] == [goodbye])
           TextOut clBlue Not unless the laws of physics have changed.
        endif

Boolean operators may also be used. && = and, || = or, ! = not.

        if (2+3 == 5) && (4*2 == 8)
           TextOut clBlue Naturally.
        endif

In fact, you'll rarely have to use the ! operator. You'll see that the
following two statements are equivalent:

        if ([$x] != [$y])
        if !([$x] == [$y])

Note that spaces are not required (they are ignored by the parser), but may be
included for clarity. For example:

        if (2+3==5)&&(10*17==170)&&((5>=2)||(9==16))

That's perfectly correct, but impossible to read ;). Adding spaces makes the
statement far clearer:

        if (2+3 == 5) && (10*17 == 170) && ((5 >= 2) || (9 == 16))

You must enclose string expressions in []'s. This prevents V97 from trying to
numerically evaluate the text between the [ and the ]. For example:

        if ([$nick] == [hello])
           TextOut clBlue Blah!!
        endif

An ELSE construction is supported too.

        @ $x = $?="What does IRC stand for?"
        if ([$x] == [Internet Relay Chat])
           TextOut clGreen Well done!!
        else
           TextOut clRed Wrong!!
        endif

[2.1.3] ForEach/EndForEach statements
-------------------------------------

Usage: ForEach (variable;list)
         ...
       EndForEach

       ForEach (variable,variable,variable ... ;list)
         ...
       EndForEach

This statement really is every scripter's dream. Basically, it iterates through
every item in list, assigning one or more elements in list to one or more of
the variables specified. If one variable is specified, the code block is
executed for each element (word) in list. If more than one variable is
specified, then elements are assigned sequentually to each variable until all
the variables have been assigned, and then the code block is executed for
each group of elements in list. This sounds rather complex, however, usage is
not that tricky to grasp. It's best illustrated with lots of examples:

        ForEach ($number; 1 2 3 4 5 6 7 8)
          TextOut > . clBlack $number
        EndForEach

This will output the following:

        1
        2
        3
        4
        5
        6
        7
        8

As stated, more than one variable can be supplied, separated by a comma:

        ForEach ($number1, $number2; 1 2 3 4 5 6 7 8)
          TextOut > . clBlack $number1 $number2
        EndForEach

This will output the following:

        1 2
        3 4
        5 6
        7 8

Some more examples of that technique:

        @l $numbers = 1 2 3 4 5 6 7 8
        ForEach ($number1, $number2, $number3; $numbers)
          TextOut > . clBlack $number1
        EndForEach

This will output the following:

        1
        4
        7

Another example:

        ForEach ($number1, $number2, $number3; 1 2 3 4 5 6 7 8)
          TextOut > . clBlack $number1 $number2 $number3
        EndForEach

This will output the following:

        1 2 3
        4 5 6
        7 8

If you'd like to see more examples, or have a better description of the FOREACH
statement that you'd like to share with other VS programmers, feel free to
email me at foreach-request@jimc.demon.co.uk.

[2.1.3] For/EndFor statements
-----------------------------

Usage: for [optimized] (initial statement;condition;increment statement)
         ...
       endfor

V97's for statement behaves exactly like the for statement in C/C++, so you
should have no problems. For example, the following C code:

        for (int i = 0; i < 10; i++)
          printf("%d", i);

Is equivalent to the following ViRCScript code:

        for (@ $i = 0; $i < 10; $i++)
          TextOut clBlue $i
        endfor

(Note the use of the new ++ operator here!!)

Note that variables created by the for statement (e.g. the $i above) are not
deallocated at the end, so the following statement should really be added to
the end of the above code fragment:

        -@ $i

The for and while statements are often interchangable. In fact:

        for (x;y;z)
          ...
        endfor

Is equivalent to:

        x
        while (y)
          ...
          z
        endwhile

However, usage of for is much neater in many cases than while. Note that, just
like C, misuse of for can lock the system up!! Compare the following C
fragment:

        for (;;)
          ...

And the following ViRCScript:

        for (;;)
          ...
        endfor

Both will lock the system up in an infinite loop (unless, of course, a BREAK
or HALT statement is used somewhere in the loop). So be careful!!

In V96 0.82 and above, the new OPTIMIZED keyword is supported. You can use it
like this:

for optimized (@ $i = 1; $i <= 10000; $i++)
  $j++
endfor

OPTIMIZED enables specific optimizations which cause tight loops (containing
only one instruction, in this case $j++) to execute around 20% faster. V97 will
check that the loop contains only one instruction if you specify OPTIMIZED, and
if it does not, the keyword will be ignored.

You can use all regular commands and functions in an OPTIMIZED for loop except
for HALT, BREAK, FALLTHROUGH, YIELD, and TEXTOUT. Usage of these commands in an
OPTIMIZED loop may cause undefined (and possibly erratic) problems.

[2.1.4] Switch/EndSwitch statements
-----------------------------------

Usage: Switch x
         [Case a:]
           [...]
         [Case Expr b]
           [...]
         [Case Is c]
           [...]
         [Case Matches d]
           [...]
         [Case Multi e]
           [...]
         [Case Range f]
           [...]
         [Case Else]
           [...]
       EndSwitch

Executes a block of code if x matches any of the cases given. If x matches none
of the cases given, the code in the CASE ELSE block is executed, if present.
Functionally similar to the switch statement in C. In case code blocks (...),
a special variable, $@, is available, which contains the contents of the
condition being tested against, x. Example:

        @l $num = $?="Enter a number from 1 to 3"
        Switch $num
          Case 1:
            MessageBox You entered the number "one".
          Case 2:
            MessageBox You entered the number "two".
          Case 3:
            MessageBox You entered the number "three".
          Case Else
            MessageBox You didn't enter a number between 1 and 3!!
        EndSwitch

Another example:

        @l $num = $?="Enter YES SIR or NO WAY."
        Switch $num
          Case YES SIR:
            MessageBox You said YES SIR!
          Case NO WAY:
            MessageBox You said NO WAY!
          Case Else
            MessageBox You said $@. I told you to enter YES SIR or NO WAY. :)
        EndSwitch

The CASE statement and the block of code must be on separate lines. Putting
both on one line is invalid and will not work.

New in 1.00rc5 are a number of extended case directives: EXPR, IS, MULTI,
MATCHES, and RANGE. This will be documented separately.

[2.1.4.1] Expr directive
------------------------

Usage: Switch x
         Case Expr a
           ...
       EndSwitch

Executes the code block ... if the expression a is true. Use the special
variable $@ to determine the condition being tested against.

        Switch $?="Enter a number between 10 and 20."
          Case Expr ($@ >= 10) && ($@ <= 20)
            MessageBox You entered $@.
          Case Else
            MessageBox You didn't enter a number between 10 and 20!!
        EndSwitch

[2.1.4.2] Is directive
----------------------

Usage: Switch x
         Case Is a
           ...
       EndSwitch

Executes the code block ... if the partial expression a is true. a is something
like > 10 or < 20. Example:

        Switch $?="Enter a number."
          Case Is > 100:
            MessageBox The number was greater than 100.
          Case Is < 100:
            MessageBox The number was less than 100.
          Case 100:
            MessageBox The number was 100.
        EndSwitch

[2.1.4.3] Matches directive
---------------------------

Usage: Switch x
         Case Matches a
           ...
       EndSwitch

Executes the code block ... if x is matched by a, which may contain wildcard
characters (* and ?). Example:

        Switch $?="Enter a word."
          Case Matches *e*
            MessageBox The word contains the letter e.
          Case Else
            MessageBox The word doesn't contain the letter e.
        EndSwitch

[2.1.4.4] Multi directive
-------------------------

Usage: Switch x
         Case Multi a
           ...
         EndSwitch

Executes the code block ... if x is matched by a, which may contain a number of
values, separated by commas. Take this code which does not use the Multi
directive, for example:

        Switch $?="Enter 13, 17, 23 or 31."
          Case 13:
            MessageBox OK.
          Case 17:
            MessageBox OK.
          Case 23:
            MessageBox OK.
          Case 31:
            MessageBox OK.
          Case Else
            MessageBox You didn't enter 13, 17, 23 or 31.
        EndSwitch

However, the above code could be written more efficiently, with the Multi
directive, as follows:

        Switch $?="Enter 13, 17, 23 or 31."
          Case Multi 13,17,23,31
            MessageBox OK.
          Case Else
            MessageBox You didn't enter 13, 17, 23 or 31.
        EndSwitch

[2.1.4.5] Range directive
-------------------------

Usage: Switch x
         Case Range a..b
           ...
       EndSwitch

Executes the code block ... if x lies in the numeric range from a to b
(inclusive). Example:

        Switch $?="Enter a number."
          Case Is < 0
            MessageBox The number is negative.
          Case 0..100
            MessageBox The number is between 0 and 100 (inclusive).
          Case Is > 100
            MessageBox The number is greater than 100.
        EndSwitch

[2.1.5] While/EndWhile statements
---------------------------------

Usage: while [optimized] (condition)
         ...
       endwhile

Executes a block of code while condition is true. If condition is false
initially, the while block will be skipped. See the IF/ELSE/ENDIF statement for
details on how to specify conditions. Beware, as a condition that's always true
will produce an infinite loop and will lock V97 up!! For example:

        while (1)
        endwhile

In fact, now ViRCScript has a C-like for statement, while is largely
superflous. In fact:

        while (condition)
          ...
        endwhile

Is functionally-identical to:

        for (;condition;)
          ...
        endfor

The for statement is used only with a condition, with no initial statement and
no increment statement.

In V96 0.82 and above, the new OPTIMIZED keyword is supported. You can use it
like this:

while optimized ($i <= 10000)
  $i++
endwhile

OPTIMIZED enables specific optimizations which cause tight loops (containing
only one instruction, in this case $j++) to execute around 20% faster. V97 will
check that the loop contains only one instruction if you specify OPTIMIZED, and
if it does not, the keyword will be ignored.

You can use all regular commands and functions in an OPTIMIZED while loop
except for HALT, BREAK, CONTINUE, FALLTHROUGH, YIELD, and TEXTOUT. Usage of
these commands in an OPTIMIZED loop may cause undefined (and possibly erratic)
problems.

[2.2] Alias/event/menu definition statements
--------------------------------------------

[2.2.1] Alias/EndAlias statements
---------------------------------

Usage: Alias <name> [hotkey]
         ...
       EndAlias

Defines an alias (similar to a procedure or function in other languages).
The parameters of the alias are passed in as $1, $2, $3 and so on, and the
actual alias command itself is passed in as $0. The channel window the alias is
typed in is passed in as $C. $C is set to . if the alias is run from the server
notices window. Optionally, hotkey may be specifed (e.g. F3, or Ctrl+Shift+Z).
When hotkey is pressed, the alias will be executed as if it were typed in the
current window.

It's recommended that, to begin with, you try making some aliases in ViRC '97's
alias editor (Scripting/Aliases ...), as this saves having to make text files
and then using /load to load them in. Of course, when making an alias with
V97's alias editor, you DON'T include the Alias and EndAlias lines, as the name
and hotkey for the alias have already been entered manually.

Aliases can be very useful, for example, consider this:

        Alias GO
          Connect
          Join #quake
          Msg Bot !op
          Mode #quake +ooo User1 User2 User3
          Part #quake
          Quit
        EndAlias

When the user types /go, V97 will connect to the server, join #quake, /msg Bot
for ops, op User1, User2 and User3, leave #quake, and quit IRC. Aliases can
also be used as functions. Simply assign a value to $fresult as the value of
the function. For example, consider this, a function to pick and return a
random boolean value, either True or False:

        Alias RANDBOOL
          @ $x = $rand(2)
          if ($x == 1)
             @ $fresult = True
          else
             @ $fresult = False
          endif
        EndAlias

Now:

        TextOut clBlue Random boolean expression: $randbool()

In V96 0.91 and above, if an alias, which is called as a function, doesn't
assign a value to $fresult, it will automatically return the string <no value>,
for example:

        TextOut clBlue $nonexistentfunction()

This will output the string:

        <no value>

Notice that, in 1.00rc5 and above, an alias can tell if it's being executed as
a command or called as a function. The name of the alias is always available
as $0, but if the alias is called as a function, $0 is prefixed by a %
character. So, you can have code like this to check if an alias is being called
as a function or not:

        if ([$substr($0 1 1)] == [%])
           // Called as a function (for example, $0 = %TEST) ...
        else
           // Called as a command (for example, $0 = TEST) ...
        endif

Another use for aliases is executing frequently-used single commands. For
example, say you're on #quake, and are frequently asked what the current
version of Quake is. You could make an alias like this:

        Alias QUAKEVER
          Say $C $1: The current version of Quake is 1.01.
        EndAlias

Then, for example, if Dnormlguy asked what the latest version of Quake was,
in the #quake channel window, you could just type /quakever Dnormlguy. V97
would expand $C to #quake, and $1 to the first parameter, Dnormlguy. So, the
text "Dnormlguy: The current version of Quake is 0.92" to the channel.

Newer versions of V97 (after about 0.90) don't need the $C at all, so the above
alias could be rewritten simply as:

        Alias QUAKEVER
          Say $1: The current version of Quake is 1.01.
        EndAlias

[2.2.2] Event/EndEvent statements (read!! This is changed!!)
------------------------------------------------------------

Usage: Event <name> "<mask>"
         ...
       EndEvent

Defines an event. Events are the most powerful feature of VS, although also the
hardest to grasp (although this has largely been alleviated now that event
priorities have been removed). The best way to get a feel for events is to look
through V97's built-in events and see how they work.

It's recommended that, to begin with, you try making some events in ViRC '97's
event editor (Scripting/Events ...), as this saves having to make text files
and then using /load to load them in. Of course, when making an event with
V97's event editor, you DON'T include the Event and EndEvent lines, as the name
and mask for the event have already been entered manually.

Name is just an arbitrary name to assign to the event. You can call events
anything you like. Mask is the text that must be received from the server to
trigger the event, and can include wildcards.

Parameters are passed into the event with the first word received from the
server as $0, the second word as $1, etc. In addition, the sender of the
message's nick is stored in $nick, the username in $user, and the hostname
in $host. If the message originates from the server, $nick is the server, and
$user and $host are empty. Example:

        :greygoon!bhess@wilma.widomaker.com NOTICE MeGALiTH :You're not opped!!

This is what the server sends when greygoon sends the notice
"You're not opped!!" to MeGALiTH. So, the parameter breakdown would be as
follows:

        $0      :greygoon!bhess@wilma.widomaker.com
        $1      NOTICE
        $2      MeGALiTH
        $3      :You're
        $4      not
        $5      opped!!

        $nick   greygoon
        $user   bhess
        $host   wilma.widomaker.com

Thus the activation mask for a NOTICE is "* NOTICE *". This basically means:
$0 can be anything, $1 must be NOTICE, and $2 can be anything. Any parameters
that are not supplied can be anything - in fact, the * at the end of the mask
is not really necessary, but is included for clarity.

More specific masks are executed in preference to less specific masks. For
example, the following event statements are used for private and channel
messages.

        Private messages:

           Event PrivateMessage "* PRIVMSG *"

        Channel messages:

           Event ChannelMessage "* PRIVMSG #*"

A typical private message received from the server may look like this:

        :nick!user@host PRIVMSG YourNick :hello!!

A typical channel message might look like this:

        :nick!user@host PRIVMSG #quake :hello all!!

Therefore, if V97 gets a channel message, the PrivateMessage event is NOT
executed, even though the mask matches, because there's a more specific event
mask that matches, namely ChannelMessage.

Note that the <default> event (mask *), which is fired for every line of server
text that is received, is only executed if NO OTHER EVENTS have a mask which
matches the line of server text.

In 0.80 and above, event templates are supported. This means that you can use
masks from other events as templates for your own masks, which makes the
events clearer. You use another event mask as a template by putting the name
of the event in ()'s at the beginning of your own mask. For example, the CTCP
event mask is as follows:

        * PRIVMSG * :\A*

Therefore, if you wanted to make an event that responded to CTCP HELLO, you
could do:

        Event CTCPHello "(CTCP)HELLO"

V97 would expand the mask (CTCP)HELLO to ...

        * PRIVMSG * :\A*HELLO

... which is the correct mask to do what you want. In addition, if you wish to
redefine an event without changing the mask, you could always use the event
mask itself as a mask template, for example:

        Event PrivateMessage "(PrivateMessage)"
          ... code for new PrivateMessage event ...
        EndEvent

Events that begin with < (with the exception of <default>) are NEVER fired by
events from the server, even if the masks match. You can thus create your own
<On_xxx> events which you can fire manually from code with the FIREEVENT
command.

Built-in events
---------------

V97 has a number of built-in events. They are:

        <OnConnect> - fired when connected to a server
                      $0 = server name

        <OnDisconnect> - fired when disconnected from a server
                         $0 = server name

        <OnErrorConnecting> - fired when a socket error occurs while connecting
                              to a server (for example, connection refused)
                              $0 = error number, $1- = error message

        <OnNotifyJoin> - fired when a user in the notify list joins IRC
                         $0 = nick of user who joined

        <OnNotifyQuit> - fired when a user in the notify list leaves IRC
                         $0 = nick of user who left

        <OnNewInactiveText> - fired when next is added to an inactive window
                              $0 = 1 if first new line, 0 for subsequent lines
                              $1 = window type (SERVER, CHANNEL, QUERY, or DCC)
                              $2 = window name (e.g. #quake, MeGALiTH, etc).

        <OnDCCChatConnect> - fired when a DCC Chat session connects
                             $0 = nick of user who chat connection is with

        <OnDCCChatDisconnect> - fired when a DCC Chat session disconnects
                                $0 = nick of user who chat connection is with

        <OnDCCSendConnect> - fired when a DCC Send session connects
                             $0 = nick of user you're sending the file to
                             $1 = filename of file you're sending

        <OnDCCSendDisconnect> - fired when a DCC Send session disconnects
                                $0 = nick of user you're sending the file to
                                $1 = filename of file you're sending
                                $2 = 1 if transfer complete, 0 if transfer aborted

        <OnDCCGetConnect> - fired when a DCC Send session connects
                            $0 = nick of user you're getting the file from
                            $1 = filename of file you're receiving

        <OnDCCGetDisconnect> - fired when a DCC Send session disconnects
                               $0 = nick of user you're getting the file from
                               $1 = filename of file you're receiving
                               $2 = 1 if transfer complete, 0 if transfer aborted

        <OnAcceptDCCQuery> - fired before an incoming DCC connection is accepted
                             $nick, $user, $host, $dcctype, $dccfile, $dccip,
                             $dccport and $dccsize are available here, which
                             describe the incoming DCC connection. In this
                             event, you may execute the AcceptDCC command,
                             which accepts the DCC connection without any
                             confirmation from the user, or the CancelDCC
                             command, which will cancel the DCC connection
                             without any confirmation from the user.

        <OnStart>            - fired when ViRC '97 starts up

        <OnClose>            - fired when ViRC '97 closes down

IMPORTANT NOTE: In 0.82 and later versions of V97, you can define multiple,
individual events for each of the above. This is done by calling the events
<OnXXXX_text>. For example, if you wanted several <OnStart> events, you could
define them as <OnStart_1>, <OnStart_2> etc., and they would each be called
correctly. If you are defining these events in a script, it is STRONGLY
RECOMMENDED that you give these events a unique name, so that it doesn't
interfere with the operation of any other scripts, for example, you could call
an event <OnStart_XYZScript> or <OnDCCGetConnect_XYZScript> if you're writing
a script called XYZScript.

Event names in <>'s (e.g. <OnXYZ>) will never be fired by text received from
the server, even if the masks match. If they're not built-in events, like
<OnStart>, you will have to call them manually with the FIREEVENT command.

[2.2.3] MenuTree/EndMenuTree command
------------------------------------

Usage: MenuTree menutype
         [item1]
         [item2]
         ...
       EndMenuTree

Defines the menu tree for menutype. This command is used to define the
structure of a menu or popup, before code is assigned to each item. The
following values for menutype are currently recognized:

     MT_MainMenu          - define the tree for the main menu
     MT_ServerPopup       - define the tree for the server window popup
     MT_ChannelTextPopup  - define the tree for the channel window text pane
                            popup
     MT_ChannelNicksPopup - define the tree for the channel window names pane
                            popup
     MT_QueryTextPopup    - define the tree for the query window text pane
                            popup

Each item defined between MenuTree and EndMenuTree takes the following format:

     ItemName HotKey State Depth Text

ItemName is an arbitrary name to give to the menu item. The name will be used
again later to define the code when you click on the menu item. HotKey defines
what hotkey to activate the menu item on. HotKey can be something like F12 or
Ctrl+Shift+A, or <none> if you don't require a hotkey. Note that HotKey is
ignored for menus other than MT_MainMenu. State determines the menu item's
state. For menu types MT_MainMenu and MT_ServerPopup, State can take the
following values:

        0 - Menu item is enabled
        1 - Menu item is enabled when you're connected to the server, and
            disabled otherwise
        2 - Menu item is disabled when you're connected to the server, and
            enabled otherwise
        3 - Menu item is disabled

For menu types MT_ChannelTextPopup and MT_ChannelNicksPopup, State can take the
following values:

        0 - Menu item is enabled
        1 - Menu item is enabled when you're opped on this channel, and
            disabled otherwise
        2 - Menu item is disabled when you're opped on this channel, and
            enabled otherwise
        3 - Menu item is disabled

For menu type MT_QueryTextPopup, State can take the following values:

        0 - Menu item is enabled
        3 - Menu item is disabled

Depth defines the "depth" of the menu item. For MT_MainMenu, a depth of 0
represents an entry on the top menu bar. A depth of 1 is a subitem of the
closest item above which has a depth of 0. A depth of 2 is a subitem of the
closest item above that has a depth of 1. In V97 1.00af3 and above, depths of
3 and 4 are also supported, and these are simply subitems of the nearest items
above that have a depth of 2 and 3 respectively.

Text is the actual text to display on the menu. If an & is present in Text,
you can pull the menu down quickly by pressing Alt and the letter after the &.

Here are some example menu tree items, taken from DEFAULT.LIB:

  M_FILE       <none> 0 0 &File
  M_NEWCONNECT Ctrl+K 0 1 &New connection ...
  M_SETUP      <none> 0 1 Client s&etup ...
  M_FSEP1      <none> 0 1 -
  M_EXIT       Alt+X  0 1 E&xit
  M_TOOLS      <none> 0 0 &Tools
  M_FINGER     Ctrl+F 0 1 UNIX &finger ...

Hopefully by comparing this with what you actually see in the program will
enable you to understand the significance of each field.

After defining your menu trees, it is crucial to include an UpdateMenus
command to make V97 actually update the menus on-screen.

[2.2.4] MenuItem/EndMenuItem command
------------------------------------

Usage: MenuItem ItemName on MenuType

Defines the ViRCScript code to trigger when the user clicks on the menu item
ItemName on the menu type MenuType. MenuType can take the same values here as
with the MenuTree command detailed above. In the above example, one of the item
lines between MenuTree and EndMenuTree is:

  M_NEWCONNECT Ctrl+K 0 1 &New connection ...

To define the ViRCScript code to actually make this open a new server window,
you would use:

        MenuItem M_NEWCONNECT on MT_MainMenu
          NewServerWindow
        EndMenuItem

For a good example of how this works, see DEFAULT.LIB.

Menu items on a MenuType of MT_ChannelTextPopup and MT_ChannelNicksPopup are
supplied with the current channel window as $C.

Menu items on a MenuType of MT_ChannelNicksPopup are supplied with the nickname
selected in the names pane of the currently-active channel window as the
parameter $nick (and also as $1). If more than one nick is selected, the first
nick selected is available as $nick (and also as $1), the second nick selected
is available as $2, the third is available as $3, and so forth. For example:

        MenuItem M_HELLO on MT_ChannelNicksPopup
          Say Hello, $nick!!
        EndMenuItem

If the user clicks on abc123's nick in a channel window, and then right-clicks
and selects M_HELLO from the popup menu, the text "Hello, abc123!!" will be
said to the channel.

        MenuItem M_DEMO1 on MT_ChannelNicksPopup
          Say The following nicks are selected: $1-
        EndMenuItem

This example will say what nicks are selected to the channel.

Menu items on a MenuType of MT_QueryTextPopup are supplied with the nickname
of the person you're querying as $nick.

[2.3] Parsing statements
------------------------

[2.3.1] Parse/EndParse statements
---------------------------------

Note that this feature, although still present and functional (to preserve
compatibility with old scripts), has largely been superceded by the new
list-handling functions, and as such should be considered obsolete.

Usage: Parse [extended] text
        ...
       EndParse

Parses text into the pseudovariables $0 to $9 for the duration of the parse
block. Without doubt one of the most powerful commands in ViRCScript. Its use
is best illustrated by an example:

        @ $x = This is a test.
        Parse $x
          TextOut clBlue $0 $1 $2 $3
          TextOut clBlue $3 $2 $1 $0
        EndParse

The following will appear on the screen:

        This is a test.
        test. a is This

The values of the pseudovariables are restored to their previous state at the
end of the parse block. So, they are only valid between Parse and EndParse.
You must assign them to other variables if you want to use them outside the
parse block. You may nest as many parse blocks within each other as you like.

What in reality could this be used for? One idea is a #chaos-type question
game, You have a file called QUESTION.TXT which contains questions and answers
in the form:

        answer question ...
        answer question ...
        answer question ...

And so on. You want some code to pick a random question from the file, putting
the question in $question and the answer in $answer. The following code would
do the trick:

        @ $x = $randomread(question.txt)
        Parse $x
          @ $answer = $0
          @ $question = $1-
        EndParse

In addition, 0.91 and above support the new EXTENDED keyword. If this keyword
is specified, multiple words surrounded by quotes will be parsed as one
parameter. Example:

        Parse "one two" "three four"
          TextOut > . clBlue 0: $0
          TextOut > . clBlue 1: $1
          TextOut > . clBlue 2: $2
          TextOut > . clBlue 3: $3
        EndParse

        Parse Extended "one two" "three four"
          TextOut > . clBlue 0: $0
          TextOut > . clBlue 1: $1
          TextOut > . clBlue 2: $2
          TextOut > . clBlue 3: $3
        EndParse

The first block of code will display:

        0: "one
        1: two"
        2: "three
        3: four"

The second block of code will display:

        0: "one two"
        1: "three four"
        2:
        3:

The EXTENDED keyword is very useful when you're parsing strings that might
contain multiple filenames, each enclosed in quotes (the filenames may contain
spaces on Win32 systems, remember). For example, the following code snippet
will display each filename in XDCC pack #1 on a separate line:

        Parse Extended $getxdccpackfiles(1)
          for (@l $i = 0; $i < $getxdccpackfilecount(1); $i++)
            TextOut > . clBlack $'$i'
          endfor
        EndParse

[2.4] Commands
--------------

[2.4.1] Formatted text output commands
--------------------------------------

[2.4.1.1] FlushBitmapCache statement
------------------------------------

Usage: FlushBitmapCache

Clears V97's internal text bitmap caches. If you are using your own custom
bitmaps in text output and you change them on disk, you need to execute this
command to reload the bitmaps from disk. More information about when you need
to use this command is given in the description for the Bitmap function.

[2.4.1.2] TextOut statement
---------------------------

Usage: TextOut [> window] <colour> <text ...>

Displays some text in a window. If the window name is left out, TextOut will
output the text to all channel windows, unless there are none open, in which
case the text will be displayed in the server window. Specifying a channel name
will display the text in that channel (or the server window if the channel
doesn't exist). Specifying . will output the text to the server notices window.
Specifying anything else will create a query window with that name (if it
doesn't already exist) and output the text there. You can use a query window
created "on-the-fly" like this as a simple text output window for your scripts.

Colour may be specified in four ways.

        (1) Specifying a colour constant. The following colour constants
            are supported (this will be familiar to Delphi 2.0 users):

            clBlack             Black
            clMaroon            Maroon
            clGreen             Green
            clOlive             Olive green
            clNavy              Navy blue
            clPurple            Purple
            clTeal              Teal
            clGray              Gray
            clSilver            Silver
            clRed               Red
            clLime              Lime green
            clBlue              Blue
            clFuchsia           Fuchsia
            clAqua              Aqua
            clWhite             White

            clBackground        Current color of your Windows background
            clActiveCaption     Current color of the title bar of the active window
            clInactiveCaption   Current color of the title bar of inactive windows
            clMenu              Current background color of menus
            clWindow            Current background color of windows
            clWindowFrame       Current color of window frames
            clMenuText          Current color of text on menus
            clWindowText        Current color of text in windows
            clCaptionText       Current color of the text on the title bar of the active window
            clActiveBorder      Current border color of the active window
            clInactiveBorder    Current border color of inactive windows
            clAppWorkSpace      Current color of the application workspace
            clHighlight         Current background color of selected text
            clHightlightText    Current color of selected text
            clBtnFace           Current color of a button face
            clBtnShadow         Current color of a shadow cast by a button
            clGrayText          Current color of text that is dimmed
            clBtnText           Current color of text on a button
            clInactiveCaptionText   Current color of the text on the title bar of an inactive window
            clBtnHighlight      Current color of the highlighting on a button
            cl3DDkShadow        Windows 95 only: Dark shadow for three-dimensional display elements
            cl3DLight           Windows 95 only: Light color for three-dimensional display elements (for edges facing the light source)
            clInfoText          Windows 95 only: Text color for tooltip controls
            clInfoBk            Windows 95 only: Background color for tooltip controls

            The second half of the colors listed here are Windows system
            colors. The color that appears depends on the color scheme users
            are using for Windows. Users can change these colors using the
            Control Panel in Program Manager. The actual color that appears
            will vary from system to system. For example, the color fuchsia
            may appear more blue on one system than another.

            For example, to output some blue text in the server window:

                TextOut > . clBlue blah blah blah ...

        (2) Specifying an event colour constant. Event colour constants
            correspond to the colour of the corresponding event type the user
            has selected in Client setup/Colours and fonts. This allows scripts
            that you write to automatically adjust to the colours the user
            wants. The following event colour constants are available.

            ecJOIN              Join colour
            ecPART              Part colour
            ecQUIT              Quit colour
            ecTOPIC             Topic change colour
            ecMODE              Mode change colour
            ecKICK              Kick colour
            ecPRIVMSG           Private message colour
            ecNOTICE            Notice colour
            ecCTCP              CTCP colour
            ecACTION            Action colour
            ecNICK              Nick change colour
            ecMyChanText        Colour of channel text the user has entered himself
            ecChanText          Colour of channel text other users have entered
            ecMyQueryText       Colour of query text the user has entered himself
            ecQueryText         Colour of query text other users have entered
            ecServText          Colour of server text
            ecError             Colour of error text
            ecScript or ecXDCC  Colour of script (e.g. XDCC) status messages

            For example:

                TextOut ecKICK This text will appear in the same colour as channel kicks do.

        (3) Specifying a hex RGB value, in the form $bbggrr.


            For example:

                TextOut $0000FF This text is red.
                TextOut $00FF00 This text is green.
                TextOut $FF0000 This text is blue.
                TextOut $00FFFF This text is yellow.
                TextOut $FFFFFF This text is white.
                TextOut $000000 This text is black.

        (4) Specifying a decimal RGB value. This is rather useless, unless
            you're specifying the text colour as a random number, e.g.

                TextOut $rand($FFFFFF) This text appears in a random colour.

New in 0.80, with ObjectViRCScript, you can also specify the handle of a
TRichEdit object you have created (see OBJECTVS.TXT) to output text to that
TRichEdit control. However, in order for TextOut to recognize the handle as
an ObjectViRCScript object handle, it must be preceded with %. Example to
create a form with a TRichEdit on it and write some text to it (BTW, the
@p $edit.Align = 5 line simply makes the TRichEdit automatically fill the form,
so there's no need to specify a size initally by setting the Left, Top etc.
properties. Align = 5 corresponds to Delphi's Align = alClient. You'll be able
to specify the properties by textual name shortly, but for now you'll just have
to fiddle with the numbers until you get the effect you want!!):

@ $form = $new(TForm)
@p $form.Left = 20
@p $form.Top = 20
@p $form.Width = 300
@p $form.Height = 300
@p $form.Visible = 1

@ $edit = $new(TRichEdit ownedby $form)
@p $edit.Align = 5
@p $edit.Visible = 1

TextOut > %$edit clBlue This text will appear in \bblue\b!!
TextOut > %$edit clRed This text will appear in \bred\b!!

[2.4.1.3] TextOutBitmap statement
---------------------------------

Usage: TextOutBitmap [> window] <colour> <bitmap> <text ...>

Displays some text in a window, along with a small bitmap to the left of the
text. Otherwise, exactly the same as the TEXTOUT statement described above.
The bitmap parameter is usually a value returned by the BITMAP function. For
example:

        TextOutBitmap > #virc clBlack $bitmap(_join.bmp) Welcome to #virc!

See the BITMAP function for more information on bitmaps.

[2.4.2] Flow control commands
-----------------------------

[2.4.2.1] Break command
-----------------------

Usage: Break [if condition]

Quits from the currently-executing code block. A code block is something like
the code between if/endif, while/endwhile, parse/endparse etc. If this
statement is executed outside a code block, execution of your script routine
will stop (see the HALT command). If a BREAK statement is encountered inside
a FOR or WHILE loop, control will immediately be transferred out of the loop.

If a condition is specified, the break will only occur if the condition is
met, for example, the following code will print 0, 1, 2, 3 and 4 in the server
window:

        for (@l $i = 0; $i <= 10; $i++)
          Break if ($i == 5)
          TextOut > . clBlue $i
        endfor

[2.4.2.2] Continue command
--------------------------

Usage: Continue [if condition]

Only used within FOR and WHILE blocks, CONTINUE causes the next iteration of
the loop to begin immediately, without finishing the current iteration.

If a condition is specified, the continue will only occur if the condition is
met, for example, the following code will print 0, 1, 2, 3, 4, 6, 7 and 8 in
the server window:

        for (@l $i = 0; $i <= 10; $i++)
          Continue if ($i == 5)
          TextOut > . clBlue $i
        endfor

[2.4.2.4] FallThrough command
-----------------------------

Usage: FallThrough

This powerful command makes event programming much easier. If you've defined a
special event, but you only want it to execute sometimes, and the rest of the
time you want the system to behave as if the event was never defined, you can
use the FallThrough statement to pass the event down to a handler of lower
priority. A good example is if you're writing, for example, a channel
statistics script, which catches WHO replies (* 352 *) and processes them,
without displaying them in the server notices window. However, if the user has
not typed /chanst, then the regular <default> event should be executed to
display the WHO on the screen in the normal way. The event would be defined
like this:

Event ChanStatWHOReply 5 "* 352 *"
  if ($doingchanst)
     ...
  else
     FallThrough
  endif

[2.4.2.3] Halt command
----------------------

Usage: Halt [if condition]

Similar to the BREAK command, only exits from ALL code blocks and terminates
execution of your script. As with BREAK, an optional condition can be
specified, and the HALT will only occur if the condition is met.

[2.4.2.5] Yield command
-----------------------

Usage: Yield

Polls the Windows message queue and processes waiting messages. If you're
writing a script that uses a while loop that takes a long time to execute, it
may be a good idea to use YIELD to prevent the system from locking up while
your script is executing. For example, the following will lock V97 up:

        while (1)
        endwhile

However, the following will not lock V97 up, although it'll slow it down a
little because it is actually executing the while loop over and over again,
ad infinitum:

        while (1)
          Yield
        endwhile

The YIELD command is very useful when implementing background processing.
Adding a YIELD statement to a time-consuming for loop will allow other tasks to
continue running in the background while the for loop executes.

IMPORTANT NOTE!! Things can happen while Yield is executing. Even other VS code
can execute (e.g. if an event occurs during the Yield statement). Therefore,
you CANNOT assume that variables like $C will retain their value after
executing Yield, as another VS code section may have changed them. Therefore,
always save things like $C to your own variables (e.g. $chan) before executing
Yield if you wish to ensure that the variables don't change from underneath
your feet.

[2.4.3] Alias/event/menu control commands
-----------------------------------------

[2.4.3.1] DisableEvent command
------------------------------

Usage: DisableEvent event

Disables event. When an event is disabled, it will never be triggered.

[2.4.3.2] EnableEvent command
-----------------------------

Usage: EnableEvent event

Enables event. Use after DisableEvent to re-enable the event to allow it to be
triggered again.

[2.4.3.3] FireEvent command
---------------------------

Usage: FireEvent event parameters

Fires event with parameters. This can either be used to pretend that an event
was fired by ViRC '97, for example:

        FireEvent <OnConnect>

Or, you can define your own custom events, for example <OnOpNick>, which you
could then fire manually, say, in your MODE event:

        FireEvent <OnOpNick> $C $nick

If no parameters are specified, the event is fired unconditionally. If
parameters are specified, the event is only fired if the event's mask matches
the parameters specified. You may fire a range of events by including a
wildcard, for example:

        FireEvent <OnConnect*

This would fire all events whose names begin with the string <OnConnect.

[2.4.3.4] SetAlias command
--------------------------

Usage: SetAlias alias = text

This is a very powerful command which you will use very seldomly, if at all.
It creates an alias with the ViRCScript code set to text. You can separate
multiple lines of code in text with $char(13). Examples:

        @l $code = TextOut > . clBlue Line 1$char(13)
        @l $code = $codeTextOut > . clBlue Line 2

        SetAlias TEST1 = $code

Together with the GETALIAS function, SETALIAS can be used to append ViRCScript
code to existing aliases. For an example of this usage, see the GETALIAS
function.

[2.4.3.5] UnAlias command
-------------------------

Usage: UnAlias alias [alias ...]

Removes one or more aliases. For example, this removes the 3 aliases OP, DEOP
and J.

        UnAlias OP DEOP J

[2.4.3.6] UnEvent command
-------------------------

Usage: UnEvent event [event ...]

Removes one or more events. For example, this removes the 2 events JOIN and
PART:

        UnEvent JOIN PART

[2.4.3.7] UpdateMenus command
-----------------------------

Usage: updatemenus

Recreates all menus and popups from the in-memory menu trees and writes the
trees to the registry. After you have changed menu(s) with MenuTree and
MenuItem statements, you must use this command for your changes to take effect
properly. Failure to execute this command when you've finished altering the
menus can cause unwanted side-effects, as the in-memory menu trees and the
actual menus and popups become desynchronized from each other.

[2.4.4] Window manipulation commands
------------------------------------

[2.4.4.1] Close command
-----------------------

Usage: Close window

Closes window. window can be . to set the focus to the server notices window,
a channel name, or a nick (query window).

[2.4.4.2] Max command
---------------------

Usage: Max window

Maximizes window. window can be . to set the focus to the server notices
window, a channel name, or a nick (query window).

[2.4.4.3] Min command
---------------------

Usage: Min window

Minimizes window. window can be . to set the focus to the server notices
window, a channel name, or a nick (query window).

[2.4.4.4] Restore command
-------------------------

Usage: Restore window

Restores window. window can be . to set the focus to the server notices window,
a channel name, or a nick (query window).

[2.4.4.5] SetFocus command
--------------------------

Usage: SetFocus window

Sets focus to window. window can be . to set the focus to the server notices
window, a channel name, or a nick (query window).

[2.4.5] File I/O commands
-------------------------

[2.4.5.2] AppendText command
----------------------------

Usage: AppendText "filename" text

Appends text to the end of filename. In V96 0.80 and above, filename will be
created if it doesn't already exist. Putting quotes around filename enables
filenames and paths containing spaces to work correctly.

[2.4.5.1] CreateFile command
----------------------------

Usage: CreateFile filename

Creates filename, or truncates it to 0 bytes if it already exists.

[2.4.5.5] ChDir command
-----------------------

Usage: ChDir dir

Changes to the dir directory.

[2.4.5.4] MkDir command
-----------------------

Usage: MkDir dir

Makes a directory called dir.

[2.4.5.6] RmDir command
-----------------------

Usage: RmDir dir

Removes the dir directory.

[2.4.5.3] RmFile command
------------------------

Usage: RmFile file

Erases file.

[2.4.6] Registry I/O commands
-----------------------------

[2.4.6.1] RehashRegistry command
--------------------------------

Usage: RehashRegistry

Makes V97 reload all its settings from the registry. If you're writing a
program which modifies any of the in-registry settings while V97 is running,
the program should send a RehashRegistry command to V97 via DDE (see
VIRCDDE.TXT) to make V97 reload everything from the registry.

[2.4.6.2] WriteRegistry command
-------------------------------

Usage: WriteRegistry "section" key value

Assigns value to key in the registry under the section "section", located under
the ViRC '97 key (e.g. having a section of "YyzScript" would write to
HKEY_CURRENT_USER\Software\MeGALiTH Software\Visual IRC 96\YyzScript. If key
doesn't exist, it will be created. If key already contains a value, it will
be overwritten by the new value you're setting. You cannot write outside the
ViRC '97 key in the registry. This is a conscious design decision to ensure
maximum security (a buggy or malicious script could go around trashing
system-required registry entries otherwise).

[2.4.7] Sound and multimedia commands
-------------------------------------

[2.4.7.1] Beep command
----------------------

Usage: Beep

The name says it all. ;) Produces a standard Windows beep.

[2.4.7.2] MCI command
---------------------

Usage: MCI command

Sends command to the Windows MCI (Media Control Interface) system. MCI commands
can be used to play, stop, and record audio (and more too), and the full syntax
is beyond the scope of this document and into the realm of the Win32 API help
file. However, here are some examples to get you started:

        // Play filename.wav
        MCI Play filename.wav

        // Play bach.mid
        MCI Play bach.mid

        // Stop playing bach.mid
        MCI Stop bach.mid

        // Start recording audio to test.wav
        MCI Record test.wav

        // Stop recording audio to test.wav
        MCI Stop test.wav

[2.4.8] Server (and IRC) commands
---------------------------------

[2.4.8.1] Say command
---------------------

Usage: Say channel text

Sends the message text to channel. Use in scripts to send text to a channel. I
believe this has been undocumented since around 0.30. =]

[2.4.8.2] ASay command
----------------------

Usage: ASay text

Says text to every channel you are currently on.

[2.4.8.3] AMe command
---------------------

Usage: AMe text

Executes /me text to every channel you are currently on.

[2.4.8.4] SimulateServerData command
------------------------------------

Usage: SimulateServerData text

Puts text directly into ViRC '97's received data buffer, making V97 behave as
if text was received from the server. This is very useful as it allows you to
test new events you've written offline, and, possibly more usefully, to simply
make DCC connections to a certain IP address and port from a script. In clients
like mIRC which don't have this function, you have to send a CTCP to yourself,
but this isn't a good idea as you have to wait for the request to come back,
which is subject to server lag, and won't work if you're not connected to an
IRC server. This command can get around that. For example:

        SimulateServerData :test!virc@megalith.co.uk PRIVMSG blah :This is a test!!

This would make it appear exactly as if you received a private message from
a user whose nick is test and whose email address is virc@megalith.co.uk. There
is no way to differentiate between real and simulated server events in your
scripts.

[2.4.8.5] Using regular IRC commands
------------------------------------

Usage: [^][*]command ...

Regular IRC commands may be used in VS (of course ;), only the slash prefix is
optional and should be left out, and the code looks neater without it. In
addition, the command can be prefixed with ^, * or ^*.

A prefix of ^ surpresses the output of any text that the command directly
causes. For example, V97 contains code in its built-in MSG command to display
the message you're sending on the screen. ^MSG will send the message, but
surpress the text output.

A prefix of * passes the command straight into V97's built-in command
interpreter, without executing any aliases. This is very useful if you're
trying to override built-in commands, as, for example, if you want to call
V97's MSG command in your new MSG alias, you need to call the command as *MSG
to avoid the alias calling itself recursively.

Both prefixes can be combined as ^*. Please note that a prefix of *^ is
INVALID, and will not work.

The following code will change the text displayed when the user uses the /msg
command to something a little more fancy, demonstrating how to override a
built-in command:

Alias MSG
  TextOut ecPRIVMSG [*>\b$1\b<*]\t$2-
  ^*Msg $1-
EndAlias

[2.4.9] Inter-server communication commands
-------------------------------------------

[2.4.9.1] OnServer
------------------

Usage: OnServer index command

Executes command on the IRC server connection index. The best way to explain
how to use this function is to use a simple example, which will also make use
of the $ServerList() function.

7ay, for example, you're on 2 IRC servers: irc.ionet.net:6667 and
efnet.demon.co.uk:6666. The server connection that the script is running under
is irc.ionet.net:6667 (for example, if the user typed an alias from the
irc.ionet.net:6667 server window or any of its channel, query or DCC windows),
but you want to execute a command on the other server, efnet.demon.co.uk:6666.
First, you'd get the list of server connections with the $ServerList()
function, which would return:

        irc.ionet.net:6667 efnet.demon.co.uk:6666

(Note that the first server in the list (list index 0) is not necessarily the
active server connection - use the $CurrentServer() function to retrieve the
index of the current server.)

With this, your script could find out what the active server connection is.
$CurrentServer() would return:

        0

Hence, the script could, if necessary, display the name of the active server
connection with this code:

        TextOut > . clBlack *** The active server connection is: $listIndex($CurrentServer() $ServerList())

Now that the active server is known to be number 0, and hence the other server
is number 1, the script could execute an IRC command on the other server as
follows:

        OnServer 1 Join #virc

Note that only that command is executed on the IRC server number 1. All
subsequent IRC commands are executed on the server that was previously active.

[2.4.10] Miscellaneous commands
-------------------------------

[2.4.10.1] AcceptDCC command
----------------------------

Usage: AcceptDCC
       AcceptDCC filename

When called inside an <OnAcceptDCCQuery> event, accepts the incoming DCC
connection without any confirmation from the user, regardless of the DCC
settings specified in Client setup.

If a filename is specified, then the incoming file will be saved under that
filename (as if the user had manually chosen to rename the incoming file).

[2.4.10.2] AddToIAL command
---------------------------

Usage: AddToIAL channel nick user@host

Adds nick, with email address user@host, to channel's IAL (Internal Address
List). The IAL is used as a cache for the GetAddress function, so the server
does not have to be queried each time the function is used, speeding this
valuable function up and pretty much eliminating server lag. When a user joins
a channel, speaks in a channel, or makes a mode change in a channel, the user
is added to the channel's IAL automatically, and is removed when that user
leaves the channel or quits IRC. The whole of the channel's IAL is cleared when
you leave that channel. Use AddToIAL to force an entry into the IAL which V97
would not add on its own. For example, if you want to cache all the WHO replies
on a channel in the IAL, you can write an event handler which parses each WHO
reply and adds each entry manually. ViRC '97 will then "take care" of those
manually-added entries itself, deleting them when necessary and so forth.

For more information on the IAL, see the GetAddress function.

[2.4.10.3] CancelDCC command
----------------------------

Usage: CancelDCC

When called inside an <OnAcceptDCCQuery> event, cancels the incoming DCC
connection without any confirmation from the user, regardless of the DCC
settings specified in Client setup.

[2.4.10.4] DDE command
----------------------

Usage: DDE service topic "item" text

Syntactically identical to mIRC's command of the same name. Connects to a DDE
server using the details supplied and sends text by DDE. This command can also
be used as a function, i.e. $dde(service topic "item" text), and will return
any data received from the DDE server as a result of the DDE function.

[2.4.10.5] DisableInternalXDCCEvents
------------------------------------

Usage: DisableInternalXDCCEvents

Disables all internal XDCC processing. V97 will no longer respond to XDCC
requests from other users, and the standard events will be called when an
XDCC request is received, just as if it were a standard PRIVMSG or CTCP. Use
this if you wish to override the built-in XDCC mechanism in your own script.

[2.4.10.6] DNS command
----------------------

Usage: DNS host

The DNS command will take a hostname as a parameter and display on the screen
the corresponding IP address. Example:

        DNS jimc.demon.co.uk

Will display:

        *** DNS lookup: jimc.demon.co.uk resolves to 158.152.45.81

[2.4.10.7] EnableInternalXDCCEvents
-----------------------------------

Usage: EnableInternalXDCCEvents

Re-enables all internal XDCC processing after DisableIncomingXDCCEvents has
been called. V97 will then respond to XDCC requests from other users. Use
this if you wish to re-enable V97's internal XDCC mechanism after you have
overriden it in your own script.

[2.4.10.8] Eval command
-----------------------

Usage: Eval command
       $eval(text)

Normally, commands are evaluated before executing them. Placing EVAL before a
command line causes the line to be evaluated twice before executing. You'd
probably never have to use this in your scripts, except when evaluating
expressions that are stored somewhere else, for example, a line in a file.
To get a random line from a file, evaluate that line, and store in $x, you'd
use:

        Eval @ $$x = $randomread(filename.txt)

EVAL can also be called as a function, in which case text is evaluated, and
the evaluated text is returned, rather than being executed, as with the EVAL
command. Hence, the above line could be rewritten as:

        @ $x = $eval($randomread(filename.txt))

[2.4.10.9] Name command
-----------------------

Usage: Name text

Names your script text. This isn't really a command at all. It's used by the
script loader to display your script's name in the loading progress dialog box.
It's recommended you use NAME to give your script a sensible name at the top of
the file, so people know what they're loading.

[2.4.10.10] NoAttribs command
-----------------------------

Usage: NoAttribs command

Executes command as normal, but surpresses attribute (\b, \u, \i and \t)
parsing. For example, the following statement will not work as desired (try
it):

        Say #channel I'll send you the file c:\unix\tftp.

This is because V97's parser will pick up the \u and \t in your "filename" and
will translate them to the underline and tab formatting codes. The solution is
to prefix the command with NoAttribs, which surpresses parsing of formatting
codes:

        NoAttribs Say #channel I'll send you the file c:\unix\tftp.

This will work as desired (try this too if you don't understand this fully).

[2.4.10.11] MessageBox command
------------------------------

Usage: MessageBox text

Displays a message box on the screen with an OK button, with text as its
contents. Use this in scripts to inform the user of something.

[2.4.10.12] SetInputLine command
--------------------------------

Usage: SetInputLine window text

Sets the the contents of window's command entry box to text. window can be .
(a period) for the server notices window, a channel name for a channel window,
a nick for a query window, or =nick for a DCC Chat window.

[2.4.10.13] UserAdd command
---------------------------

Usage: UserAdd mask userlevel banlevel protlevel
       UserAdd mask userlevel banlevel protlevel customlevel

Adds mask (in nick!user@host form), which may contain wildcards, to the
userlist, assigning it the specified userlevel, banlevel and protlevel.
The levels assigned may be between 0 and 1048576 (1M), and have no real
built-in meaning (although a few userlevels are used in DEFAULT.LIB), so you
can assign whatever meaning you want to each level in your script. Specifying
a level of -1 leaves mask's current level unchanged (or sets the level to 0 if
mask isn't already in the userlist). Example:

        UserAdd *!*megalith@*demon.co.uk 1 0 0
        // The above adds the mask *!*megalith@*demon.co.uk to the userlist
        // with a userlevel of 1, a banlevel of 0 and a protlevel of 0.

        UserAdd *!*megalith@*demon.co.uk 10 -1 -1
        // The above increases *!*megalith@*demon.co.uk's userlevel to 10,
        // leaving the banlevel and protlevel unchanged.

The userlevel, banlevel and protlevel of a mask can be retrieved with the
GETUSERLEVEL, GETBANLEVEL and GETPROTLEVEL functions respectively.

Additionally, a customlevel may be specified. The customlevel can be any text
string to assign to the mask - it doesn't have to be a number. No internal
meaning is assigned to the customlevel, nor is it used by DEFAULT.LIB, so if
you're designing your own userlevel system and wish to store any additional
information or flags for the user, store them in the customlevel. If no
customlevel is supplied on the command line, the customlevel is unchanged.
Example:

        UserAdd *!*megalith@*demon.co.uk -1 -1 -1 This is a test.
        // The above doesn't change the userlevel, banlevel or protlevel of
        // *!*megalith@*demon.co.uk, but changes the customlevel to the string
        // "This is a test.".

        UserAdd *!*megalith@*demon.co.uk 0 20 -1
        // The above changes *!*megalith@*demon.co.uk's userlevel to 0 and
        // banlevel to 20, leaving the protlevel and the customlevel unchanged.

The customlevel of a mask can be retrieved with the GETCUSTOMLEVEL function.

[2.4.10.14] UserDelete command
------------------------------

Usage: UserDelete mask

Deletes the single, specific entry mask (in nick!user@host form), which may
contain wildcards, from the userlist. For example, if the userlist contains:

        *!*@*.com
        user1!*@*.com
        user2!*@*.com

This command will only delete the first entry, *!*@*.com, not the others,
because wildcard comparison between the mask specified as the parameter and
each mask in the userlist is NOT performed:

        UserDelete *!*@*.com

[2.4.10.15] UserDeleteWithWildcards command
-------------------------------------------

Usage: UserDeleteWithWildcards mask

Deletes any entry from the userlist whose mask matches the mask (in
nick!user@host form), which may contain wildcards, specified as the parameter.
For example, if the userlist contains:

        *!*@*.com
        user1!*@*.com
        user2!*@*.com

This command will delete every entry from the userlist, because wildcard
comparison between the mask specified as the parameter and each mask in the
userlist IS performed:

        UserDeleteWithWildcards *!*@*.com

[2.4.11] Debugging commands
---------------------------

[2.4.11.1] EvaluateWindow command
---------------------------------

Usage: EvaluateWindow

Pops up a window, similar to Delphi's variable evaluation window, which allows
expressions to be evaluated at run-time. You can, for example, place an
EvaluateWindow command stategically in your code for debugging to examine the
contents of variables at a particular point.

[2.5] Functions
---------------

[2.5.1] String manipulation functions
-------------------------------------

[2.5.1.1] Asc function
----------------------

Usage: $asc(char)

Returns the ASCII value for char. For example, $asc(A) = 65, as the ASCII code
for the character A is 65.

[2.5.1.2] Char function
-----------------------

Usage: $char(value)

Returns the character for value. For example, $asc(65) = A, as the character
A corresponds to the ASCII code 65.

[2.5.1.3] IsNumeric function
----------------------------

Usage: $isnumeric(num)

Returns 1 if num is a number, and 0 if num is not a number. Examples:

        $isnumeric(1234) = 1
        $isnumeric(hello) = 0

[2.5.1.4] IsChannel function
----------------------------

Usage: $ischannel(channel)

Returns 1 if channel is a valid channel name, otherwise returns 0. Examples:

        $ischannel(#quake) = 1
        $ischannel(&local) = 1
        $ischannel(xyz) = 0

[2.5.1.5] IsURL function
------------------------

Usage: $isurl(url)

Returns 1 if url is a valid URL (an address that a web browser can handle).
Examples:

        $isurl(http://www.megalith.co.uk) = 1
        $isurl(mailto:acable@sv.span.com) = 1
        $isurl(www.microsoft.com) = 1
        $isurl(ftp.htsoft.com) = 1
        $isurl(blah.xyz.com) = 0

[2.5.1.6] Length function
-------------------------

Usage: $length(text)

Returns the length of text in characters. Example:

        $length(hello) = 5

[2.5.1.7] Lower function
------------------------

Usage: $lower(text)

Converts the given text to lower case. For example:

        $lower(BLAH) = blah

[2.5.1.8] MaskMatch function
----------------------------

Usage: $maskmatch(text mask)

Matches text against mask. Use MASKMATCH, and _not_ WILDMATCH, if you're trying
to match a nick!user@host-style mask. Example:

        $maskmatch(MeGALiTH!~megalith@jimc.demon.co.uk *!*megalith@*demon.co.uk) = 1

Mask comparisons are case-insensitive.

[2.5.1.9] RStrPos function
--------------------------

Usage: $rstrpos(needle haystack)

The reverse of STRPOS. Finds the last occurrence of needle within haystack, and
returns the character position of needle. 0 is returned if needle is not found
in haystack. For example:

        $rstrpos(x abxcdxba) = 6
        $rstrpos(dx abxcdxba) = 5
        $rstrpos(blah hahahahha) = 0

[2.5.1.10] RStrTokL function
----------------------------

Usage: $rstrtokl(token text)

The reverse of STRTOKL. Searches for token within text, and returns everything
to the left of the last occurrence of token. If token can't be found, returns
text unchanged.

        $rstrtokl(. www.megalith.co.uk) = www.megalith.co
        $rstrtokl(q abc123xyz) = abc123xyz

[2.5.1.11] RStrTokR function
----------------------------

Usage: $rstrtokr(token text)

The reverse of STRTOKR. Searches for token within text, and returns everything
to the right of the last occurrence of token. If token can't be found, returns
an empty string.

        $rstrtokr(. www.megalith.co.uk) = uk
        $rstrtokr(q abc123xyz) =

[2.5.1.12] StrPos function
--------------------------

Usage: $strpos(needle haystack)

Finds the first occurrence of needle within haystack, and returns the character
position of needle. 0 is returned if needle is not found in haystack. For
example:

        $strpos(cd abcdefg) = 3
        $strpos(blah hahahahha) = 0

[2.5.1.13] StrPosFrom function
------------------------------

Usage: $strposfrom(position needle haystack)

Starting from the character at position (where 1 is the first character in the
string) and onwards, finds needle within haystack, and returns the character
position of needle. 0 is returned if needle is not found in haystack. For
example:

        $strposfrom(5 cd abcdefcdg) = 7
        $strposfrom(4 blah hahahahha) = 0

[2.5.1.14] StrTokL function
---------------------------

Usage: $strtokl(token text)

Searches for token within text, and returns everything to the left of the first
occurrence of token. If token can't be found, returns text unchanged.

        $strtokl(. www.megalith.co.uk) = www
        $strtokl(q abc123xyz) = abc123xyz

[2.5.1.15] StrTokR function
---------------------------

Usage: $strtokr(token text)

Searches for token within text, and returns everything to the right of the
first occurrence of token. If token can't be found, returns an empty string.

        $strtokr(. www.megalith.co.uk) = megalith.co.uk
        $strtokr(q abc123xyz) =

[2.5.1.16] StrTrim function
---------------------------

Usage: $strtrim(text)

Removes control characters and the preceding colon, if present, from text. This
is very useful, as many lines received from the IRC server contain parameters
prefixed by a colon.

Example: Consider this line of server text.

        :nick!user@host PRIVMSG #channel :well, what's up everybody!!

To extract the actual message sent to the channel correctly, you would use
$strtrim($3-). This function will also remove the \A character from the
beginning of CTCPs.

[2.5.1.17] SubStr function
--------------------------

Usage: $substr(text start num)

Returns num characters at start from text. Exactly equivalent to Delphi's
Copy(text, start, num) function or VB's Mid$(text, start, num) function.
Example:

        $substr(abcdef 2 3) = bcd

[2.5.1.18] Upper function
-------------------------

Usage: $upper(text)

Converts the given text to upper case. For example:

        $upper(blah) = BLAH

[2.5.1.19] WildMatch function
-----------------------------

Usage: $wildmatch(text mask)

Matches text against mask, which can contain wildcards. Examples:

        $wildmatch(blah *lah) = 1
        $wildmatch(blah bla*) = 1
        $wildmatch(blah *la*) = 1
        $wildmatch(blah *) = 1
        $wildmatch(blah *hah) = 0

Mask comparisons are case-insensitive. text may contain spaces. mask, however,
may not.

[2.5.1.20] WordCount function
-----------------------------

Usage: $wordcount(text)

*** NOTE: This function has been superceded by the listElementCount function,
although the WordCount function is still available for backwards compatibility
with old scripts.

Returns the number of words in text. Examples:

        $wordcount()            = 0
        $wordcount(abc)         = 1
        $wordcount(a b c)       = 3

This is very useful if you wish to find out the number of parameters passed to
an alias, for example. You would use something like:

        @l $paramcount = $wordcount($1-)

[2.5.2] List manipulation functions
-----------------------------------

V97 0.94pre7 and above support lists, a feature very similar to the lists in
TCL. Basically, whereas the regular string manipulation functions in VS work
on characters (e.g. SUBSTR returns a range of characters, STRPOS searches for
one or more characters within the string), the list functions work on words,
which, to use the correct terminology, are called elements. The first element
in a list has index 0. Elements in a list are separated by spaces. If you want
to have an element in a list which actually contains a space itself, you must
enclose the whole element in quotation marks ("). As lists are just strings,
they are defined as normal variables, just like anything else. Here are some
examples:

        // A list with four elements
        @ $x = zero one two three
        // This will display: two
        MessageBox $listIndex(2 $x)

        // A list with elements containing spaces
        @ $x = Jack "John Smith" Jill "Chris Jones"
        // This will display: Chris Jones
        MessageBox $listIndex(3 $x)

Lists are an extremely powerful feature. Get to know the different functions
available well. Development of many complex scripts can be made dramatically
simpler by good use of lists.

Note that, with all the below functions, if you wish to specify one element
that contains a space, enclose it with quotes (").

[2.5.2.1] listElementCount function
-----------------------------------

Usage: $listElementCount(list)

Returns the number of elements in list. Examples:

        @ $x = zero one two three
        // This will display: 4
        MessageBox $listElementCount($x)

        @ $x = "one two" "three four" five six "seven eight"
        // This will display: 5
        MessageBox $listElementCount($x)

In case the second example isn't clear, that list contains 5 elements, which
are: "one two", "three four", five, six, and "seven eight".

[2.5.2.2] listIndex function
----------------------------

Usage: $listIndex(index list)

Returns element index from list. The first element in the list is at index 0.
Examples:

        @ $x = zero one two three four
        // This will display: one
        MessageBox $listIndex(1 $x)

        // This will display: three
        MessageBox $listIndex(3 $x)

[2.5.2.3] listIndexOf function
------------------------------

Usage: $listIndexOf(element list)

Returns the index of element in list. The first element in the list is at index
0, the second is at index 1, and so forth. If element isn't present in list,
this function will return -1. element can contain wildcard characters.

Examples:

        @ $x = zero one two three four
        // This will display: 3
        MessageBox $listIndexOf(three $x)

        // This will display: 2
        MessageBox $listIndexOf(*w* $x)

        // This will display: -1
        MessageBox $listIndexOf(five $x)

[2.5.2.4] listInsert function
-----------------------------

Usage: $listInsert(index element list)

Inserts element at position index into list. Example:

        @ $x = 0 1 2 3 4 5
        // This will display: 0 1 2 X 3 4 5
        MessageBox $listInsert(3 X $x)

[2.5.2.5] listJoin function
---------------------------

Usage: $listJoin(delimiter list)

Returns list, with each element separated by delimeter. Examples:

        @ $x = Jack Jill Bill Ben
        // This will display: Jack,Jill,Bill,Ben
        MessageBox $listJoin(, $x)

        // This will display: Jack and Jill and Bill and Ben
        MessageBox $listJoin (" and " $x)

[2.5.2.6] listRange function
----------------------------

Usage: $listRange(start end list)

Returns one or more elements from list, starting from start and ending at end.
Example:

        @ $x = zero one two three four
        // This will display: one two three
        MessageBox $listRange(1 3 $x)

[2.5.2.7] listRemove function
-----------------------------

Usage: $listRemove(mask list)

Returns another list which contains every element in list that is not matched
by mask. Effectively removes one or more items from the list. Examples:

        @ $x = one two ten twenty-two
        // This will return a list with the element "two" removed. This will
        // display: one ten twenty-two
        MessageBox $listRemove(two $x)

        // This will return a list with any items matching the mask *two*
        // removed. This will display: one ten
        MessageBox $listRemove(*two* $x)

mask is a standard wildcard mask, e.g. h?el?o, *test, bla*, *e*, etc.

[2.5.2.8] listReplace function
------------------------------

Usage: $listReplace(start end element list)

Replaces the elements in list from start to end with element. Examples:

        @ $x = zero one two three four
        // This will display: zero X four
        MessageBox $listReplace(1 3 X $x)

        // This will display: zero "VIRC SCRIPT" four
        MessageBox $listReplace(1 3 "VIRC SCRIPT" $x)

Notice how this function replaces the elements specified with one element only.
The last string returned, zero "VIRC SCRIPT" four, has 3 elements: zero, VIRC
SCRIPT, and four. The string VIRC SCRIPT is inserted as one element.

[2.5.2.9] listSearch function
-----------------------------

Usage: $listSearch(mask list)

Returns another list which contains every element in list that is matched by
mask:

        @ $x = zero one two three four five six seven eight nine ten
        // This will display every element that has an e in it, i.e.
        // zero one three five seven eight nine ten
        MessageBox $listSearch(*e* $x)

mask is a standard wildcard mask, e.g. h?el?o, *test, bla*, *e*, etc.

[2.5.2.10] listSearchReplace function
-------------------------------------

Usage: $listSearchReplace(mask element list)

Returns another list which is the same as list, except that every element in
list that matches mask is replaced by the element specified. Examples:

        @ $x = zero one two three four five six seven eight nine ten
        // This will display: X X two X four X six X X X X
        MessageBox $listSearchReplace(*e* X $x)

        // This will make any occurrences of your nick in $y appear in bold
        @ $y = $listSearchReplace($N \b$N\b $y)

[2.5.2.11] listSplit function
-----------------------------

Usage: $listSplit(delimiter list)

Returns another list whose elements are delimited by the delimiter specified in
the list specifed. Example:

        @ $x = jimc.demon.co.uk
        // This will display: jimc demon co uk
        MessageBox $listSplit(. $x)

        @ $x = blah.blah test.test
        // Lists like these are handled correctly too. When delimited by a .
        // this list contains 3 elements only, blah, "blah test", and test.
        // So, this will display: blah "blah test" test
        MessageBox $listSplit(. $x)

[2.5.3] Set manipulation functions
----------------------------------

V96 0.82 and above support sets, a very powerful feature similar to Delphi's
set capability. ObjectVS set properties are supported (see OBJECTVS.TXT), but
sets work well in regular VS without objects too.

Basically, a set can contain one or more elements, each which is one word. It's
as simple as that. For example, consider this data:

        Patricia        - Female, long dark hair, brown eyes, married
        Mark            - Male, short dark hair, blue eyes, not married
        Sarah           - Female, short red hair, black eyes, not married

You could represent this data in VS easily by use of sets:

        @ $Patricia = [sexFemale,hairLong,hairDark,eyesBrown,msMarried]
        @ $Mark = [sexMale,hairShort,hairDark,eyesBlue]
        @ $Sarah = [sexFemale,hairShort,hairRed,eyesBlack]

Note that all sets are surrounded by []'s and each set element is separated
from the next by a comma.

Once $Patricia and $Mark are defined, you can use, for example, the ISINSET
function as follows:

        $IsInSet([sexMale] $Mark)                       == 1
        $IsInSet([sexFemale,eyesBrown] $Patricia)       == 1
        $IsInSet([sexFemale,hairDark] $Sarah)           == 0

If Sarah dyes her hair black and grows it long, the ADDTOSET and REMOVEFROMSET
functions can be used:

        @ $Sarah = $RemoveFromSet($Sarah [hairShort,hairRed])
        @ $Sarah = $AddToSet($Sarah [hairLong,hairBlack])

On IRC, of course, you'd hardly ever represent personal information using sets.
:) What sets are very useful for is for storing user flags, for example:

        @s $userflags.$nick = [AutoOp,Protected,OnUserlist]

Then when a user joins a channel you could use something like this to auto-op
them:

        if ($IsInSet([AutoOp] $userflags.$nick))
           Mode +o $nick
        endif

Or a set could be used to hold a list of nicknames for some purpose - the
possibilities are practically endless.

Anyway. Now I'll document these set functions individually.

[2.5.3.1] IsInSet function
--------------------------

Usage: $IsInSet(set1 set2)

Returns 1 if every element in set1 is also in set2, and 0 otherwise.

[2.5.3.2] AddToSet function
---------------------------

Usage: $AddToSet(set1 set2)

Additionally combines set1 and set2, and returns a new set containing all the
elements in both set1 and set2.

Note that ADDTOSET also cleans up the set, removing any spaces and duplicate
items. Hence it's sometimes useful to use ADDTOSET with set1 or set2 as an
empty set [] to clean it up, for example:

        @ $x = [     blue,      BLACK,    blAck, green         ]
        @ $y = $AddToSet([] $x)

$y will now contain [blue,BLACK,green]. Spaces and duplicate items (BLACK and
blAck, set operations are case-insensitive) have been removed.

[2.5.3.3] RemoveFromSet function
--------------------------------

Usage: $RemoveFromSet(set1 set2)

Returns a new set containing all the items in set1 that are not also in set2.

Note that REMOVETOSET also cleans up the set. For more information on cleaning
sets, see the note at the bottom of the ADDTOSET function above.

[2.5.4] Alias/event manipulation functions
------------------------------------------

[2.5.4.1] AliasExists function
------------------------------

Usage: $aliasexists(name)

Returns 1 if the alias name exists, and 0 if it does not.

[2.5.4.2] EventExists function
------------------------------

Usage: $eventexists(name)

Returns 1 if the event name exists, and 0 if it does not.

[2.5.4.3] IsEventEnabled function
---------------------------------

Usage: $iseventenabled(event)

Returns 1 if event is enabled (events are enabled by default), and 0 if event
is disabled (e.g. by the DISABLEEVENT command).

[2.5.5] Formatted text output functions
---------------------------------------

[2.5.5.1] Bitmap function
-------------------------

Usage: $bitmap(filename)

This function loads a bitmap and returns a handle to it that can be used with
the TextOutBitmap command to display a line of text containing a bitmap to the
left of the text. At present, only 13x13 bitmaps (in the standard Windows BMP
format) are supported. Trying to use a larger or a smaller bitmap will cause
problem. The bottom left-hand pixel of the bitmap is used as the transparency
colour.

In addition, there are a number of built-in bitmaps. They have the following
"filenames":

        _join.bmp
        _part.bmp
        _quit.bmp
        _mode.bmp
        _face.bmp

If you use one of these bitmaps, they will be loaded from within the V97 EXE,
and don't need to be present on disk.

One thing is worth stressing. Because it would be extremely slow for a bitmap
to be loaded from disk each time it is displayed, bitmaps loaded with this
function are cached. If you load them again, the bitmap is retrieved from the
cache and isn't actually loaded from disk again. Therefore, if you change the
bitmap on disk, the old bitmap will still be used. To get around this, you can
use the FlushBitmapCache command to clear the bitmap caches. All bitmaps will
then be reloaded from disk.

Examples:

        // Display a line of text using a built-in bitmap
        TextOutBitmap > #virc clBlack $bitmap(_join.bmp) Welcome to #virc!

        // Display a line of text using a bitmap loaded from disk
        TextOutBitmap > #virc clBlack $bitmap(example.bmp) Welcome to #virc!

[2.5.6] Time and clock functions
--------------------------------

[2.5.6.1] CTime function
------------------------

Usage: $ctime()

Used to calculate time intervals, measured in seconds. The actual value
returned is the number of seconds that Windows has been running, although this
may change in the future and cannot be relied upon. The number returned by
$ctime() increases by 1 every second. For example:

        @ $x = $ctime()
        for (@ $i = 0; $i < 1000; @ $i = $($i + 1))
          Yield
        endfor
        TextOut clBlue *** An empty 1000-iteration for loop takes $($ctime() - $x) seconds to complete.

Notice how $ctime() is used here to calculate a time interval - the actual
meaning of the value returned by $ctime() is insignificant.

The $ctime() function can also be used as a timer. For example, to wait for
20 seconds before quitting V97, you could use the following code:

        @ $x = $ctime()
        while ($ctime() - $x) < 20
          Yield
        endwhile
        Exit

[2.5.6.2] Date function
-----------------------

Usage: $date()

Returns the current system date in default system format. This format is
determined by your Windows locale (internationalization) settings, and may be
something like 17th June 1996.

[2.5.6.3] DecodeInterval function
---------------------------------

Usage: $decodeinterval(integer)

Converts the integer supplied as the parameter to a human-readable time
interval. For example:

        $decodeinterval(38) = 38 seconds
        $decodeinterval(60) = 1 minute
        $decodeinterval(61) = 1 minute 1 second
        $decodeinterval(3728) = 1 hour 2 minutes 8 seconds

[2.5.6.4] DecodePingInterval function
-------------------------------------

Usage: $decodepinginterval(integer)

Converts the ping-encoded integer specified to a human-readable time interval.
This function is only useful to decode received pings. To decode normal time
intervals, use the DECODEINTERVAL function.

[2.5.6.5] IdleMTime function
----------------------------

Usage: $idlemtime()

Returns the amount of time the user has been idle for in milliseconds. The same
as $idletime(), only returns a value in milliseconds rather than seconds.

[2.5.6.6] IdleTime function
---------------------------

Usage: $idletime()

Returns the amount of time the user has been idle for in seconds. Can be used
to implement auto-away scripts. For example, the following code will wait until
the user has been idle for 2 minutes (120 seconds) and will then set him away:

        while ($idletime() < 120)
          Yield
        endwhile
        Away Automatically set away after 2 minutes

[2.5.6.7] MTime function
------------------------

Usage: $mtime()

Used to calculate time intervals, measured in milliseconds. Use for measuring
time intervals. The number returned by $mtime() increases by 1 every
millisecond.

[2.5.6.8] Time function
-----------------------

Usage: $time(format)

Returns the current system time in a human-readable format (hour:minute:second
AM/PM by default). For example, $time() may return 11:52:48 AM. If you wish,
you may specify an optional format string to format the date/time in any way
you wish. Valid format specifiers are:

        d       - Day of the month in numeric format, with no trailing zero (e.g. 7, 23)
        dd      - Day of the month in numeric format, with trailing zero if necessary (e.g. 07, 23)
        ddd     - Day of the week in short format (e.g. Sat)
        dddd    - Day of the week in long format (e.g. Saturday)
        m       - Month in numeric format, with no trailing zero (e.g. 6, 11)
        mm      - Month in numeric format, with trailing zero if necessary (e.g. 06, 11)
        mmm     - Month in short format (e.g. Jan)
        mmmm    - Month in long format (e.g. January)
        yy      - Year in short numeric format (e.g. 97)
        yyy     - Year in long numeric format (e.g. 1997)

        h       - Hour of the day in numeric format, with no trailing zero (e.g. 5, 16)
        hh      - Hour of the day in numeric format, with trailing zero if necessary (e.g. 05, 16)
        n       - Minute in numeric format, with no trailing zero (e.g. 3, 34)
        nn      - Minute in numeric format, with trailing zero if necessary (e.g. 03, 34)
        s       - Second in numeric format, with no trailing zero (e.g. 9, 46)
        ss      - Second in numeric format, with trailing zero if necessary (e.g. 09, 46)
        A/P     - A if the time is AM, P if the time is PM
        AM/PM   - AM if the time is AM, PM is the time is PM

Note that if A/P or AM/PM are specified, the time is given in 12-hour format,
otherwise, it is given in 24-hour format.

For example:

        $time(dd/mm/yy hh:nn:ss) - might return 12/07/96 19:21:18
        $time(dd/mm/yy hh:nn:ss AM/PM) - might return 12/07/96 07:21:18 PM
        $time(ss) - might return 18

[2.5.6.9] TimeConnected function
--------------------------------

Usage: $timeconnected()

Returns the number of seconds that you've been connected to the server for. If
you're not currently connected to the server, this will return 0. Usefully, the
value of this function is not reset to 0 until after <OnDisconnect> has been
fired. Therefore, your script can report the total time connected to the server
when the user disconnects by adding a line of code to the <OnDisconnect>
event.

[2.5.6.10] UnixTime function
----------------------------

Usage: $unixtime(unixtime)
       $unixtime(unixtime format)

Converts the unixtime specified to human-readable format. Many IRC server
responses return times in unixtime (otherwise known as UTC time) format, which
is currently a number around 850000000. The unixtime value is the number of
seconds since 1st January 1970 00:00:00 AM GMT, and is the value returned by
the C time() function. If you do not specify the format parameter, the date
and time will be displayed in the same way as the TIME function displays dates
and times by default. See the TIME function for information on format strings.

[2.5.7] File I/O functions
--------------------------

[2.5.7.1] FileExists function
-----------------------------

Usage: $fileexists(filename)

Returns true (1) if filename exists, otherwise returns false (0).

[2.5.7.2] GetCurrentDir function
--------------------------------

Usage: $getcurrentdir()

Returns the current directory on the current drive. The directory name returned
by this function ALWAYS ends in a bashslash (\).

[2.5.7.3] GetFileSize function
------------------------------

Usage: $getfilesize(filename)

Returns the size, in bytes, of filename. If filename doesn't exist, or cannot
be accessed, this function will return -1 (it returned 0 in versions prior to
1.00rc5b).

[2.5.7.4] GetFileDateTime function
----------------------------------

Usage: $getfiledatetime(filename)
       $getfiledatetime(filename format)

Returns filename's date and/or time. If format is not specified, the filename's
date and time will be returned in the same format as the TIME function returns
system times. You may also specify format to format the date and time
information in any way you wish. See the TIME function for information on
format strings.

[2.5.7.5] GetLinesInFile function
---------------------------------

Usage: $getlinesinfile(filename)

Returns the number of lines in filename. If filename doesn't exist, the
function will return -1.

[2.5.7.6] GetPath function
--------------------------

Usage: $getpath(id)

Returns one of the stock ViRC '97 paths (see Client setup/Paths). id can be one
of the following:

        virc                    - returns the base ViRC '97 directory
        upload                  - returns the V97 upload directory
        download                - returns the V97 download directory
        script                  - returns the V97 script directory
        sound                   - returns the V97 sound directory

[2.5.7.7] PathExists function
-----------------------------

Usage: $pathexists(path)

Returns 1 if path exists, and 0 otherwise.

[2.5.7.8] RandomRead function
-----------------------------

Usage: $randomread(file)

Returns a randomly-selected line from file. This is useful for quote or slap
scripts.

[2.5.7.9] ReadLine function
---------------------------

Usage: $readline(linenum filename)

Returns line number linenum from filename. For example, $readline(1 blah.txt)
will return the 1st line from the file blah.txt. If you specify an invalid
line number, the function returns an empty string.

[2.5.8] Registry I/O functions
------------------------------

[2.5.8.1] ReadRegistry function
-------------------------------

Usage: $readregistry("section" key)
       $readregistry("section" key default)

Returns the value of key from the registry section "section", located under
the ViRC '97 key (e.g. having a section of "YyzScript" would write to
HKEY_CURRENT_USER\Software\MeGALiTH Software\Visual IRC 96\YyzScript. If you
wish, you may also specify a default value which is returned if the registry
value you're trying to read doesn't exist. You cannot read outside the ViRC '97
key in the registry. This is a conscious design decision to ensure maximum
security (a malicious script cannot read private parts of your registry and
send them over IRC).

[2.5.8.2] GetSetting function
-----------------------------

Usage: $getsetting(section value)

This is a very powerful function which allows a script to obtain any ViRC '97
user setting that it's stored in the registry. For example, the default event
library that comes with V97, DEFAULT.LIB, uses this function to determine
whether to output text in a query window or not, depending on whether the user
has chosen to use a query window or not in the Options tab of the Client Setup
dialog.

The best way to find the values for section and value is to load up REGEDIT (it
comes with Windows 95 and NT) and to look in
HKEY_CURRENT_USER/Software/MeGALiTH Software/Visual IRC '97. All available
sections are visible there.

Examples:

        $getsetting(Options QueryEnabled)
        $getsetting(Options AutoRejoin)
        $getsetting(SOCKS setup Enabled)
        $getsetting(IDENTD setup Port)

[2.5.9] Common dialogs
----------------------

[2.5.9.1] OpenDialog function
-----------------------------

Usage: $opendialog(title|filespecdescription|filespec ...)
       $opendialog(title)

Displays a COMDLG32.DLL standard file open dialog, which has the title title,
and displays files of type filespecdescription and filespec. If
filespecdescription and filespec are omitted, all files (*.*) are displayed.
Use of this function is best illustrated with a few examples:

        // Prompts the user for a script and /loads it
        Load $opendialog(Select a ViRCScript script to load|ViRCScript files (*.vsc)|*.vsc)

        // Prompts the user to select any file, and assigns its name to $x
        @ $x = $opendialog(Select any file)

        // Prompts the user for a .TXT or a .DOC file, and DCC SENDs it to the nick abc123
        DCC Send abc123 $opendialog(Select a text file|Text files|*.txt|Word documents|*.doc)

If the user presses the Cancel button on the dialog, an empty string is
returned, for example:

        @ $x = $opendialog(blah blah blah)
        if ([$x] == [])
           MessageBox You must select a filename!!
           Halt
        endif

[2.5.9.2] OpenPictureDialog function
------------------------------------

Usage: $openpicturedialog(title|filespecdescription|filespec ...)
       $openpicturedialog(title)

Identical to the OpenDialog function, except that this dialog has a built-in
picture viewer, currently supporting BMP, ICO, WMF and JPG files. You can use
this function to write a poor man's picture viewer in ViRCScript.

[2.5.9.3] SaveDialog function
-----------------------------

Usage: $savedialog(title|filespecdescription|filespec ...)
       $savedialog(title)

Very similar to the OPENDIALOG function documented above, except the dialog has
a Save button instead of an Open button. In addition, if the file the user
selects already exists, they will be prompted whether they wish to overwrite
it. If no file is selected, the function returns an empty string.

For examples, see the OPENDIALOG function documented above.

[2.5.9.4] SavePictureDialog function
------------------------------------

Usage: $savepicturedialog(title|filespecdescription|filespec ...)
       $savepicturedialog(title)

Identical to the SaveDialog function, except that this dialog has a built-in
picture viewer, currently supporting BMP, ICO, WMF and JPG files.

[2.5.10] IRC-specific functions
-------------------------------

[2.5.10.1] ActiveWindow function
--------------------------------

Usage: $activewindow()

Returns the window that currently has the focus. If a channel window currently
has the focus, this function will return the name of the channel. If a query
window currently has the focus, this function will return the nick of the
query window. If the server window currently has the focus, this function will
return . (a period).

Remember that, in an alias, $C contains the name of the window that the alias
was executed in, but in an event (which is really just fired when any line of
text is received from the server), $C has no value, but $activewindow() will
always return the correct value. Useful if you want to write some text to the
window the user currently has the focus set to (so he/she won't miss the
text!!).

[2.5.10.2] ChannelCount function
--------------------------------

Usage: $channelcount()

Returns the number of open channels.

[2.5.10.3] Channels function
----------------------------

Usage: $channels(num)

Returns the name of open channel number num. For example, if you have one
channel open, #quake, $channels(1) will return #quake. If the channel number
num specified does not exist, the function will return nothing.

[2.5.10.4] ChannelList function
-------------------------------

Usage: $channellist()

Returns a list of all the channels you're on. For example, if you're on #quake,
#virc, and #polska, this function would return:

        #quake #virc #polska

[2.5.10.5] CurrentServer_ActiveWindow function
----------------------------------------------

Usage: $currentserver_activewindow()

This horribly-named function is exactly the same as $activewindow(), except for
the fact that, if the active window does NOT belong to the current server
connection (e.g. if the active window is a channel from a different server to
the one that the alias/event was executed in), the function will return . as if
the active window was the server notices window for the current server. If you
don't understand this, you won't have to use this function. :)

[2.5.10.6] GetAddress function
------------------------------

Usage: $getaddress(nick)

Gets the email (user@host) address of nick. If the address cannot be retrieved
for some reason, the function will return unknown@unknown.

Recent versions of ViRC '97 maintain a cache called the IAL (Internal Address
List) which keeps track of the user@host addresses of nicks on channels. If any
address is in the IAL, it will be retrieved immediately, and the server will
not be queried for it again. You may manually add nick!user@host masks with the
AddToIAL command. For more information on the IAL, see the AddToIAL command.

[2.5.10.7] GetBanLevel function
-------------------------------

Usage: $getbanlevel(mask)

Returns the banlevel of mask in your banlist. If the user cannot be found in
the banlist, the function will return 0.

[2.5.10.8] GetCustomLevel function
----------------------------------

Usage: $getcustomlevel(mask)

Returns the customlevel of mask in your userlist. If the user cannot be found
in the userlist, the function will return an empty string.

[2.5.10.9] GetLag function
--------------------------

Usage: $getlag()

Gets the current lag-ness of the active server connection. The lag is returned
in tenths of seconds (e.g. 10 means 1 second of lag). If the lag is unknown,
this function will return -1.

[2.5.10.10] GetUser function
----------------------------

Usage: $getuser()

If the -user parameter was specified on V97's command line, this function
returns the name of the user. If -user was not specified, this function returns
an empty string.

[2.5.10.11] GetUserLevel function
--------------------------------

Usage: $getuserlevel(mask)

Returns the userlevel of mask in your userlist. For example, if
*!*blah@*hah.com is in your userlist with level 3,
$getuserlevel(user!nablah@spahah.com) would return 3. If the user cannot be
found in the userlist, the function will return 0.

[2.5.10.12] GetProtLevel function
--------------------------------

Usage: $getprotlevel(mask)

Returns the protlevel of mask in your protlist. If the user cannot be found in
the protlist, the function will return 0.

[2.5.10.13] IsDCCChatting function
----------------------------------

Usage: $isdccchatting(nick)

Returns 1 if a DCC Chat connection is currently open with nick, and 0 if no
DCC Chat connection is currently open with nick.

[2.5.10.14] IsOn function
-------------------------

Usage: $ison(nick channel)

Returns true (1) if nick is on channel, otherwise returns false (0). Example:

        if $ison(MeGALiTH #quake)
           Msg MeGALiTH Hi there!!
        endif

[2.5.10.15] IsOp function
-------------------------

Usage: $isop(nick channel)

Returns true (1) if nick is an op on channel. If nick is a non-op on channel,
or if nick is not on channel, returns false (0).

[2.5.10.16] IsQuerying function
-------------------------------

Usage: $isquerying(nick)

Returns 1 if a query window is currently open for nick, and 0 otherwise.

[2.5.10.17] IsVoice function
----------------------------

Usage: $isvoice(nick channel)

Returns 1 if nick, a non-op, is allowed to speak on the moderated channel
channel, and 0 if nick cannot speak, if nick is not on a moderated channel, if
nick is not on channel, or if nick is opped.

In order to find out if any user, op or otherwise, can speak on a moderated
channel, use something like:

        if ($isop($nick $channel) || $isvoice($nick $channel))
           // User can speak ...
        endif

[2.5.10.18] IsWatchdogActive function
-------------------------------------

Usage: $iswatchdogactive()

Returns 1 if the watchdog is currently enabled (and hence the main V97 window
is hidden), and 0 if the watchdog is currently disabled (the normal state -
the main V97 window is visible).

[2.5.10.19] Nicks function
--------------------------

Usage: $nicks(channel num)

Returns the num'th user on channel. For example, $nicks(#quake 45) will return
the nick of the 45th user on channel #quake (the list is sorted
alphabetically, with ops at the top, followed by peons). If channel doesn't
exist, or there is no user at num (i.e. if num is less than 1 or greater than
$nickcount), the function will return nothing.

[2.5.10.20] NickCount function
------------------------------

Usage: $nickcount(channel)

Returns the number of users on channel. If channel doesn't exist, the function
will return 0.

[2.5.10.21] NickList function
-----------------------------

Usage: $nicklist(channel)

Returns a list of all the users on channel. For example, if nick1, nick2 and
nick3 are on channel, this function would return:

        nick1 nick2 nick3

[2.5.10.22] Ops function
------------------------

Usage: $ops(channel num)

Returns the num'th op on channel. For example, $ops(#quake 3) will return the
nick of the 3rd op on channel #quake (the list is sorted alphabetically). If
channel doesn't exist, or there is no op at num (i.e. if num is less than 1 or
greater than $opcount), the function will return nothing.

[2.5.10.23] OpCount function
----------------------------

Usage: $opcount(channel)

Returns the number of ops on channel. If channel doesn't exist, or if there are
no ops, the function will return 0.

[2.5.10.24] OpList function
---------------------------

Usage: $oplist(channel)

Returns a list of all the ops on channel. For example, if nick1, nick2 and
nick3 are ops on channel, this function would return:

        nick1 nick2 nick3

[2.5.10.25] OpStrip function
----------------------------

Usage: $opstrip(nick)

Strips any trailing @ or + from nick. If, for example, you are using
the SELECTEDNICK function to get the currently-selected nick in a channel nicks
list, you must use the OPSTRIP function on the nick before performing any
operations to make sure that the op (@) and/or voice (+) prefixes are removed.

[2.5.10.26] Peons function
--------------------------

Usage: $peons(channel num)

Returns the num'th peon (non-op) on channel. For example, $peons(#quake 19)
will return the nick of the 19th peon on channel #quake (the list is sorted
alphabetically). If channel doesn't exist, or there is no peon at num (i.e. if
num is less than 1 or greater than $peoncount), the function will return
nothing.

[2.5.10.27] PeonCount function
------------------------------

Usage: $peoncount(channel)

Returns the number of peons (non-ops) on channel. If channel doesn't exist, or
if there are no peons, the function will return 0.

[2.5.10.28] PeonList function
-----------------------------

Usage: $peonlist(channel)

Returns a list of all the peons (non-ops) on channel. For example, if nick1,
nick2 and nick3 are peons on channel, this function would return:

        nick1 nick2 nick3

[2.5.10.29] QueryList function
------------------------------

Usage: $querylist()

Returns a list of all the users you have a query (private message) window open
to. For example, if you have a query window open with nick1, nick2 and nick3,
this function would return:

        nick1 nick2 nick3

[2.5.10.30] SelectedNick function
---------------------------------

Usage: $selectednick(channel)

Returns the nick selected in channel's nicks list. If channel is not a valid
channel window, or if no nick is selected in channel's nicks list, this
function will return an empty string. The nick returned may be prefixed with
op (@) and/or voice (+) flags, which should be stripped off with the OPSTRIP
function before the nick can be used with other IRC commands (e.g. MODE, KICK
etc.).

[2.5.10.31] VoiceList function
------------------------------

Usage: $voicelist(channel)

Returns a list of all the users who can speak (excluding ops) on the moderated
channel specified as the parameter. For example, if nick1, nick2 and nick3 are
+v (can speak) on the moderated channel specified as the parameter, this
function would return:

        nick1 nick2 nick3

[2.5.11] XDCC (file offer server) functions
-------------------------------------------

[2.5.11.1] GetXDCCPackCount function
------------------------------------

Usage: $getxdccpackcount()

Returns the number of XDCC packs defined in Client setup/XDCC. If no packs are
defined, this function will return 0.

[2.5.11.2] GetXDCCPackDesc function
-----------------------------------

Usage: $getxdccpackdesc(pack)

Returns the pack description for XDCC pack number pack. pack ranges from 1 to
the value returned by the GETXDCCPACKCOUNT function. If you specify an invalid
pack number, this function will return an empty string.

[2.5.11.3] GetXDCCPackFileCount function
----------------------------------------

Usage: $getxdccpackfilecount(pack)

Returns the number of files in XDCC pack number pack. pack ranges from 1 to the
value returned by the GETXDCCPACKCOUNT function. If you specify an invalid pack
number, this function will return 0.

[2.5.11.4] GetXDCCPackFiles function
------------------------------------

Usage: $getxdccpackfiles(pack)

Returns a list of files in XDCC pack number pack. Quotes (") are placed around
each filename, and the filenames (which include a full path) are separated by
spaces. pack ranges from 1 to the value returned by the GETXDCCPACKCOUNT
function. If you specify an invalid pack number, this function will return an
empty string. The PARSE EXTENDED statement can then be used to separate the
file names.

[2.5.11.5] GetXDCCPackGets function
-----------------------------------

Usage: $getxdccpackgets(pack)

Returns the number of times XDCC pack number pack has been downloaded. pack
ranges from 1 to the value returned by the GETXDCCPACKCOUNT function. If you
specify an invalid pack number, this function will return 0.

[2.5.11.6] GetXDCCPackSize function
-----------------------------------

Usage: $getxdccpacksize(pack)

Returns the total size of all the files defined in XDCC pack number pack. pack
ranges from 1 to the value returned by the GETXDCCPACKCOUNT function. If you
specify an invalid pack number, this function will return 0.

[2.5.12] DCC (chat and file transfer) functions
-----------------------------------------------

[2.5.12.1] DCCChatList
----------------------

Usage: $DCCChatList()

Returns a list of all active DCC Chat sessions (both incoming and outgoing).
The list is returned in the format of a list of =nick entries, which can then
be passed as parameters to commands that take a window ID, such as Min and
Max, or the OVS $MapObject() function (see OBJECTVS.TXT). For example, if
you're chatting to Amagosa and Mr2001, this function would return:

        =Amagosa =Mr2001

[2.5.12.2] DCCGetList
---------------------

Usage: $DCCGetList()

Returns a list of all active DCC Get and TDCC Get sessions. The list is
returned in the format of a list of *[T]GET/nick/file entires, which can then
be passed as parameters to commands that take a window ID, such as Min and
Max, or the OVS $MapObject() function (see OBJECTVS.TXT), or the $GetDCC...()
functions detailed below. For example, if you're getting README.TXT from
Amagosa by DCC and VSCRIPT.TXT from Mr2001 by TDCC, this function would return:

        *GET/Amagosa/README.TXT *TGET/Mr2001/VSCRIPT.TXT

If file names contain a space, the entries will be surrounded in quotes, e.g.:

        "*GET/Atrox/long filename.txt"

The quotes will be removed when you use the list-handling functions, for
example, $listIndex(), to extract the list elements.

Note that the filename returned here is the actual filename of the file being
written to disk, which isn't necessarily the same as the original name of the
file (the user may have opted to rename the file before receiving it).

[2.5.12.3] DCCSendList
----------------------

Returns a list of all active DCC Send and TDCC Send sessions. The list is
returned in the format of a list of *[T]SEND/nick/file entires, which can then
be passed as parameters to commands that take a window ID, such as Min and
Max, or the OVS $MapObject() function (see OBJECTVS.TXT), or the $GetDCC...()
functions detailed below. For example, if you're sending README.TXT to
Amagosa by DCC and VSCRIPT.TXT to Mr2001 by TDCC, this function would return:

        *SEND/Amagosa/README.TXT *TSEND/Mr2001/VSCRIPT.TXT

If file names contain a space, the entries will be surrounded in quotes, e.g.:

        "*SEND/Atrox/long filename.txt"

The quotes will be removed when you use the list-handling functions, for
example, $listIndex(), to extract the list elements.

Note that the filename returned here is the actual filename of the file being
written to disk, which isn't necessarily the same as the original name of the
file (the user may have opted to rename the file before receiving it).

[2.5.12.4] GetDCCSize
---------------------

Usage: $GetDCCSize(dccwindow)

Returns the size of the file being transferred in dccwindow. dccwindow is a DCC
transfer window ID, as returned by the $DCCGetList() or $DCCSendList()
functions, as detailed above. For example, if the file README.TXT that's being
sent by DCC to Amagosa is 34078 bytes large,
$GetDCCSize(*SEND/Amagosa/README.TXT) will return:

        34078

[2.5.12.5] GetDCCSpeed
---------------------

Usage: $GetDCCSpeed(dccwindow)

Returns the file transfer speed of the file being transferred in dccwindow.
dccwindow is a DCC transfer window ID, as returned by the $DCCGetList() or
$DCCSendList() functions, as detailed above. For example, if the file
README.TXT is being send by DCC to Amagosa at 2.86 kilobytes per second,
$GetDCCSpeed(*SEND/Amagosa/README.TXT) will return:

        2.86 kb/sec

[2.5.12.5] GetDCCPercent
------------------------

Usage: $GetDCCPercent(dccwindow)

Returns the percentage complete (from 0 to 100) of the file being transferred
in dccwindow. dccwindow is a DCC transfer window ID, as returned by the
$DCCGetList() or $DCCSendList() functions, as detailed above. For example, if
the file README.TXT being received by TDCC from Amagosa is 44% complete,
$GetDCCPercent(*TGET/Amagosa/README.TXT) will return:

        44

[2.5.12.6] GetDCCProgress
-------------------------

Usage: $GetDCCProgress(dccwindow)

Returns the number of bytes sent or received of the file being transferred in
dccwindow. dccwindow is a DCC transfer window ID, as returned by the
$DCCGetList() or $DCCSendList() functions, as detailed above. For example, if
24062 bytes of the file README.TXT being received by TDCC from Amagosa have
already been received, $GetDCCProgress(*TGET/Amagosa/README.TXT) will return:

        24062

[2.5.12.7] GetDCCTimeLeft
-------------------------

Usage: $GetDCCTimeLeft(dccwindow)

Returns the estimated time left to completion of the file being transferred in
dccwindow. dccwindow is a DCC transfer window ID, as returned by the
$DCCGetList() or $DCCSendList() functions, as detailed above. For example, if
the TDCC Send to Mr2001 of VSCRIPT.TXT is estimated to complete in 4 minutes
and 3 seconds, $GetDCCTimeLeft(*TSEND/Mr2001/VSCRIPT.TXT) will return:

        4 minutes and 3 seconds

[2.5.13] Inter-server communication functions
---------------------------------------------

The functions detailed below, along with the OnServer command, allow your
scripts to send data to a different IRC server connection from what the script
was run in.

[2.5.13.1] CurrentServer function
---------------------------------

Usage: $CurrentServer()

Returns the number of the active server connection. This number is the list
index of the active server connection in the list as returned by the
$ServerList() function. For example, if the first server in the list returned
by the $ServerList() function is the active server, this function will return
0, and if the second server is active, this function will return 1, and so
forth.

Note that changing the active server connection MAY WELL CHANGE THE ORDER OF
THE ITEMS IN THE LIST RETURNED BY THE $ServerList() FUNCTION. For example, you
may find that, no matter what server connection is active, this function always
returns, say, 0. This may seem counter-intuitive, but remember that item 0 in
the server connection list has actually changed instead. Make sure that your
scripts do not rely on the order of the items in the $ServerList() list staying
constant between server connections - it won't.

[2.5.13.2] ServerCount function
-------------------------------

Usage: $ServerCount()

Returns the number of open server connections. For example, if you had 3 server
windows open, and 2 of them were connected, this function would return 2.

[2.5.13.3] ServerList function
------------------------------

Usage: $ServerList()

Returns a list of all the servers you're connected to. For example, if you're
connected to irc.ionet.net port 6667 and efnet.demon.co.uk port 6666, this
function would return:

        irc.ionet.net:6667 efnet.demon.co.uk:6666

Note that changing the active server connection MAY WELL CHANGE THE ORDER OF
THE ITEMS IN THIS LIST. This may seem counter-intuitive, so make sure your
scripts do not rely on the order of the items in this list staying constant
between server connections - it won't.

[2.5.14] Miscellaneous functions
--------------------------------

[2.5.14.1] $? (text input dialog)
---------------------------------

Usage: $?="prompt"

Prompts the user to enter some text, displaying prompt in the text entry dialog
box. This is similar to mIRC's $? "function".

In 0.91 and above, you may specify some text that appears in the input section
of the box by placing |text in prompt. For example, the following line of code
will prompt you for a channel name with #virc already in the input field of the
box:

        @l $channel = $?="Enter a channel to join:|#virc"

[2.5.14.2] DecodeIP function
----------------------------

Usage: $decodeip(encodedip)

Converts encodedip (an unsigned long) into an IP address in a.b.c.d format. You
can use this function to convert encoded IP addresses (for example, in DCC
requests received from users) to user-readable format. Example:

        $decodeip(2660773201)           = 158.152.45.81

[2.5.14.3] DNS function
-----------------------

Usage: $dns(hostname)

Resolves hostname and returns the corresponding IP. If hostname cannot be
resolved for some reason (for example, if the hostname doesn't exit), the
function will return an empty string.

        $dns(megalith.co.uk) = 158.152.45.81

[2.5.14.4] EncodeIP function
----------------------------

Usage: $encodeip(IP)

Encodes IP to unsigned long format. This lets you connect to an IP address and
send stuff via a DCC Chat connection, for example, just like telnet. For
example, my mail server is 194.217.242.145, so, in a script, you could use the
following line to start an SMTP connection with my mail server:

        CTCP $N DCC CHAT chat $encodeip(194.217.242.145) 25

By faking an incoming DCC Chat connection, this neat little trick lets you do
all sorts of things, like, for example, making raw connections to IRC servers
etc. without the use of the ObjectViRCScript TSockets class.

[2.5.14.5] GetAlias function
----------------------------

Usage: $getalias(alias)

Returns the ViRCScript code of alias. Together with the SETALIAS command, the
GETALIAS function can be used to append lines of code to existing aliases.
Example:

        SetAlias DEOP = $getalias(deop)$char(13)Beep

This will add the command BEEP (preceded by a $char(13) - the new line
character) to the end of the DEOP alias.

[2.5.14.6] GetInputLine function
--------------------------------

Usage: $getinputline(window)

Gets the current contents of the command entry box in window. window can be .
(a period) for the server notices window, a channel name for a channel window,
a nick for a query window, or =nick for a DCC Chat window.

[2.5.14.7] GetWindowID function
-------------------------------

Usage: $getwindowid(window)

Returns a window ID for window. The window ID is the number in []'s in the
window's title bar. For example, $getwindowid(.) would return 2 if the
current server connection's server window was "[2] Server notices".

[2.5.14.8] MessageDlg function
------------------------------

Usage: $messagedlg(type text)

Displays a message box on the screen, of type type, which contains text, and
returns which button the user pressed. type is calculated by selecting either
none or one item from each of the 3 groups, and adding the numbers together.

Group 1:

0       Display OK button only.
1       Display OK and Cancel buttons.
2       Display Abort, Retry, and Ignore buttons.
3       Display Yes, No, and Cancel buttons.
4       Display Yes and No buttons.
5       Display Retry and Cancel buttons.

Group 2:

16      Display a STOP icon.
32      Display a question mark icon.
48      Display an exclamation mark icon.
64      Display an "i" icon.

Group 3:

0       First button is default.
256     Second button is default.
512     Third button is default.

For example, if you wanted a message dialog that had Yes and No buttons,
displayed a question mark icon, and whose second button (No) was default, you
would specify type as 292 (which is 4+32+256).

The value returned by this function depends on the button the user pressed:

1       OK button selected.
2       Cancel button selected.
3       Abort button selected.
4       Retry button selected.
5       Ignore button selected.
6       Yes button selected.
7       No button selected.

[2.5.14.9] Rand function
------------------------

Usage: $rand(n)

Returns a random integer in the range 0 to n - 1. For example, $rand(1000) may
return 0, 273, or 879, but never -112 or 1000.

