Gaim Tcl plugin-writing HOWTO

INTRODUCTION

The Gaim Tcl interface provides a Tcl API for many useful gaim
functions.  Like the perl API, the Tcl API does not provide access to
every corner of gaim exposed by the C interface.  It does, however,
provide a very powerful interface to many of Gaim's functions through
a simple to learn and extend scripting language.

If you are not familiar with Tcl, you will probably find it somewhat
different from what you are used to.  Despite being somewhat unique
(more akin to shell programming than other traditional scripting
languages such as perl or python), it is simple to learn for beginners
and experienced programmers alike.  There are numerous books on the
subject, we will not discuss it any further here.

GETTING STARTED

The only requirement placed on a Gaim Tcl script by Gaim is the
existence of a procedure called 'plugin_init'.  This procedure has
some limitations placed upon it; it will be parsed and evaluated
before the rest of the Tcl script, so it cannot reference any other
variables or procedures declared in the script.  In practice this is
not a problem, as the only thing this procedure should do is return a
simple list containing five items: the name of the script, its version
number, a summary (just a few words) of its function, a short (longer
than the summary, but no more than a couple of sentences if possible)
description, the author, and a web page.  For example:

proc plugin_init { } {
  return [ list "Example Plugin" \
                "1.0" \
		"Example plugin registration" \
		"Example of how to register a plugin for the Tcl HOWTO" \
		"Ethan Blanton <eblanton@cs.purdue.edu>" \
		"http://gaim.sf.net/" ]
}

The rest of the script will generally be registration to recieve
notification of various Gaim signals (more about this below) and
definitions of procedures to be executed when those signals occur.

INTERPRETER DETAILS

Gaim initializes and drives the Tcl event loop (similar to Tk),
meaning that commands like fileevent and after are available and
do not require 'vwait' etc.  'vwait' actually seems to be somewhat
broken due to a bug somewhere in the Tcl/Glib event loop glue, and it
should not be used for now.

The gaim-specific functions are provided in a statically-linked
package called 'gaim'; this means that if you spawn a child
interpreter and wish to use the gaim-specific functions, you will need
to execute 'load {} gaim' in that interpreter.

GAIM INTERNAL PROCEDURES AND VARIABLES

All of the information provided for your use by Gaim will be in the
::gaim namespace.  This means that in order to access it you will
either have to import the gaim namespace (e.g. via the command
'namespace import gaim::*') or reference it explicitly.  The following
descriptions will reference it explicitly for clarity.

* Variables

gaim::version

  This contains the version of the gaim process which loaded the
  script.

* Commands

gaim::account alias account
gaim::account connect account
gaim::account connection account
gaim::account disconnect account
gaim::account find username protocol
gaim::account handle
gaim::account isconnected account
gaim::account list ?option?
gaim::account protocol account
gaim::account username account

  The 'gaim::account' command consists of a set of subcommands
  pertaining to gaim accounts.

  'alias' returns the alias for the account 'account'.  If there is no
  alias for the given account, it returns the empty string.

  The subcommand 'connect' connects the named account if it is not
  connected, and does nothing if it is.  In either case, it returns
  the gc for the account.

  'connection' returns the gc of the given account if it is connected,
  or 0 if it is not.  This gc is the gc used by gaim::connection and
  other functions.

  'disconnect' disconnects the given account if it is connected, or
  does nothing if it is.

  'find' finds an account by its username and protocol (as returned by
  'gaim::account username' and 'gaim::account protocol') and returns
  the account if found, or 0 otherwise.

  'handle' returns the instance handle required to connect to account
  signals.  (See 'gaim::signal connect').

  The 'isconnected' query returns true if the given account is
  connected and false otherwise.

  The 'list' subcommand returns a list of all of the accounts known to
  Gaim.  The elements of this lists are accounts appropriate for the
  'account' argument of the other subcommands.  The '-all' option
  (default) returns all accounts, while the '-online' option returns
  only those accounts which are online.

  The 'protocol' subcommand returns the protocol ID (e.g. "prpl-msn")
  for the given account.

  The 'username' subcommand returns the username for the account
  'account'.

gaim::buddy alias buddy
gaim::buddy handle
gaim::buddy info ( buddy | account username )
gaim::buddy list

  'gaim::buddy' is a set of commands for retrieving information about
  buddies and manipulating the buddy list.  For the purposes of Tcl,
  a "buddy" is currently a list of several elements, the first of
  which being the type.  The currently recognized types are "group",
  "buddy", and "chat".  A group node looks like:
	{ group name { buddies } }
  A buddy node is:
	{ buddy name account }
  And a chat node is:
	{ chat alias account }

  The 'alias' subcommand returns the alias for the given buddy if it
  exists, or the empty string if it does not.

  'handle' returns the blist handle for the purposes of connecting
  signals to buddy list events.  (See 'gaim::signal connect').

  'info' causes gaim to display the info dialog for the given buddy.
  Since it is possible to request user info for a buddy not in your
  buddy list, you may also specify a buddy by his or her username and
  the account through which you wish to retrieve info.

  'list' returns a list of 'group' structures, filled out with buddies
  and chats as described above.

gaim::connection account gc
gaim::connection displayname gc
gaim::connection handle
gaim::connection list

  'gaim::connection' is a collection of subcommands pertaining to
  account connections.

  'account' returns the Gaim account associated with 'gc'.  This
  account is the same account used by gaim::account and other
  commands.

  'displayname' returns the display name (duh) of 'gc' as reported by
  gaim_connection_get_display_name(gc).

  'handle' returns the gaim connections instance handle.  (See
  'gaim::signal connect').

  'list' returns a list of all known connections.  The elements of
  this list are appropriate as 'gc' arguments to the other
  gaim::connection subcommands or other commands requiring a gc.


gaim::conv_send account who text

  'gaim::conv' is simply a convenience wrapper for 'gaim::send_im' and
  'gaim::conversation write'.  It sends the IM, determines the from
  and to arguments for 'gaim::conversation write', and prints the text
  sent to the conversation as one would expect.  For the curious, you
  may view the source for it by typing 'info body gaim::conv_send' at
  a Gaim Commander prompt.

  Note that an error in either gaim::send_im or 'gaim::conversation
  write' will not be caught by this procedure, and will be propagated
  to the caller.

gaim::conversation find ?-account account? name
gaim::conversation handle
gaim::conversation list
gaim::conversation new ?-chat? ?-im? account name
gaim::conversation write conversation style from to text

  'gaim::conversation' provides an API for dealing with conversations.
  Given that Gaim is an instant messenger program, you'll probably
  spend a lot of time here.

  The command 'find' attempts to find an existing conversation with
  username 'name'.  If the '-account' option is given, it refines its
  search to include only conversations on that account.

  'handle' returns the conversations instance handle for the purposes
  of signal connection.  (See 'gaim::signal connect').

  'list' returns a list of all currently open conversations.

  The 'new' subcommand can be used to create a new conversation with
  a specified user on a specified account if one does not exist, or
  retrieve the existing conversation if it does.  The '-chat' and
  '-im' options specify whether the created conversation should be a
  chat or a standard IM, respectively.

  'write' is used to write to the specified conversation.  The 'style'
  argument specifies how the text should be printed -- as text coming
  from the gaim user (style 'send'), being sent to the gaim user
  (style 'recv'), or as a system message (such as "so-and-so has
  signed off", style 'system').  From is the name to whom the text
  should be attributed -- you probably want to check for aliases here,
  lest you confuse the user.  'text' is the text to print.

gaim::core handle
gaim::core quit

  This command exposes functionality provided by the gaim core API.

  'gaim::core handle' returns a handle to the gaim core for signal
  connection.  (See 'gaim::signal connect').

  'quit' exits gaim cleanly, and should be used in preference to the
  tcl 'exit' command.  (Note that 'exit' has not been removed,
  however.)

gaim::debug level category message

  Equivalent to the C gaim_debug function, this command outputs
  debugging information to the gaim debug window (or stdout if gaim is
  invoked with -n).  The valid levels are, in increasing level of
  severity, -misc, -info, -warning, and -error.  'category' is a short
  (a few characters ... for instance, "tcl" or "tcl plugin") "topic"
  type name for this message, and 'message' is the text of the
  message. In the style of Tcl 'puts' (and differing from gaim_debug),
  no trailing \n is required.  (However, embedded newlines may be
  generated with \n).

gaim::notify ?type? title primary secondary

  Also a direct equivalent to a C function, gaim_notify, this command
  causes gaim to present the provided notification information to the
  user via some appropriate UI method.  The 'type' argument, if
  present, must be one of -error, -warning, or -info. The following
  three arguments' absolute meanings may vary with the Gaim UI being
  used (presently only a Gtk2 UI is available), but 'title' should
  generally be the title of the window, and 'primary' and 'secondary'
  text within that window; in the Gtk2 UI, 'primary' is slightly
  larger than 'secondary' and displayed in a boldface font.

gaim::send_im gc who text

  This sends an IM in the fashion of serv_send_im.  'gc' is the GC of
  the connection on which you wish to send (as returned by most event
  handlers), 'who' is the nick of the buddy to which you wish to send,
  and 'text' is the text of the message.

gaim::signal connect instance signal args proc
gaim::signal disconnect instance signal

  'gaim::signal' is a set of subcommands for dealing with gaim signals
  (known as "events" prior to gaim 0.68).

  The 'connect' subcommand registers the procedure 'proc' as a handler
  for the signal 'signal' on the instance 'instance'.  'instance'
  should be an instance handle as returned by one of the 'handle'
  commands from the various parts of gaim. 'args' and 'proc' are as in
  the Tcl 'proc' command; note that the number of arguments in 'args'
  must match the number of arguments emitted by the signal exactly,
  although you need not use them all.  The procedure 'proc' may be
  either a simple command or a procedure in curly brackets.  Note that
  only one procedure may be associated with each signal; an attempt to
  connect a second procedure to the same signal will remove the
  existing binding and replace it with the new procedure.
  'gaim::signal connect' returns 0 on success and 1 on failure.

  'disconnect' removes any existing signal handler for the named
  signal and instance.

gaim::unload

  This unloads the current plugin.  Note that preferences will not be
  updated (yet).

SIGNALS

Check the file SIGNALS for the meaning of these signals; this is
intended to be a list only of their arguments.  Signal callbacks will
be made in their own namespace, and arguments to those signal
callbacks will live in the namespace 'event' underneath that
namespace.  To briefly illustrate, the signal receiving-im-msg is
provided with three arguments; the account on which the IM was
received, the screen name of the user sending the IM, and the text of
the IM.  These arguments live in the variables event::account,
event::sender, and event::buffer, respectively.  Therefore a callback
which notifies the user of an incoming IM containing the word 'shizzle'
might look like this:

gaim::signal connect [gaim::conversation handle] receiving-im-msg {
	if {[ string match "*shizzle*" $event::buffer ]} {
		gaim::notify -info "tcl plugin" "Fo' shizzle" \
			"$event::sender is down with the shizzle"
	}
}

Note that for some signals (notably receiving-im-msg, sending-im-msg,
and their chat counterparts), changes to the event arguments will
change the message itself from Gaim's vantage.  For those signals
whose return value is meaningful, returning a value from the Tcl event
