
This IRC client is a faithful XiRCON [1] clone regarding how the user scripting operates. Here are some screenshots:
- Doing Japanese:

- Doing Chinese:

- Doing Klingon (in utf-8 over IRC and back using the CTCP/2 method of escaping):

- Elvish (layer 1 ConScript):

- being normal (boring):

The client has been painfully designed to be 2 complimentary halves:
- The back-end : The irc_engine Tcl extension DLL (100% Tcl API only, with a little STL) for handling everything that is not seen (ie. sockets, scripts, default behavior, IAL, etc..).
- The UI : Whatever UI the user prefers according to the command control API. It could done in Tk, an implimentation in curses, Win32 GUI, or as odd as streaming html output with form input for posting.
The IRC_Engine back-end --The irc_engine extension provides a single Incr Tcl class. The UI half (partialy undefined) also provides an Incr Tcl class. The two are brought together using inheritence like so:
source irc_engine.itcl # =============================================================== # By selecting which IRC::ui class is sourced, we can switch # to what UI we want to use. # =============================================================== source irc_ui.itcl itcl::class IRC::connection { # =============================================== # Bring the 2 halves together using inheritence. # =============================================== inherit engine ui constructor {args} { eval engine::constructor $args } {} public method destroy {} {itcl::delete object $this} } ### Create a connection instance with a couple user scripts. set a [IRC::connection #auto someUserScript1.tcl someUserScript2.tcl] ### Connect to IRC. $a connect irc.qeast.net davygrvy DG {yo moma!}In the above, $a is now the connection object. All behavior of the engine is located in a script file called default.tcl [2]. The behavior of irc_engine can be scripted by the user by loading scripts which are queried for event hooks prior to doing the default behavior. I do have a generic framework to the system, but only Tcl is supported. I have code started for perl, python, and java, but I'll have to get back to it later [3].Here's where it gets interesting for user scripts.. Each tcl user script is run in its own interpreter. It maintains some of its own commands such as [IRC::on], but aliases most up to the global interp (I also call it the controlling or UI interp). So from the script, a call to IRC::echo ... will alias up to the global as connection0 echo ... where connection0 is the Incr Tcl object. This allows us to have our scripts track with their connection object. Where this gets more interesting is that from this aliasing, I can assume commands that will be in the top-most object that are provided by the UI (thanks to inheritence). The echo method is located in the UI half, yet the user script is in a separate interp of the irc_engine extension half and always linked to its parent object.irc_engine uses Tcl's event loop. This diagram shows some of the code paths:


echo "\006CC\006***\006C\006 [event] [join [lrange [args] 1 end]]" statusWithout the debugging mode, no red color or event code is displayed. Same as:
echo "*** [join [lrange [args] 1 end]]" status
Here's an example of the user scripting and how identical it is to the idea of XiRCON. Old-time XiRCON'ers will notice, of course, the new use of namespaces and the msgcat package for handling multilingual strings. We must improve on XiRCON, too.
package require Xircon 2.0 namespace eval ::IRC { on PRIVMSG { set dest [lindex [args] 0] set msg [lindex [args] 1] ### ignore an empty one. if {![string length $msg]} {complete; return} if {![icomp $dest [my_nick]]} { ### private msg echo "[color highlight]*[color nick][nick][color highlight]*[color private] $msg" query [nick] } elseif {[string index $dest 0] == "\$"} { ### server (global) message echo "[color highlight]<[color nick][nick][color highlight]>[color default] $msg" status } else { echo "[color highlight]<[color nick][nick][color highlight]>[color default] $msg" channel $dest } complete } on $RPL_TOPICWHOTIME { echo "[color change]*** [mc {Topic for}] [color channel][lindex [args] 1][color change] [mc {was set by}] [color nick][lindex [args] 2][color change] [mc {on}] [clock format [lindex [args] 3]]" complete } on $RPL_UMODEIS { echo "[color change]*** [mc {Your modes are}] [color mode]\"[join [lrange [args] 1 end]]\"" status complete } }As in XiRCON, these are the commands available to an event hook for asking about the line that fired the event:

The UI Half --The first major feature is the support of ALL embedded text attributes ever known to mankind and robots alike. It supports ircII, mIrc, ANSI, besirc/hydra, and CTCP/2. As CTCP/2 is the most in features, this is the native usage of the display. The other attribute types are pre-translated up to CTCP/2. The CTCP/2 parser is also in the IRC_Engine as an Itcl class for use by Tk applications.CTCP/2 embedded text attributes are described @ http://www.lag.net/~robey/ctcp


(5:28 PM 11/13/2003)I put the test RichEdit terminal window into an MDI frame and used TES to run tcl, so I'm getting closer to a real GUI on win32. Mine is on the left. The goal is to clone the one on the right. None of the menus or toolbar button do anything yet, so I'm using tkcon to control the windows at the moment. The connect dialog is next on the list. Conceptually, all it will do is Tcl_Eval("$a connect ..."); just like I'm doing from tkcon. Sweet, eh? A global interp for controlling the behavior of the app is truly a beautiful thing. I will retain this wonderful concept as much and as deeply as I can for all aspects of the GUI. I'll even store settings in tcl variables.. Who needs C++ for everything? Just make a shell and use Tcl for the logic.. Oh.. That's right.. JO states this in [13]

LRESULT CALLBACK StatBoxWndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { MDICREATESTRUCT *lpCreateParams; AllWin32StatBoxThreadedGUI *pStatGUI = reinterpret_cast <AllWin32StatBoxThreadedGUI *> (::GetWindowLongPtr (hwnd, GWLP_USERDATA)); switch (iMsg) { case WM_CREATE: // move the AllWin32StatBoxThreadedGUI class pointer into the // userdata of the window. // lpCreateParams = (MDICREATESTRUCT *)((CREATESTRUCT *)lParam)->lpCreateParams; ::SetWindowLongPtr (hwnd, GWLP_USERDATA, static_cast <LONG_PTR>(lpCreateParams->lParam)); ....It's first an LPCREATESTRUCT as with CreateWindow, and the ->lpCreateParams is not our answer but an LPMDICREATESTRUCT, then we get ->lParam from that for the answer... What a mess.
NEW! (4:05 PM 11/16/2003)Just added a new MDI child window type to act as a container for Tk [14] [15] . The container protocol seems to be missing the ability to resize, though. I'll leave this for now, and move forward instead of banging my head on the desk trying to fix Tk's broken container protocol. It's fine for the Tcl/Tk Tclet Plugin as it's toplevel doesn't ever get resized.

(4:25 PM 2/9/2008)If this is a blog, I sure am slow to ever post anything. I mainly started this page as a place to write notes to myself essentially (pretending to explain to others my weird little project). So here is another little note to myself..I did prove that my back-end irc_engine.dll could run on tclhttpd and serve live IRC with html and an unending server connection (transfer-coding = "chunked") which was a fun tclhttpd patch to write. Although my main computer is down today with a sick harddrive controller, it will return and my IRC gateway to the Tcl Chatroom will be alive again:http://www.pobox.com/~davygrvy/chat/tcl
