QuIRC - What do you think?

Copyright (C) 1998-2001, Patrick Earl

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

Patrick Earl - quirc@patearl.net


TABLE OF CONTENTS
-Notes
-Keys
-Commands
-Popups
-Alias System
-Event System
-General Scripting Information
-QuIRC's Start-Up Process
-UI Programming Information
-Issues To Be Aware Of
-Lacking Features And Known Bugs


NOTES

Bug reports (detailed as possible please) and patches for QuIRC are always
welcomed wholeheartedly.  If anyone would like to assist in the development
of QuIRC, let me know and we'll see what we can work out.

Special thanks to Stuart Moore (hero-) for writing the nick complete and
substantial portions of the tcl code, and for being an Alpha tester for QuIRC.

Thanks also to Wilton Wong (Atko) who was a great help in fixing the
multiserver problems as well as a few bugs that caused a seg fault on exit.

Let's have a great big round of applause for D. Richard Hipp without whose
Embedded Tk, QuIRC would not even have happened.  Thanks also for the nice
pure Tcl/Tk tree widget :)

See the INSTALL file for instructions on installing.

See the CHANGELOG file for details on what's new.

See the FAQ for a variety of information not found here.


KEYS

These are the default keys that come in config.tcl:

Control-Enter
	Sends the input without parsing it first, so lines with / can be sent
        and not interpreted as commands.

Alt-Enter
	Acts like Control-Enter only it trims space off the text before
	sending.  Is useful for dealing with data pasted from Netscape.

Shift-Enter
	Inserts a linefeed into the command line so you can run more than one
	command on the same line easily.

Control-Down
	Goes to the next window

Control-Up
	Goes to the previous window

Up
	Recalls the previous command in the history list

Down
	Recalls the next command in the history list

Shift-Prior (PgUp)
	Scrolls the currently showing text window up.

Shift-Next (PgDn)
	Scrolls the currently showing window down.

Prior
	Same as Shift-Prior

Next
	Same as Shift-Next

Control-Prior
	Scrolls the nicklist up.

Control-Next
	Scrolls the nicklist down.

Alt-Prior
	Scrolls the windowlist up.

Alt-Next
	Scrolls the windowlist down.

Control-F4
	Closes the current window.

Alt-F4
	Closes the client.

Control-c
	Inserts the color character (\x03).

Control-l
	Inserts the bold character (\x02).

Control-u
	Inserts the underline character (\x1f).

Control-_
	Inserts the underline character (\x1f).

Alt-n
	Opens the server dialog.


COMMANDS

Commands that begin with / are evaluated as aliases.  Every command not listed
here is an alias:

/lookup - Given a hostname, it will return the numeric IP for it

Commands that begin with // are evaluated as tcl expressions.  For example:

	//say My home dir is $::env(HOME)
	//say 582 divided by 17 is [expr 582/17.0]

Will be evaluated to, for example:

	/say My home dir is /home/patearl
	/say 582 divided by 17 is 34.2352941176

And will send the message "My home dir is /home/patearl" to the current
channel, query, or chat session.  For the calcuation example, you could just
use /calc 582/17.0 to acheive similar results.

Try hitting F1 for commands not listed here.

(Really) Partial list of IRCII commands supported as well as any known
differences from IRCII:
(For more information see http://www.dal.net/services/helpserv/index.html)

/abort - Simply exits.
/admin
/away
/beep
/bye
/cd
/channel


POPUPS

See the popup command below for how to implement popups.  The popups that come
with QuIRC are all in popups.tcl and it is suggested that you place your own
popups in userpopups.tcl which will be loaded by popups.tcl.  That way when you
upgrade QuIRC it won't be a concern to merge the popup changes.


ALIAS SYSTEM

There are two types of aliases, server specific aliases and global aliases.
The server specific aliases run within the namespace of the script that they
are loaded in.  The global aliases run within the global namespace.  The server
specific aliases are run before the global ones.  Any / command entered that
does not have a corresponding alias will be sent to the server as is.  If an
alias returns 1, no other aliases of the same name (in different scripts or in
the global namespace) will be executed.  Do not put more than one alias of
the same name in the same script file.

Example:

proc alias_test { arg } {
    quote "PRIVMSG [mynick] :$arg"
}

OR

alias test {
    quote "PRIVMSG [mynick] :$arg"
}

When run with:

	/test Hello there.

would message you with the message "Hello there."


EVENT SYSTEM

There are two types of events, global events and server specific events.

Global Events

There can only be one global event of any type.  If a script is loaded that has
that particular event in it, any older one will be replaced.

The return values of global events are ignored unless otherwise indicated.

proc event_windowchanged { oldpathname oldname oldserver oldindex pathname name server index } { script }
	This event is called at the start of the totop proc and is passed the
        pathnames, names, server indexes, and windowlist indexes of the old and
        new windows.

proc event_echo { message pathname new } { script }
	This event is called everytime text is to be echoed.  You must return
	the text that you actually want to be echoed.  If you return nothing,
	it will not echo anything.  You can use echotags from within this proc
	for very customized echoing.  The new parameter is used to indicate
	whether or not the window list should be activated when the text is
	printed.

proc event_enter { message pathname } { script }
	Is called (by parseentry) whenever data is entered normally in an entry
	box.  Whatever you return is what is considered to be the actual input.
	This can be used to do replacements on various data in the input or to
	cancel certain input by returning "".  If you like, you may modify the
        entry box while inside of this event.

Server Specific Events

The event system is composed of the following:

proc event_raw { prefix command args } { script }
proc event_??? { prefix args } { script }
proc event_unparsednumeric { prefix command args } { script }
proc event_unparsed { prefix command args } { script }

??? is the event (in lowercase) as sent by the server.  For example:
	privmsg or 301
$prefix corresponds to the prefix as found in the IRC RFC (doc/rfc1459.txt).
	It is often the originator of the event.  This is usually either a
	nick!user@host or a server ip.
$command is the actual command produced (exactly as returned by the server).
$args is a TCL list of any arguments following the command part of the IRC
	reply from the server.  The 0th argument often contains the target
	of the event.  See the RFC for details.  The individual arguments of
        $args can be accessed like so: [lindex $args #], where # is any
        integer between 0 and up to but not including [llength $args].

Example:

proc event_376 { prefix args } {
    quote "JOIN #mychannel"
}

The above would send the command to join #mychannel upon reception of the
end of the MOTD from the server.

Order of Event Execution:
	event_raw_unparsed
	event_raw
	Specific Events (i.e. event_privmsg or event_301)
	event_mymode(+/-)?
	event_mode(+/-)?
        Internal Events
	event_unparsednumeric
		If any previous events return 2, this event will not occur.
	event_unparsed
		If any previous events return 2, this event will not occur.

If the message is a server numeric and is not one of the known invalid
responses, mynick is set after event_raw_unparsed.

Return Values of Events:

	1 - Stop the same event (i.e. event_raw or event_privmsg) from occuring
            in any other scripts after this point.  Scripts that are loaded
            later are executed first, so the last script you load can override
            previously loaded scripts.
	2 - Stop output to the text windows from occuring.
	    (event_unparsednumeric and event_unparsed will not be called and
            any output internal to QuIRC will not be produced)
	4 - Special return for event_raw and event_mode; stops the specific
	    events from being checked. (i.e. Events like event_privmsg and
            event_mode+o will not be called.)  This now applies to
	    event_privmsg (event_ctcp, event_text) and event_notice
	    (event_noticetext, event_ctcpreply).

As an example, "return 7" would stop everything past that point.

IRC Message Events:
	proc event_raw_unparsed { data } { script }
	proc event_raw { prefix command args } { script }
	proc event_mode { prefix args } { script }
	proc event_mymode+? { prefix args } { script }
		? is any letter of the alphabet.  Gets executed when a
                non-channel mode event occurs (ie. Personal mode change)
	proc event_mymode-? { prefix args } { script }
		Same as mymode only the removal of the mode instead of
	        the addition.		
	proc event_mode+v { prefix target parameter } { script }
	proc event_mode-v { prefix target parameter } { script }
	proc event_mode+b { prefix target parameter } { script }
	proc event_mode-b { prefix target parameter } { script }
	proc event_mode+l { prefix target parameter } { script }
	proc event_mode+k { prefix target parameter } { script }
	proc event_mode-k { prefix target parameter } { script }
	proc event_mode+o { prefix target parameter } { script }
	proc event_mode-o { prefix target parameter } { script }
	proc event_mode+? { prefix target } { script }
		Channel modes that aren't covered above.
	proc event_mode-? { prefix target } { script }
	proc event_text { prefix target text } { script }
		This event occurs when a privmsg, with some portion of it not
		being CTCP, occurs.  text is the data in the privmsg with the
		CTCP messages removed.
	proc event_ctcp { prefix target ctcps } { script }
		This occurs when a privmsg occurs with CTCP data.  ctcps is a
		list of data pairs.  In each pair, the first item is the ctcp
		name, the second item is the extra data if any.
	proc event_noticetext { prefix target text } { script }
	proc event_ctcpreply { prefix target ctcps } { script }
		These two events are the equivalent of event_text and
		event_ctcp only they are used for the replies instead of the
		queries.

Other Events:
        proc event_unload {} { script }
	proc event_disconnect {} { script }
	proc event_connect () { script }
		-Happens immediately after socket is connected before any data
		 is sent.


GENERAL SCRIPTING INFORMATION

Each script is loaded into its own namespace.  To access script-wide variables
you should use [set ::[index]::scriptname::variablename], otherwise standard
namespace conventions apply.  See the tcl man page for namespace for details.

Each server has its own namespace, given by ::<serveridx>.  Scripts are loaded
under that namespace as ::<serveridx>::<script_name>, where script_name is
the first part of the script file name that contains only alphanumeric
characters.

The way QuIRC determines which server a given command originated from is that
it checks the name of the proc it was called from.  For example:

	proc ::4::some_script::some_procname {
	    /msg [mynick] hi
        }

will run the /msg command as if it was typed in server 4.  As another example:

	proc some_procname {
	    quote "bleh"
        }

will not know which server to use the quote command on because it wasn't run
from a proc within any server's namespace.  In this case, only global commands
or aliases are allowed.

There are various types of commands which can be run:
	Regular Tcl Commands
	Templated Server Tcl Commands
        Global Aliases
        Server Specific Aliases
        Server Commands

Templated Server Tcl Commands are used in the following manner.  First a proc
is created in the ::template namespace as follows:

	proc ::template::procname { serverindex args } {
        }

After that, whenever procname is executed within a server's namespace (as shown
previously), ::template::procname will be invoked and it will be passed the
server's index as well as the arguments that were given.

Global Aliases are aliases that are created in the global namespace and are
run like this:

	/aliasname regular tcl args

Note that unlike aliases typed in at the command line, the arguments given must
be valid TCL.

Server Specific Aliases are like Global Aliases, but run in the namespace of
the server that they were created in.

Server Commands have the following format:

	/command args

Basically anything that isn't handled by an alias will be sent to the server as
"command args".

To run a command on another server, run:

	evalserver <serveridx> <script>
or:

	namespace eval ::<serveridx> <script>


If you need to escape a string to avoid problems with characters like ", {, $,
[, etc, using pure TCL, I suggest the following:

	[string range [list "\x7d$var"] 2 end]

This is the equivalent to QuIRC's:

	[escape $var]


In QuIRC, if a disconnect is detected, it will check if the auto_reconnect
variable is set.  If it is set, it will then check to see if the connect was
on purpose, in which case the ::[index]::intentional_disconnect variable will
be set to 1.  If it was on purpose, no reconnect will occur, otherwise QuIRC
will attempt reconnection with small delays.  ::template::condis is the proc


QuIRC'S START-UP PROCESS

If you would like to see the techical details as to how QuIRC starts, you will
want to examine the bottom of quirc.cc from the source.  It is well commented
and you shouldn't have many problems seeing what happens.


UI PROGRAMMING INFORMATION

A lot of the UI is handled through qwidgets.tcl.  See that file for info.

* QEntryBox

The QEntryBox widget is used to provide a quick dialog box for entering in
information.  Here is an example of it in use in a popup:

popup add item channeltext "" "Set Keyword (+k)" {
    QEntryBox::create "Channel Keyword" "Enter new keyword for channel:" "::template::quote [index] \"MODE \[channel] +k %g\""
}

The syntax is:
    QEntryBox::create <window title> <message> <command>

Any occurence of %g in the command will be replaced with the results of the
message box.  Note also that the command is run in the global namespace, so
if you need it to send data to a server or something you would need to
specify the server like I did in the example.  You could also use some
form of the tcl namespace command to do that.

QEntryBox returns the the name of the toplevel window it created.  You might
use it with tkwait to make the dialog box modal.

* QPasswordBox

Identical to QEntryBox, only it uses *'s in the box to hide what you're typing.

* QColorChooser

To pop up a little color chooser window that lets users pick one of the current
16 colors, run:

	QColorChooser command

The command will run like so:

	command <color number (0-15)>

If the window is just closed, the command will not be run.  If you want to
modify the window after you run the QColorChooser command, the window is called
.colorchooser.  Only one should be run at a time.

An example of use would be:

	QColorChooser {set ::default_foreground}


ISSUES TO BE AWARE OF

The ANSI system does not handle cases where there is = or " in the given code.
This does not affect the operation for normal IRC type ANSI, but could cause
display of parts of the code if used.  If you encounter this, let me know and
I will do something about it, otherwise it will stay this way.

In order to stop the automatic scrolling in a window due to new text being
inserted, simply move the scrollbar up so it is not at the very bottom.


LACKING FEATURES AND KNOWN BUGS

  A number of these features are easy to implement, however there are so many
  easy things that need done it amounts to tons of work for me.  If there is a
  feature here that you feel you could do, please implement it and send me the
  patch.  I will be happy to include it in the distribution.

  If you encounter any of these bugs, information on where and how it occured
  would be of great help.  If the client cores, please do a "bt" on the core
  in gdb.  The more descriptive the bug report, the more likely I'll be able
  to find the bug.  If you can make a patch for it yourself, all the better :)

  The list has moved to http://quirc.org/cgi/bugs.cgi.

Enjoy!  Patrick Earl (Hynato on irc.dal.net, quirc@patearl.net)
