home *** CD-ROM | disk | FTP | other *** search
/ ftp.swcp.com / ftp.swcp.com.zip / ftp.swcp.com / mac / mozilla-mac-0.9.sea.hqx / mozilla-mac-0.9 / Chrome / chatzilla.jar / content / chatzilla / handlers.js < prev    next >
Text File  |  2001-05-05  |  67KB  |  2,578 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2.  *
  3.  * The contents of this file are subject to the Mozilla Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/MPL/
  7.  *
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  *
  13.  * The Original Code is ChatZilla
  14.  *
  15.  * The Initial Developer of the Original Code is New Dimensions Consulting,
  16.  * Inc. Portions created by New Dimensions Consulting, Inc. are
  17.  * Copyright (C) 1999 New Dimenstions Consulting, Inc. All
  18.  * Rights Reserved.
  19.  *
  20.  * Contributor(s):
  21.  *  Robert Ginda, rginda@ndcico.com, original author
  22.  */
  23.  
  24. function onLoad()
  25. {
  26.     
  27.     initHost(client);
  28.     readIRCPrefs();
  29.     setClientOutput();
  30.     initStatic();
  31.     mainStep();
  32. }
  33.  
  34. function onUnload()
  35. {
  36.  
  37.     if (client.SAVE_SETTINGS)
  38.         writeIRCPrefs();
  39.     
  40.     client.quit ("ChatZilla 0.8 [" + navigator.userAgent + "]");
  41.     
  42. }
  43.  
  44. function onNotImplemented()
  45. {
  46.  
  47.     alert ("``We're accepting patches''");
  48.     
  49. }
  50.  
  51. /* toolbaritem click */
  52. function onTBIClick (id)
  53. {
  54.     
  55.     var tbi = document.getElementById (id);
  56.     var view = client.viewsArray[tbi.getAttribute("viewKey")];
  57.  
  58.     setCurrentObject (view.source);
  59.     
  60. }
  61.  
  62. /* popup click in user list */
  63. function onUserListPopupClick (e)
  64. {
  65.  
  66.     var code = e.target.getAttribute("code");
  67.     var ary = code.substr(1, code.length).match (/(\S+)? ?(.*)/);    
  68.  
  69.     if (!ary)
  70.         return;
  71.  
  72.     var command = ary[1];
  73.  
  74.     var ev = new CEvent ("client", "input-command", client,
  75.                          "onInputCommand");
  76.     ev.command = command;
  77.     ev.inputData =  ary[2] ? stringTrim(ary[2]) : "";    
  78.     ev.target = client.currentObject;
  79.  
  80.     getObjectDetails (ev.target, ev);
  81.  
  82.     client.eventPump.addEvent (ev);
  83. }
  84.  
  85.  
  86. function onToggleTraceHook()
  87. {
  88.     var h = client.eventPump.getHook ("event-tracer");
  89.     
  90.     h.enabled = client.debugMode = !h.enabled;
  91.     document.getElementById("menu-dmessages").setAttribute ("checked",
  92.                                                             h.enabled);
  93.     
  94. }
  95.  
  96. function onToggleSaveOnExit()
  97. {
  98.     client.SAVE_SETTINGS = !client.SAVE_SETTINGS;
  99.     var m = document.getElementById ("menu-settings-autosave");
  100.     m.setAttribute ("checked", String(client.SAVE_SETTINGS));
  101.  
  102.     var pref =
  103.         Components.classes["@mozilla.org/preferences;1"].createInstance(Components.interfaces.nsIPref);
  104.  
  105.     pref.SetBoolPref ("extensions.irc.settings.autoSave",
  106.                       client.SAVE_SETTINGS);
  107. }
  108.  
  109. function onToggleVisibility(thing)
  110. {    
  111.     var menu = document.getElementById("menu-view-" + thing);
  112.     var ids = new Array();
  113.     
  114.     switch (thing)
  115.     {
  116.         case "toolbar":
  117.             ids = ["views-tbar"];
  118.             break;
  119.             
  120.         case "info":
  121.             ids = ["user-list-box", "main-splitter"];            
  122.             break;
  123.             
  124.         case "status":
  125.             ids = ["status-bar-tbar"];
  126.             break;
  127.  
  128.         default:
  129.             dd ("** Unknown element ``" + menuId + 
  130.                 "'' passed to onToggleVisibility. **");
  131.             return;
  132.     }
  133.  
  134.  
  135.     var newState;
  136.     var elem = document.getElementById(ids[0]);
  137.     var d = elem.getAttribute("collapsed");
  138.     
  139.     if (d == "true")
  140.     {
  141.         newState = "false";
  142.         menu.setAttribute ("checked", "true");
  143.         client.uiState[thing] = true;
  144.     }
  145.     else
  146.     {
  147.         newState = "true";
  148.         menu.setAttribute ("checked", "false");
  149.         client.uiState[thing] = false;
  150.     }
  151.     
  152.     for (var i in ids)
  153.     {
  154.         elem = document.getElementById(ids[i]);
  155.         elem.setAttribute ("collapsed", newState);
  156.     }
  157.  
  158.     updateTitle();
  159.  
  160. }
  161.  
  162. function onDoStyleChange (newStyle)
  163. {
  164.  
  165.     if (newStyle == "other")
  166.         newStyle = window.prompt ("Enter stylesheet filename " +
  167.                                   "(relative to chrome://chatzilla/skin/)");
  168.  
  169.     if (newStyle)
  170.     {
  171.         setOutputStyle (newStyle);
  172.         setCurrentObject(client.currentObject);
  173.     }
  174.     
  175. }
  176.  
  177. function onHideCurrentView()
  178. {
  179.     var tb = getTBForObject(client.currentObject);
  180.     
  181.     if (tb)
  182.     {
  183.         var i = deleteToolbutton (tb);
  184.         if (i != -1)
  185.         {
  186.             if (i >= client.viewsArray.length)
  187.                 i = client.viewsArray.length - 1;
  188.             
  189.             setCurrentObject (client.viewsArray[i].source);
  190.         }
  191.         
  192.     }
  193.     
  194. }
  195.  
  196. function onDeleteCurrentView()
  197. {
  198.     var tb = getTBForObject(client.currentObject);
  199.     if (client.viewsArray.length < 2)
  200.     {
  201.         client.currentObject.display ("Cannot delete last view.", "ERROR");
  202.         return;
  203.     }
  204.     
  205.     if (tb)
  206.     {
  207.         var i = deleteToolbutton (tb);
  208.         if (i != -1)
  209.         {
  210.             delete client.currentObject.messages;
  211.  
  212.             if (i >= client.viewsArray.length)
  213.                 i = client.viewsArray.length - 1;            
  214.             setCurrentObject (client.viewsArray[i].source);
  215.         }
  216.         
  217.     }
  218.     
  219. }
  220.  
  221. function onClearCurrentView()
  222. {
  223.  
  224.     if (client.output.firstChild)
  225.         client.output.removeChild (client.output.firstChild);
  226.  
  227.     client.currentObject.messages = (void 0);
  228.     delete client.currentObject.messages;
  229.  
  230.     client.currentObject.display ("Messages Cleared.", "INFO");
  231.  
  232.     client.output.appendChild (client.currentObject.messages);
  233.     
  234. }
  235.  
  236. function onSortCol(sortColName)
  237. {
  238.     const nsIXULSortService = Components.interfaces.nsIXULSortService;
  239.    /* XXX remove the rdf version once 0.8 is a distant memory
  240.     * 2/22/2001
  241.     */
  242.     const isupports_uri =
  243.         (Components.classes["@mozilla.org/xul/xul-sort-service;1"]) ?
  244.          "@mozilla.org/xul/xul-sort-service;1" :
  245.          "@mozilla.org/rdf/xul-sort-service;1";
  246.     
  247.     var node = document.getElementById(sortColName);
  248.     if (!node)
  249.         return false;
  250.  
  251.     // determine column resource to sort on
  252.     var sortResource = node.getAttribute("resource");
  253.     var sortDirection = "ascending";
  254.         //node.setAttribute("sortActive", "true");
  255.  
  256.     switch (sortColName)
  257.     {
  258.         case "usercol-op":
  259.             document.getElementById("usercol-voice")
  260.                 .setAttribute("sortDirection", "natural");
  261.             document.getElementById("usercol-nick")
  262.                 .setAttribute("sortDirection", "natural");
  263.             break;
  264.         case "usercol-voice":
  265.             document.getElementById("usercol-op")
  266.                 .setAttribute("sortDirection", "natural");
  267.             document.getElementById("usercol-nick")
  268.                 .setAttribute("sortDirection", "natural");
  269.             break;
  270.         case "usercol-nick":
  271.             document.getElementById("usercol-voice")
  272.                 .setAttribute("sortDirection", "natural");
  273.             document.getElementById("usercol-op")
  274.                 .setAttribute("sortDirection", "natural");
  275.             break;
  276.     }
  277.     
  278.     var currentDirection = node.getAttribute("sortDirection");
  279.     
  280.     if (currentDirection == "ascending")
  281.         sortDirection = "descending";
  282.     else if (currentDirection == "descending")
  283.         sortDirection = "natural";
  284.     else
  285.         sortDirection = "ascending";
  286.     
  287.     node.setAttribute ("sortDirection", sortDirection);
  288.  
  289.     var xulSortService =
  290.         Components.classes[isupports_uri].getService(nsIXULSortService);
  291.     if (!xulSortService)
  292.         return false;
  293.     try
  294.     {
  295.         xulSortService.Sort(node, sortResource, sortDirection);
  296.     }
  297.     catch(ex)
  298.     {
  299.             //dd("Exception calling xulSortService.Sort()");
  300.     }
  301.     
  302.     return false;
  303. }
  304.  
  305. function onToggleMunger()
  306. {
  307.  
  308.     client.munger.enabled = !client.munger.enabled;
  309.     document.getElementById("menu-munger").setAttribute ("checked",
  310.                                                          client.munger.enabled);
  311.  
  312. }
  313.  
  314. function onMultilineInputKeyUp (e)
  315. {
  316.     if (e.ctrlKey && e.keyCode == 13)
  317.     {
  318.         /* ctrl-enter, execute buffer */
  319.         e.line = e.target.value;
  320.         onInputCompleteLine (e);
  321.     }
  322.     else
  323.         if (e.ctrlKey && e.keyCode == 40)
  324.             /* ctrl-down, switch to single line mode */
  325.             multilineInputMode (false);
  326. }
  327.  
  328. function onInputKeyUp (e)
  329. {
  330.     
  331.     switch (e.keyCode)
  332.     {        
  333.         case 13: /* CR */
  334.             e.line = e.target.value;
  335.             onInputCompleteLine (e);
  336.             e.target.value = "";            
  337.             break;
  338.  
  339.         case 38: /* up */
  340.             if (e.ctrlKey)  /* ctrl-up, switch to multi line mode */
  341.                 multilineInputMode (true);
  342.             else
  343.                 if (client.lastHistoryReferenced <
  344.                     client.inputHistory.length - 1)
  345.                     e.target.value =
  346.                     client.inputHistory[++client.lastHistoryReferenced];
  347.             break;
  348.  
  349.         case 40: /* down */
  350.             if (client.lastHistoryReferenced > 0)
  351.                 e.target.value =
  352.                     client.inputHistory[--client.lastHistoryReferenced];
  353.             else
  354.             {
  355.                 client.lastHistoryReferenced = -1;
  356.                 e.target.value = client.incompleteLine;
  357.             }
  358.             
  359.             break;
  360.  
  361.         case 9: /* tab */
  362.             e.preventDefault();
  363.             onTabCompleteRequest(e);
  364.             break;       
  365.             
  366.         default:
  367.             client.incompleteLine = e.target.value;
  368.             
  369.     }
  370.  
  371. }
  372.  
  373. function onTabCompleteRequest (e)
  374. {
  375.     var selStart = e.target.selectionStart;
  376.     var selEnd = e.target.selectionEnd;            
  377.     var v = e.target.value;
  378.  
  379.     if (selStart != selEnd) 
  380.     {
  381.         /* text is highlighted, just move caret to end and exit */
  382.         e.target.selectionStart = e.target.selectionEnd = v.length;
  383.         return;
  384.     }
  385.  
  386.     var firstSpace = v.indexOf(" ");
  387.     if (firstSpace == -1)
  388.         firstSpace = v.length;
  389.  
  390.     var pfx;
  391.     var d;
  392.     
  393.     if ((v[0] == client.COMMAND_CHAR) && (selStart <= firstSpace))
  394.     {
  395.         /* complete a command */                
  396.         var partialCommand = v.substring(1, firstSpace).toLowerCase();
  397.         var cmds = client.commands.listNames(partialCommand);
  398.  
  399.         if (!cmds)
  400.         {
  401.             client.currentObject.display ("No commands matching ``" +
  402.                                           partialCommand + "''", "ERROR");
  403.         }
  404.         else if (cmds.length == 1)
  405.         {
  406.             /* partial matched exactly one command */
  407.             pfx = client.COMMAND_CHAR + cmds[0];
  408.             if (firstSpace == v.length)
  409.                 v =  pfx + " ";
  410.             else
  411.                 v = pfx + v.substr (firstSpace);
  412.             
  413.             e.target.value = v;
  414.             e.target.selectionStart = e.target.selectionEnd = 
  415.                 pfx.length + 1;
  416.         }
  417.         else if (cmds.length > 1)
  418.         {
  419.             /* partial matched more than one command */
  420.             d = new Date();
  421.             if ((d - client.lastTabUp) <= client.DOUBLETAB_TIME)
  422.                 client.currentObject.display
  423.                     ("Commands matching ``" + partialCommand + 
  424.                      "'' are [" + cmds.join(", ") + "]", "INFO");
  425.             else
  426.                 client.lastTabUp = d;
  427.             
  428.             pfx = client.COMMAND_CHAR + getCommonPfx(cmds);
  429.             if (firstSpace == v.length)
  430.                 v =  pfx;
  431.             else
  432.                 v = pfx + v.substr (firstSpace);
  433.             
  434.             e.target.value = v;
  435.             e.target.selectionStart = e.target.selectionEnd = pfx.length;
  436.             
  437.         }
  438.                 
  439.     }
  440.     else if (client.currentObject.users)
  441.     {
  442.         /* complete a nickname */
  443.         var users = client.currentObject.users;
  444.         var nicks = new Array();
  445.         
  446.         for (var n in users)
  447.             nicks.push (users[n].nick);
  448.         
  449.         var nickStart = v.lastIndexOf(" ", selStart) + 1;
  450.         var nickEnd = v.indexOf (" ", selStart);
  451.         if (nickEnd == -1)
  452.             nickEnd = v.length;
  453.         
  454.         var partialNick = v.substring(nickStart, nickEnd).toLowerCase();
  455.         
  456.         var matchingNicks = matchEntry (partialNick, nicks);
  457.         
  458.         if (matchingNicks.length > 0)
  459.         {
  460.             var subst;
  461.             
  462.             if (matchingNicks.length == 1)
  463.             {   /* partial matched exactly one nick */
  464.                 subst = 
  465.                     client.currentObject.users[matchingNicks[0]].properNick;
  466.                 if (nickStart == 0)
  467.                     subst += client.ADDRESSED_NICK_SEP;
  468.                 else
  469.                     subst += " ";
  470.             }
  471.             else
  472.             {   /* partial matched more than one command */
  473.                 d = new Date();
  474.                 if ((d - client.lastTabUp) <= client.DOUBLETAB_TIME)
  475.                     client.currentObject.display
  476.                         ("Users matching ``" + partialNick +
  477.                          "'' are [" + matchingNicks.join(", ") + "]",
  478.                          "INFO");
  479.                 else
  480.                     client.lastTabUp = d;
  481.                 
  482.                 subst = getCommonPfx(matchingNicks);
  483.             }
  484.             
  485.             v = v.substr (0, nickStart) + subst + v.substr (nickEnd);
  486.             e.target.value = v;
  487.             
  488.         }
  489.         
  490.     }
  491.  
  492. }
  493.  
  494. function onWindowKeyPress (e)
  495. {
  496.     var code = Number (e.keyCode);
  497.     var w;
  498.     var newOfs;
  499.     
  500.     switch (code)
  501.     {
  502.         case 112: /* F1 */
  503.         case 113: /* ... */
  504.         case 114:
  505.         case 115:
  506.         case 116:
  507.         case 117:
  508.         case 118:
  509.         case 119:
  510.         case 120:
  511.         case 121: /* F10 */
  512.             var idx = code - 112;
  513.             if ((client.viewsArray[idx]) && (client.viewsArray[idx].source))
  514.                 setCurrentObject(client.viewsArray[idx].source);
  515.             break;
  516.  
  517.         case 33: /* pgup */
  518.             w = window.frames[0];
  519.             newOfs = w.pageYOffset - (w.innerHeight / 2);
  520.             if (newOfs > 0)
  521.                 w.scrollTo (w.pageXOffset, newOfs);
  522.             else
  523.                 w.scrollTo (w.pageXOffset, 0);
  524.             break;
  525.             
  526.         case 34: /* pgdn */
  527.             w = window.frames[0];
  528.             newOfs = w.pageYOffset + (w.innerHeight / 2);
  529.             if (newOfs < (w.innerHeight + w.pageYOffset))
  530.                 w.scrollTo (w.pageXOffset, newOfs);
  531.             else
  532.                 w.scrollTo (w.pageXOffset, (w.innerHeight + w.pageYOffset));
  533.             break;
  534.  
  535.         case 9: /* tab */
  536.             e.preventDefault();
  537.             break;
  538.             
  539.         default:
  540.             
  541.     }
  542.  
  543. }
  544.  
  545. function onInputCompleteLine(e)
  546. {
  547.  
  548.     if (client.inputHistory[0] != e.line)
  549.         client.inputHistory.unshift (e.line);
  550.     
  551.     if (client.inputHistory.length > client.MAX_HISTORY)
  552.         client.inputHistory.pop();
  553.     
  554.     client.lastHistoryReferenced = -1;
  555.     client.incompleteLine = "";
  556.     
  557.     if (e.line[0] == client.COMMAND_CHAR)
  558.     {
  559.         var ary = e.line.substr(1, e.line.length).match (/(\S+)? ?(.*)/);
  560.         var command = ary[1];
  561.         
  562.         var ev = new CEvent ("client", "input-command", client,
  563.                              "onInputCommand");
  564.         ev.command = command;
  565.         ev.inputData =  ary[2] ? stringTrim(ary[2]) : "";
  566.         ev.line = e.line;
  567.         
  568.         ev.target = client.currentObject;
  569.         getObjectDetails (ev.target, ev);
  570.         client.eventPump.addEvent (ev);
  571.     }
  572.     else /* plain text */
  573.     {
  574.         client.sayToCurrentTarget (e.line);
  575.     }
  576. }
  577.  
  578. function onNotifyTimeout ()
  579. {
  580.     for (var n in client.networks)
  581.     {
  582.         var net = client.networks[n];
  583.         if (net.isConnected() && net.notifyList &&
  584.             net.notifyList.length > 0)
  585.             net.primServ.sendData ("ISON " +
  586.                                    client.networks[n].notifyList.join(" ")
  587.                                    + "\n");
  588.     }
  589. }
  590.     
  591. client.onInputCancel =
  592. function cli_icancel (e)
  593. {
  594.     if (client.currentObject.TYPE != "IRCNetwork")
  595.     {
  596.         client.currentObject.display ("/cancel cannot be used from this view.",
  597.                                       "ERROR");
  598.         return false;
  599.     }
  600.     
  601.     if (!client.currentObject.connecting)
  602.     {
  603.         client.currentObject.display ("No connection in progress, nothing to " +
  604.                                       "cancel.", "ERROR");
  605.         return false;
  606.     }
  607.     
  608.     client.currentObject.connectAttempt = 
  609.         client.currentObject.MAX_CONNECT_ATTEMPTS + 1;
  610.  
  611.     client.currentObject.display ("Cancelling connection to ``" + 
  612.                                   client.currentObject.name + "''...", "INFO");
  613.  
  614.     return true;
  615. }    
  616.  
  617. client.onInputCommand = 
  618. function cli_icommand (e)
  619. {
  620.     var ary = client.commands.list (e.command);
  621.     
  622.     switch (ary.length)
  623.     {        
  624.         case 0:
  625.             var o = getObjectDetails(client.currentObject);
  626.             if (o.server)
  627.             {
  628.                 client.currentObject.display ("Unknown command ``" + e.command +
  629.                                               "'', just guessing.", "WARNING");
  630.                 o.server.sendData (e.command + " " + e.inputData + "\n");
  631.             }
  632.             else
  633.                 client.currentObject.display ("Unknown command ``" + e.command +
  634.                                               "''.", "ERROR");
  635.             break;
  636.             
  637.         case 1:
  638.             if (typeof client[ary[0].func] == "undefined")        
  639.                 client.currentObject.display ("Sorry, ``" + ary[0].name +
  640.                                               "'' has not been implemented.", 
  641.                                               "ERROR");
  642.             else
  643.             {
  644.                 e.commandEntry = ary[0];
  645.                 if (!client[ary[0].func](e))
  646.                     client.currentObject.display (ary[0].name + " " +
  647.                                                   ary[0].usage, "USAGE");
  648.             }
  649.             break;
  650.             
  651.         default:
  652.             client.currentObject.display ("Ambiguous command: ``" + e.command +
  653.                                           "''", "ERROR");
  654.             var str = "";
  655.             for (var i in ary)
  656.                 str += str ? ", " + ary[i].name : ary[i].name;
  657.             client.currentObject.display (ary.length + " commands match: " +
  658.                                           str, "ERROR");
  659.     }
  660.  
  661. }
  662.  
  663. client.onInputSimpleCommand =
  664. function cli_iscommand (e)
  665. {    
  666.     var o = getObjectDetails(client.currentObject);
  667.     
  668.     if (o.server)
  669.     {
  670.         o.server.sendData (e.command + " " + e.inputData + "\n");
  671.         return true;
  672.     }
  673.     else
  674.     {
  675.         client.currentObject.display ("``" + e.command +
  676.                                       "'' cannot be used from this view.",
  677.                                       "WARNING");
  678.         return false;
  679.     }
  680. }
  681.  
  682. client.onInputStatus =
  683. function cli_istatus (e)
  684. {    
  685.     function serverStatus (s)
  686.     {
  687.         var rv;
  688.         var serverName = s.connection.host + ":" + s.connection.port;
  689.         
  690.         if (s.connection.isConnected)
  691.             rv = "User ``" + s.me.properNick + "'' Attached to ";
  692.         else
  693.             rv = "No longer attached to ";
  694.         if (s.parent.name !== s.connection.host)
  695.             rv += "``" + s.parent.name + "'' via ";
  696.         rv += serverName;
  697.         
  698.         if (s.parent.primServ == s)
  699.             rv += " (Primary Server.)\n";
  700.         else
  701.             rv += ".\n";
  702.                 
  703.         if (s.connection.isConnected)
  704.             rv += "Connected for " +
  705.                 formatDateOffset ((new Date() - s.connection.connectDate) /
  706.                                   1000);
  707.         if (s.lastPing)
  708.             rv += ", last ping was " +
  709.                 formatDateOffset ((new Date() - s.lastPing) / 1000) + " ago";
  710.         if (s.lag != -1)
  711.             rv += ", server roundtrip (lag) is " + s.lag + " seconds.";
  712.  
  713.         rv += ".";
  714.  
  715.         client.currentObject.display(rv, "STATUS");
  716.     }
  717.  
  718.     function channelStatus (c)
  719.     {
  720.         var rv = "";
  721.         var cu;
  722.         
  723.         if ((cu = c.users[c.parent.me.nick]))
  724.         {
  725.             if (cu.isOp)
  726.                 rv = "Operator";
  727.             if (cu.isVoice)
  728.                 rv = (rv) ? rv + " and voiced" : "Voiced";
  729.             if (rv)
  730.                 rv += " m";
  731.             else
  732.                 rv += "M";
  733.             rv += "ember of " + c.name + ", with " + c.getUsersLength() +
  734.                 " users total, " + c.opCount + " operators, " + c.voiceCount +
  735.                 " voiced.";
  736.             if (c.topic)
  737.                 rv += "\n" + c.name + ": ``" + c.topic + "''.";
  738.         }
  739.         else
  740.             rv = "No longer a member of " + c.name;
  741.  
  742.         client.currentObject.display(rv, "STATUS");
  743.     }
  744.         
  745.     var n, s, c;
  746.  
  747.     switch (client.currentObject.TYPE)
  748.     {
  749.         case "IRCNetwork":
  750.             for (s in client.currentObject.servers)
  751.             {
  752.                 serverStatus(client.currentObject.servers[s]);
  753.                 for (var c in client.currentObject.servers[s].channels)
  754.                     channelStatus (client.currentObject.servers[s].channels[c]);
  755.             }
  756.             break;
  757.  
  758.         case "IRCChannel":
  759.             serverStatus(client.currentObject.parent);
  760.             channelStatus(client.currentObject);
  761.             break;
  762.             
  763.         default:
  764.             for (n in client.networks)
  765.                 for (s in client.networks[n].servers)
  766.                 {
  767.                     serverStatus(client.networks[n].servers[s]);
  768.                     for (var c in client.networks[n].servers[s].channels)
  769.                         channelStatus (client.networks[n].servers[s].channels[c]);
  770.                 }
  771.             break;
  772.     }
  773.  
  774.     client.currentObject.display ("End of status.", "END_STATUS");
  775.     return true;
  776.     
  777. }            
  778.             
  779. client.onInputHelp =
  780. function cli_ihelp (e)
  781. {
  782.     var ary = client.commands.list (e.inputData);
  783.  
  784.     if (ary.length == 0)
  785.     {
  786.         client.currentObject.display ("No such command, ``" + e.inputData +
  787.                                       "''.", "ERROR");
  788.         return false;
  789.     }
  790.  
  791.     var saveDir = client.PRINT_DIRECTION;
  792.     client.PRINT_DIRECTION = 1;
  793.     
  794.     for (var i in ary)
  795.     {        
  796.         client.currentObject.display (ary[i].name + " " + ary[i].usage,
  797.                                       "USAGE");
  798.         client.currentObject.display (ary[i].help, "HELP");
  799.     }
  800.  
  801.     client.PRINT_DIRECTION = saveDir;
  802.     
  803.     return true;
  804.     
  805. }
  806.  
  807. client.onInputTestDisplay =
  808. function cli_testdisplay (e)
  809. {
  810.     var o = getObjectDetails(client.currentObject);
  811.     
  812.     client.currentObject.display ("Sample HELLO message.", "HELLO");
  813.     client.currentObject.display ("Sample INFO message.", "INFO");
  814.     client.currentObject.display ("Sample ERROR message.", "ERROR");
  815.     client.currentObject.display ("Sample HELP message.", "HELP");
  816.     client.currentObject.display ("Sample USAGE message.", "USAGE");
  817.     client.currentObject.display ("Sample STATUS message.", "STATUS");
  818.  
  819.     if (o.server && o.server.me)
  820.     {
  821.         var me = o.server.me;
  822.         var viewType = client.currentObject.TYPE;
  823.         var sampleUser = {TYPE: "IRCUser", nick: "ircmonkey",
  824.                           name: "IRCMonkey", properNick: "IRCMonkey"};
  825.         var sampleChannel = {TYPE: "IRCChannel", name: "#mojo"};
  826.  
  827.         function test (from, to, msg)
  828.         {
  829.             var fromText = (from != me) ? from.TYPE + " ``" + from.name + "''" :
  830.                 "you";
  831.             var toText   = (to != me) ? to.TYPE + " ``" + to.name + "''" :
  832.                 "you";
  833.             
  834.             client.currentObject.display ("Normal message from " + fromText +
  835.                                           " to " + toText + ((msg) ?
  836.                                                              ": " + msg : ""),
  837.                                           "PRIVMSG", from, to);
  838.             client.currentObject.display ("Action message from " + fromText +
  839.                                           " to " + toText + ((msg) ?
  840.                                                              ": " + msg : ""),
  841.                                           "ACTION", from, to);
  842.             client.currentObject.display ("Notice message from " + fromText +
  843.                                           " to " + toText + ((msg) ?
  844.                                                              ": " + msg : ""),
  845.                                           "NOTICE", from, to);
  846.         }
  847.         
  848.         test (sampleUser, me); /* from user to me */
  849.         test (me, sampleUser); /* me to user */
  850.  
  851.         client.currentObject.display ("Sample URL <http://www.mozilla.org> " +
  852.                                       "message.",
  853.                                       "PRIVMSG", sampleUser, me);
  854.         client.currentObject.display ("Sample text styles *bold*, _underline_" +
  855.                                       ", /italic/, |teletype|, #SmallCap# " +
  856.                                       "message.",
  857.                                       "PRIVMSG", sampleUser, me);
  858.         client.currentObject.display ("Sample emoticon :) :( :~( :0 :/ :P " +
  859.                                       ":| (* message.",
  860.                                       "PRIVMSG", sampleUser, me);
  861.         client.currentObject.display ("Sample Rheeeeeeeeeet! message.",
  862.                                       "PRIVMSG", sampleUser, me);
  863.         
  864.  
  865.         if (viewType == "IRCChannel")
  866.         {
  867.             test (sampleUser, sampleChannel); /* user to channel */
  868.             test (me, sampleChannel);         /* me to channel */
  869.             client.currentObject.display ("Sample Topic message", "TOPIC",
  870.                                           sampleUser, sampleChannel);
  871.             client.currentObject.display ("Sample Join message", "JOIN",
  872.                                           sampleUser, sampleChannel);
  873.             client.currentObject.display ("Sample Part message", "PART",
  874.                                           sampleUser, sampleChannel);
  875.             client.currentObject.display ("Sample Kick message", "KICK",
  876.                                           sampleUser, sampleChannel);
  877.             client.currentObject.display ("Sample Quit message", "QUIT",
  878.                                           sampleUser, sampleChannel);
  879.             client.currentObject.display (me.nick + ": Sample /stalk match.",
  880.                                           "PRIVMSG", sampleUser, sampleChannel);
  881.             client.currentObject.display ("Sample text styles *bold*, " +
  882.                                           "_underline_, /italic/, " +
  883.                                           "|teletype|, #SmallCap# message.",
  884.                                           "PRIVMSG", me, sampleChannel);
  885.         }        
  886.         
  887.     }
  888.     
  889.     return true;
  890.     
  891. }   
  892.  
  893. client.onInputNetwork =
  894. function cli_inetwork (e)
  895. {
  896.     if (!e.inputData)
  897.         return false;
  898.  
  899.     var net = client.networks[e.inputData];
  900.  
  901.     if (net)
  902.     {
  903.         client.lastNetwork = net;
  904.         setCurrentObject (net);    
  905.     }
  906.     else
  907.     {
  908.         client.currentObject.display ("Unknown network ``" + e.inputData + "''",
  909.                                       "ERROR");
  910.         return false;
  911.     }
  912.     
  913.     return true;
  914.     
  915. }
  916.  
  917. client.onInputNetworks =
  918. function clie_ilistnets (e)
  919. {
  920.     var span = document.createElementNS("http://www.w3.org/1999/xhtml",
  921.                                         "html:span");
  922.     
  923.     span.appendChild (newInlineText("Available networks are ["));
  924.  
  925.     var netnames = keys(client.networks).sort();
  926.     var lastname = netnames[netnames.length - 1];
  927.     
  928.     for (n in netnames)
  929.     {
  930.         var net = client.networks[netnames[n]];
  931.         var a = document.createElementNS("http://www.w3.org/1999/xhtml",
  932.                                          "html:a");
  933.         a.setAttribute ("class", "chatzilla-link");
  934.         a.setAttribute ("href", "irc://" + net.name);
  935.         var t = newInlineText (net.name);
  936.         a.appendChild (t);
  937.         span.appendChild (a);
  938.         if (netnames[n] != lastname)
  939.             span.appendChild (newInlineText (", "));
  940.     }
  941.  
  942.     span.appendChild (newInlineText("]."));
  943.  
  944.     client.currentObject.display (span, "INFO");
  945.     return true;
  946. }   
  947.  
  948. client.onInputServer =
  949. function cli_iserver (e)
  950. {
  951.     if (!e.inputData)
  952.         return false;
  953.  
  954.     var ary = e.inputData.match(/^([^\s\:]+)[\s\:]?(\d+)? ?(\S+)?/);
  955.     var pass = (ary[2]) ? ary[2] : "";
  956.     
  957.     if (ary == null)
  958.         return false;
  959.  
  960.     if (!ary[2])
  961.         ary[2] = 6667;
  962.  
  963.     var net = null;
  964.     
  965.     for (var n in client.networks)
  966.         if (n == ary[1])
  967.             if (client.networks[n].isConnected())
  968.             {
  969.                 client.currentObject.display ("Already connected to " + ary[1],
  970.                                               "ERROR");
  971.                 return false;
  972.             }
  973.             else
  974.             {
  975.                 net = client.networks[n];
  976.                 break;
  977.             }
  978.  
  979.     if (!net)
  980.         client.networks[ary[1]] =
  981.             new CIRCNetwork (ary[1], [{name: ary[1], port: ary[2]}],
  982.                              client.eventPump);
  983.     else
  984.         net.serverList = [{name: ary[1], port: ary[2]}];
  985.     
  986.     client.onInputAttach ({inputData: ary[1] + " " + pass});
  987.     
  988.     return true;
  989.  
  990. }
  991.  
  992. client.onInputQuit =
  993. function cli_quit (e)
  994. {
  995.     if (!e.server)
  996.     {
  997.         client.currentObject.display ("Quit can only be used in the context " +
  998.                                       "of a network, perhaps you meant /exit?",
  999.                                       "ERROR");
  1000.         return false;
  1001.     }
  1002.  
  1003.     if (!e.server.connection.isConnected)
  1004.     {
  1005.         client.currentObject.display ("Not connected", "ERROR");
  1006.         return false;
  1007.     }
  1008.  
  1009.     e.server.logout (e.inputData);
  1010.  
  1011.     return true;
  1012.     
  1013. }
  1014.  
  1015. client.onInputExit =
  1016. function cli_exit (e)
  1017. {
  1018.     
  1019.     client.quit(e.inputData);    
  1020.     window.close();
  1021.     
  1022. }
  1023.  
  1024. client.onInputDelete =
  1025. function cli_idelete (e)
  1026. {
  1027.     if (e.inputData)
  1028.         return false;
  1029.     onDeleteCurrentView();
  1030.     return true;
  1031.  
  1032. }
  1033.  
  1034. client.onInputHide=
  1035. function cli_ihide (e)
  1036. {
  1037.     
  1038.     onHideCurrentView();
  1039.     return true;
  1040.  
  1041. }
  1042.  
  1043. client.onInputClear =
  1044. function cli_iclear (e)
  1045. {
  1046.     
  1047.     onClearCurrentView();
  1048.     return true;
  1049.  
  1050. }
  1051.  
  1052. client.onInputNames =
  1053. function cli_inames (e)
  1054. {
  1055.     var chan;
  1056.     
  1057.     if (!e.network)
  1058.     {
  1059.         client.currentObject.display ("/names cannot be used from this " +
  1060.                                       "view.", "ERROR");
  1061.         return false;
  1062.     }
  1063.  
  1064.     if (e.inputData)
  1065.     {
  1066.         if (!e.network.isConnected())
  1067.         {
  1068.             client.currentObject.display ("Network ``" + e.network.name +
  1069.                                           "'' is not connected.", "ERROR");
  1070.             return false;
  1071.         }
  1072.  
  1073.         chan = e.inputData;
  1074.     }
  1075.     else
  1076.     {
  1077.         if (client.currentObject.TYPE != "IRCChannel")
  1078.         {
  1079.             client.currentObject.display ("You must supply a channel name to " +
  1080.                                           "use /names from this view.",
  1081.                                           "ERROR");
  1082.             return false;
  1083.         }
  1084.         
  1085.         chan = e.channel.name;
  1086.     }
  1087.     
  1088.     client.currentObject.pendingNamesReply = true;
  1089.     e.server.sendData ("NAMES " + chan + "\n");
  1090.     
  1091.     return true;
  1092.     
  1093. }
  1094.  
  1095. client.onInputInfobar =
  1096. function cli_tinfo ()
  1097. {
  1098.     
  1099.     onToggleVisibility ("info");
  1100.     return true;
  1101.     
  1102. }
  1103.  
  1104. client.onInputToolbar =
  1105. function cli_itbar ()
  1106. {
  1107.     
  1108.     onToggleVisibility ("toolbar");
  1109.     return true;
  1110.  
  1111. }
  1112.  
  1113. client.onInputStatusbar =
  1114. function cli_isbar ()
  1115. {
  1116.     
  1117.     onToggleVisibility ("status");
  1118.     return true;
  1119.  
  1120. }
  1121.  
  1122. client.onInputCommands =
  1123. function cli_icommands (e)
  1124. {
  1125.  
  1126.     client.currentObject.display ("Type /help <command-name> for " +
  1127.                                   "information about a specific " +
  1128.                                   "command.", "INFO");
  1129.     
  1130.     if (e && e.inputData)
  1131.         client.currentObject.display ("Currently implemented commands " +
  1132.                                       "matching the pattern ``" + e.inputData +
  1133.                                       "'' are ["  + 
  1134.                                       client.commands.listNames(e.inputData)
  1135.                                       .join(", ") + "].\n" +
  1136.                                       "Type /help <command-name> for " +
  1137.                                       "information about a specific " +
  1138.                                       "command.", "INFO");
  1139.     else
  1140.         client.currentObject.display ("Currently implemented commands are ["  + 
  1141.                                       client.commands.listNames().join(", ") +
  1142.                                       "].", "INFO");
  1143.     return true;
  1144. }
  1145.  
  1146. client.onInputAttach =
  1147. function cli_iattach (e)
  1148. {
  1149.     var net;
  1150.     var pass;
  1151.     
  1152.     if (!e.inputData)
  1153.     {
  1154.         if (client.lastNetwork)
  1155.         {        
  1156.             client.currentObject.display ("No network specified network, " +
  1157.                                           "Using ``" + client.lastNetwork.name +
  1158.                                           "''", "NOTICE");
  1159.             net = client.lastNetwork;
  1160.         }
  1161.         else
  1162.         {
  1163.             client.currentObject.display ("No network specified, and no " +
  1164.                                           "default network is in place.",
  1165.                                           "ERROR");
  1166.             return false;
  1167.         }
  1168.     }
  1169.     else
  1170.     {
  1171.         var ary = e.inputData.match (/(\S+) ?(\S+)?/);
  1172.         net = client.networks[ary[1]];
  1173.         pass = ary[2];
  1174.         
  1175.         if (!net)
  1176.         {
  1177.             client.currentObject.display ("Unknown network ``" +
  1178.                                           e.inputData + "''", "ERROR");
  1179.             return false;
  1180.         }
  1181.         client.lastNetwork = net;
  1182.     }
  1183.  
  1184.     if (!net.messages)
  1185.         net.displayHere ("Network view for ``" + net.name + "'' opened.",
  1186.                          "INFO");
  1187.     setCurrentObject(net);
  1188.  
  1189.     if (net.isConnected())
  1190.     {
  1191.         net.display ("You are already connected to ``" + net.name + "''.",
  1192.                      "ERROR");
  1193.         return true;
  1194.     }
  1195.     
  1196.     if (CIRCNetwork.prototype.INITIAL_NICK == client.defaultNick)
  1197.         CIRCNetwork.prototype.INITIAL_NICK =
  1198.             prompt ("Please select a nickname", client.defaultNick);
  1199.     
  1200.     net.connect(pass);
  1201.     net.display ("Attempting to connect to ``" + net.name + 
  1202.                  "''.  Use /cancel to abort.", "INFO");
  1203.     return true;
  1204.     
  1205. }
  1206.     
  1207. client.onInputMe =
  1208. function cli_ime (e)
  1209. {
  1210.     if (typeof client.currentObject.act != "function")
  1211.     {
  1212.         client.currentObject.display ("Me cannot be used in this view.",
  1213.                                       "ERROR");
  1214.         return false;
  1215.     }
  1216.  
  1217.     e.inputData = filterOutput (e.inputData, "ACTION", "ME!");
  1218.     client.currentObject.display (e.inputData, "ACTION", "ME!",
  1219.                                   client.currentObject);
  1220.     client.currentObject.act (e.inputData);
  1221.     
  1222.     return true;
  1223. }
  1224.  
  1225. client.onInputQuery =
  1226. function cli_imsg (e)
  1227. {
  1228.     if (!e.server.users)
  1229.     {
  1230.         client.currentObject.display ("/query cannot be used from this view.",
  1231.                                       "ERROR");
  1232.         return false;
  1233.     }
  1234.  
  1235.     var ary = e.inputData.match (/(\S+)\s*(.*)?/);
  1236.     if (ary == null)
  1237.     {
  1238.         client.currentObject.display ("Missing parameter.", "ERROR");
  1239.         return false;
  1240.     }
  1241.     
  1242.     var usr = e.network.primServ.addUser(ary[1].toLowerCase());
  1243.  
  1244.     if (!usr.messages)
  1245.         usr.displayHere ("Query view for ``" + usr.properNick + "'' opened.",
  1246.                          "INFO");
  1247.     setCurrentObject (usr);
  1248.     
  1249.     if (ary[2])
  1250.     {
  1251.         var msg = filterOutput(ary[2], "PRIVMSG", "ME!");
  1252.         usr.display (msg, "PRIVMSG", "ME!", usr);
  1253.         usr.say (ary[2]);
  1254.     }
  1255.     
  1256.     return true;
  1257. }
  1258.  
  1259. client.onInputMsg =
  1260. function cli_imsg (e)
  1261. {
  1262.  
  1263.     if (!e.network || !e.network.isConnected())
  1264.     {
  1265.         client.currentObject.display ("You must be connected to a network " +
  1266.                                       "to use msg", "ERROR");
  1267.         return false;
  1268.     }
  1269.  
  1270.     var ary = e.inputData.match (/(\S+)\s+(.*)/);
  1271.     if (ary == null)
  1272.         return false;
  1273.  
  1274.     var usr = e.network.primServ.addUser(ary[1].toLowerCase());
  1275.  
  1276.     var msg = filterOutput(ary[2], "PRIVMSG", "ME!");
  1277.     client.currentObject.display (msg, "PRIVMSG", "ME!", usr);
  1278.     usr.say (ary[2]);
  1279.  
  1280.     return true;
  1281.  
  1282. }
  1283.  
  1284. client.onInputNick =
  1285. function cli_inick (e)
  1286. {
  1287.  
  1288.     if (!e.inputData)
  1289.         return false;
  1290.     
  1291.     if (e.server) 
  1292.         e.server.sendData ("NICK " + e.inputData + "\n");
  1293.     else
  1294.         CIRCNetwork.prototype.INITIAL_NICK = e.inputData;
  1295.     
  1296.     return true;
  1297.     
  1298.     
  1299. }
  1300.  
  1301. client.onInputName =
  1302. function cli_iname (e)
  1303. {
  1304.  
  1305.     if (!e.inputData)
  1306.         return false;
  1307.     
  1308.     CIRCNetwork.prototype.INITIAL_NAME = e.inputData;
  1309.  
  1310.     return true;
  1311.     
  1312. }
  1313.  
  1314. client.onInputDesc =
  1315. function cli_idesc (e)
  1316. {
  1317.  
  1318.     if (!e.inputData)
  1319.         return false;
  1320.     
  1321.     CIRCNetwork.prototype.INITIAL_DESC = e.inputData;
  1322.     
  1323.     return true;
  1324.     
  1325. }
  1326.  
  1327. client.onInputQuote =
  1328. function cli_iquote (e)
  1329. {
  1330.     if (!e.network || !e.network.isConnected())
  1331.     {
  1332.         client.currentObject.display ("You must be connected to a network " +
  1333.                                       "to use quote.", "ERROR");
  1334.         return false;
  1335.     }
  1336.  
  1337.     e.server.sendData (e.inputData + "\n");
  1338.     
  1339.     return true;
  1340.     
  1341. }
  1342.  
  1343. client.onInputEval =
  1344. function cli_ieval (e)
  1345. {
  1346.     if (!e.inputData)
  1347.         return false;
  1348.     
  1349.     if (e.inputData.indexOf ("\n") != -1)
  1350.         e.inputData = "\n" + e.inputData + "\n";
  1351.     
  1352.     try
  1353.     {
  1354.         client.currentObject.doEval = function (__s) { return eval(__s); }
  1355.         client.currentObject.display (e.inputData, "EVAL-IN");
  1356.         
  1357.         rv = String(client.currentObject.doEval (e.inputData));
  1358.         
  1359.         client.currentObject.display (rv, "EVAL-OUT");
  1360.  
  1361.     }
  1362.     catch (ex)
  1363.     {
  1364.         client.currentObject.display (String(ex), "ERROR");
  1365.     }
  1366.     
  1367.     return true;
  1368.     
  1369. }
  1370.  
  1371. client.onInputCTCP =
  1372. function cli_ictcp (e)
  1373. {
  1374.     if (!e.inputData)
  1375.         return false;
  1376.  
  1377.     if (!e.server)
  1378.     {
  1379.         client.currentObject.display ("You must be connected to a server to " +
  1380.                                       "use CTCP.", "ERROR");
  1381.         return false;
  1382.     }
  1383.  
  1384.     var ary = e.inputData.match(/^(\S+) (\S+)$/);
  1385.     if (ary == null)
  1386.         return false;
  1387.     
  1388.     e.server.ctcpTo (ary[1], ary[2]);
  1389.     
  1390.     return true;
  1391.     
  1392. }
  1393.  
  1394.  
  1395. client.onInputJoin =
  1396. function cli_ijoin (e)
  1397. {
  1398.     if (!e.network || !e.network.isConnected())
  1399.     {
  1400.         if (!e.network)
  1401.             client.currentObject.display ("No network selected.", "ERROR");
  1402.         else
  1403.             client.currentObject.display ("Network ``" + e.network.name +
  1404.                                           "'' is not connected.", "ERROR");
  1405.         return false;
  1406.     }
  1407.     
  1408.     var ary = e.inputData.match(/(\S+) ?(\S+)?/);
  1409.     if (!ary)
  1410.         return false;
  1411.     
  1412.     var name = ary[1];
  1413.     var key = (ary[2]) ? ary[2] : "";
  1414.  
  1415.     if ((name[0] != "#") && (name[0] != "&") && (name[0] != "+"))
  1416.         name = "#" + name;
  1417.  
  1418.     e.channel = e.server.addChannel (name);
  1419.     e.channel.join(key);
  1420.     if (!e.channel.messages)
  1421.         e.channel.display ("Channel view for ``" + e.channel.name +
  1422.                            "'' opened.", "INFO");
  1423.     setCurrentObject(e.channel);
  1424.     
  1425.     return true;
  1426.     
  1427. }
  1428.  
  1429. client.onInputLeave =
  1430. function cli_ipart (e)
  1431. {
  1432.     if (!e.channel)
  1433.     {            
  1434.         client.currentObject.display ("Leave can only be used from channels.",
  1435.                                       "ERROR");
  1436.         return false;
  1437.     }
  1438.  
  1439.     e.channel.part();
  1440.  
  1441.     return true;
  1442.     
  1443. }
  1444.  
  1445. client.onInputZoom =
  1446. function cli_izoom (e)
  1447. {
  1448.     client.currentObject.display ("**WARNING** Zoom is busted at this time :(",
  1449.                                   "WARNING");
  1450.  
  1451.     if (!e.inputData)
  1452.         return false;
  1453.     
  1454.     if (!e.channel)
  1455.     {
  1456.         client.currentObject.display ("Zoom can only be used from channels.",
  1457.                                      "ERROR");
  1458.         return false;
  1459.     }
  1460.     
  1461.     var cuser = e.channel.getUser(e.inputData);
  1462.     
  1463.     if (!cuser)
  1464.     {
  1465.         client.currentObject.display ("User ``" + e.inputData + "'' not found.",
  1466.                                       "ERROR");
  1467.         return false;
  1468.     }
  1469.     
  1470.     setCurrentObject(cuser);
  1471.  
  1472.     return true;
  1473.     
  1474. }    
  1475.  
  1476. /**
  1477.  * Performs a whois on a user.
  1478.  */
  1479. client.onInputWhoIs = 
  1480. function cli_whois (e) 
  1481. {
  1482.     if (!e.network || !e.network.isConnected())
  1483.     {
  1484.         client.currentObject.display ("You must be connected to a network " +
  1485.                                       "to use whois", "ERROR");
  1486.         return false;
  1487.     }
  1488.  
  1489.     if (!e.inputData)
  1490.     {
  1491.         var nicksAry = e.channel.getSelectedUsers();
  1492.  
  1493.         if (nicksAry)
  1494.         {
  1495.             mapObjFunc(nicksAry, "whois", null);
  1496.             return true;
  1497.         }
  1498.         else
  1499.         {
  1500.             return false;
  1501.         }
  1502.     }
  1503.     // Otherwise, there is no guarantee that the username
  1504.     // is currently a user
  1505.     var nick = e.inputData.match( /\S+/ );
  1506.  
  1507.     e.server.whois (nick);
  1508.     
  1509.     return true;
  1510. }
  1511.  
  1512. client.onInputTopic =
  1513. function cli_itopic (e)
  1514. {
  1515.     if (!e.channel)
  1516.     {
  1517.         client.currentObject.display ("Topic can only be used from channels.",
  1518.                                       "ERROR");
  1519.         return false;
  1520.     }
  1521.     
  1522.     if (!e.inputData)
  1523.     {
  1524.         e.server.sendData ("TOPIC " + e.channel.name + "\n");
  1525.     }
  1526.     else
  1527.     {
  1528.         if (!e.channel.setTopic(e.inputData))
  1529.             client.currentObject.display ("Could not set topic.", "ERROR");
  1530.     }
  1531.  
  1532.     return true;
  1533.     
  1534. }
  1535.  
  1536. client.onInputAway =
  1537. function cli_iaway (e)
  1538.     if (!e.network || !e.network.isConnected())
  1539.     {
  1540.         client.currentObject.display ("You must be connected to a network " +
  1541.                                       "to use away.", "ERROR");
  1542.         return false;
  1543.     }
  1544.     else if (!e.inputData) 
  1545.     {
  1546.         e.server.sendData ("AWAY\n");
  1547.     }
  1548.     else
  1549.     {
  1550.         e.server.sendData ("AWAY " + e.inputData + "\n");
  1551.     }
  1552.  
  1553.     return true;
  1554. }    
  1555.  
  1556. /**
  1557.  * Removes operator status from a user.
  1558.  */
  1559. client.onInputDeop = 
  1560. function cli_ideop (e) 
  1561. {
  1562.     /* NOTE: See the next function for a well commented explanation
  1563.        of the general form of these Multiple-Target type functions */
  1564.  
  1565.     if (!e.channel)
  1566.     {
  1567.         client.currentObject.display ("You must be on a channel to use " +
  1568.                                       "to use deop.", "ERROR");
  1569.         return false;
  1570.     }    
  1571.     
  1572.     if (!e.inputData)
  1573.     {
  1574.         var nicksAry = e.channel.getSelectedUsers();
  1575.  
  1576.  
  1577.         if (nicksAry)
  1578.         {
  1579.             mapObjFunc(nicksAry, "setOp", false);
  1580.             return true;
  1581.         }
  1582.         else
  1583.         {
  1584.             return false;
  1585.         }
  1586.     }
  1587.  
  1588.     var cuser = e.channel.getUser(e.inputData);
  1589.     
  1590.     if (!cuser)
  1591.     {
  1592.         /* use e.inputData so the case is retained */
  1593.         client.currentObject.display ("User ``" + e.inputData + "'' not found.",
  1594.                                       "ERROR");
  1595.         return false;
  1596.     }
  1597.     
  1598.     cuser.setOp(false);
  1599.  
  1600.     return true;
  1601. }
  1602.  
  1603.  
  1604. /**
  1605.  * Gives operator status to a channel user.
  1606.  */
  1607. client.onInputOp = 
  1608. function cli_iop (e) 
  1609. {
  1610.     if (!e.channel)
  1611.     {
  1612.         client.currentObject.display ("You must be connected to a network " +
  1613.                                       "to use op.", "ERROR");
  1614.         return false;
  1615.     }
  1616.     
  1617.     
  1618.     if (!e.inputData)
  1619.     {
  1620.         /* Since no param is passed, check for selection */
  1621.         var nicksAry = e.channel.getSelectedUsers();
  1622.  
  1623.         /* If a valid array of user objects, then call the mapObjFunc */
  1624.         if (nicksAry)
  1625.         {
  1626.             /* See test3-utils.js: this simply
  1627.                applies the setOp function to every item
  1628.                in nicksAry with the parameter of "true" 
  1629.                each time 
  1630.             */
  1631.             mapObjFunc(nicksAry, "setOp", true);
  1632.             return true;
  1633.         }
  1634.         else
  1635.         {
  1636.             /* If no input and no selection, return false
  1637.                to display the usage */
  1638.             return false;
  1639.         }
  1640.     }
  1641.  
  1642.     /* We do have inputData, so use that, rather than any
  1643.        other option */
  1644.  
  1645.     var cuser = e.channel.getUser(e.inputData);
  1646.     
  1647.     if (!cuser)
  1648.     {
  1649.         client.currentObject.display ("User ``" + e.inputData + "'' not found.",
  1650.                                       "ERROR");
  1651.         return false;
  1652.     }
  1653.     
  1654.     cuser.setOp(true);
  1655.  
  1656.     return true;   
  1657.     
  1658. }
  1659.  
  1660. /**
  1661.  * Gives voice status to a user.
  1662.  */
  1663. client.onInputVoice = 
  1664. function cli_ivoice (e) 
  1665. {
  1666.     if (!e.channel)
  1667.     {
  1668.         client.currentObject.display ("You must be on a channel " +
  1669.                                       "to use voice.", "ERROR");
  1670.         return false;
  1671.     }    
  1672.     
  1673.     if (!e.inputData)
  1674.     {
  1675.         var nicksAry = e.channel.getSelectedUsers();
  1676.  
  1677.         if (nicksAry)
  1678.         {
  1679.             mapObjFunc(nicksAry, "setVoice", true);
  1680.             return true;
  1681.         }
  1682.         else
  1683.         {
  1684.             return false;
  1685.         }
  1686.     }
  1687.  
  1688.     var cuser = e.channel.getUser(e.inputData);
  1689.     
  1690.     if (!cuser)
  1691.     {
  1692.         client.currentObject.display ("User ``" + e.inputData + "'' not found.",
  1693.                                       "ERROR");
  1694.         return false;
  1695.     }
  1696.     
  1697.     cuser.setVoice(true);
  1698.  
  1699.     return true;
  1700. }
  1701.  
  1702. /**
  1703.  * Removes voice status from a user.
  1704.  */
  1705. client.onInputDevoice = 
  1706. function cli_devoice (e) 
  1707. {
  1708.     if (!e.channel)
  1709.     {
  1710.         client.currentObject.display ("You must be on a channel " +
  1711.                                       "to use devoice.", "ERROR");
  1712.         return false;
  1713.     }    
  1714.     
  1715.     if (!e.inputData)
  1716.     {
  1717.         var nicksAry = e.channel.getSelectedUsers();
  1718.  
  1719.         if (nicksAry)
  1720.         {
  1721.             mapObjFunc(nicksAry, "setVoice", false);
  1722.             return true;
  1723.         }
  1724.         else
  1725.         {
  1726.             return false;
  1727.         }
  1728.     }
  1729.     
  1730.     var cuser = e.channel.getUser(e.inputData);
  1731.     
  1732.     if (!cuser)
  1733.     {
  1734.         client.currentObject.display ("User ``" + e.inputData + "'' not found.",
  1735.                                       "ERROR");
  1736.         return false;
  1737.     }
  1738.     
  1739.     cuser.setVoice(false);
  1740.  
  1741.     return true;
  1742. }
  1743.  
  1744. /**
  1745.  * Displays input to the current view, but doesn't send it to the server.
  1746.  */
  1747. client.onInputEcho =
  1748. function cli_iecho (e)
  1749. {
  1750.     if (!e.inputData)
  1751.     {
  1752.         return false;
  1753.     }
  1754.     else 
  1755.     {
  1756.         client.currentObject.display (e.inputData, "ECHO");
  1757.         
  1758.         return true;
  1759.     }
  1760. }
  1761.  
  1762. client.onInputInvite =
  1763. function cli_iinvite (e) 
  1764. {
  1765.  
  1766.     if (!e.network || !e.network.isConnected())
  1767.     {
  1768.         client.currentObject.display ("You must be connected to a network " +
  1769.                                       "to use invite.", "ERROR");
  1770.         return false;
  1771.     }     
  1772.     else if (!e.channel)
  1773.     {
  1774.         client.currentObject.display 
  1775.         ("You must be in a channel to use invite", "ERROR");
  1776.         return false;
  1777.     }    
  1778.     
  1779.     if (!e.inputData) {
  1780.         return false;
  1781.     }
  1782.     else 
  1783.     {
  1784.         var ary = e.inputData.split( /\s+/ );
  1785.         
  1786.         if (ary.length == 1)
  1787.         {
  1788.             e.channel.invite (ary[0]);
  1789.         }
  1790.         else
  1791.         {
  1792.             var chan = e.server.channels[ary[1].toLowerCase()];
  1793.  
  1794.             if (chan == undefined) 
  1795.             {
  1796.                 client.currentObject.display ("You must be on " + ary[1] + 
  1797.                                               " to use invite.", "ERROR");
  1798.                 return false;
  1799.             }            
  1800.  
  1801.             chan.invite (ary[0]);
  1802.         }   
  1803.         
  1804.         return true;
  1805.     }
  1806. }
  1807.  
  1808.  
  1809. client.onInputKick =
  1810. function cli_ikick (e) 
  1811. {
  1812.     if (!e.channel)
  1813.     {
  1814.         client.currentObject.display ("You must be on a channel to use " +
  1815.                                       "kick.", "ERROR");
  1816.         return false;
  1817.     }    
  1818.     
  1819.     if (!e.inputData)
  1820.     {
  1821.         var nicksAry = e.channel.getSelectedUsers();
  1822.  
  1823.         if (nicksAry)
  1824.         {
  1825.             mapObjFunc(nicksAry, "kick", "");
  1826.             return true;
  1827.         }
  1828.         else
  1829.         {
  1830.             return false;
  1831.         }
  1832.     }
  1833.  
  1834.     var ary = e.inputData.match ( /(\S+)? ?(.*)/ );
  1835.  
  1836.     var cuser = e.channel.getUser(ary[1]);
  1837.     
  1838.     if (!cuser)
  1839.     {    
  1840.         client.currentObject.display ("User ``" + e.inputData + "'' not found.",
  1841.                                       "ERROR");
  1842.         return false;
  1843.     }
  1844.  
  1845.     if (ary.length > 2)
  1846.     {               
  1847.         cuser.kick(ary[2]);
  1848.     }
  1849.     else     
  1850.  
  1851.     cuser.kick();    
  1852.             
  1853.     return true;
  1854. }
  1855.  
  1856. client.onInputClient =
  1857. function cli_iclient (e)
  1858. {
  1859.     if (!client.messages)
  1860.         client.display ("JavaScript console for ``*client*'' opened.", "INFO");
  1861.  
  1862.     setCurrentObject (client);
  1863.     return true;
  1864. }
  1865.  
  1866. client.onInputNotify =
  1867. function cli_inotify (e)
  1868. {
  1869.     if (!e.network)
  1870.     {
  1871.         client.currentObject.display ("/notify cannot be used from this view.",
  1872.                                       "ERROR");
  1873.         return false;
  1874.     }
  1875.  
  1876.     var net = e.network;
  1877.     
  1878.     if (!e.inputData)
  1879.     {
  1880.         if (net.notifyList && net.notifyList.length > 0)
  1881.         {
  1882.             /* delete the lists and force a ISON check, this will
  1883.              * print the current online/offline status when the server
  1884.              * responds */
  1885.             delete net.onList;
  1886.             delete net.offList;
  1887.             onNotifyTimeout();
  1888.         }
  1889.         else
  1890.             client.currentObject.display ("Your notify list is empty", "INFO");
  1891.     }
  1892.     else
  1893.     {
  1894.         var adds = new Array();
  1895.         var subs = new Array();
  1896.         
  1897.         if (!net.notifyList)
  1898.             net.notifyList = new Array();
  1899.         var ary = e.inputData.toLowerCase().split(/\s+/);
  1900.  
  1901.         for (var i in ary)
  1902.         {
  1903.             var idx = arrayIndexOf (net.notifyList, ary[i]);
  1904.             if (idx == -1)
  1905.             {
  1906.                 net.notifyList.push (ary[i]);
  1907.                 adds.push(ary[i]);
  1908.             }
  1909.             else
  1910.             {
  1911.                 arrayRemoveAt (net.notifyList, idx);
  1912.                 subs.push(ary[i]);
  1913.             }
  1914.         }
  1915.  
  1916.         if (adds.length > 0)
  1917.             client.currentObject.display (arraySpeak(adds, "has", "have") +
  1918.                                           " been added to your notify list.");
  1919.         if (subs.length > 0)
  1920.             client.currentObject.display (arraySpeak(subs, "has", "have") +
  1921.                                           " been removed from your notify list.");
  1922.         delete net.onList;
  1923.         delete net.offList;
  1924.         onNotifyTimeout();
  1925.     }
  1926.  
  1927.     return true;
  1928.     
  1929. }
  1930.  
  1931.                 
  1932. client.onInputStalk =
  1933. function cli_istalk (e)
  1934. {
  1935.     if (!e.inputData)
  1936.     {
  1937.         if ( client.stalkingVictims.length == 0 ) {
  1938.             client.currentObject.display( "No stalking victims.", "STALK" );
  1939.         } else {
  1940.             client.currentObject.display( "Currently stalking [" +
  1941.                                       client.stalkingVictims.join(", ") + "]",
  1942.                                       "STALK");
  1943.         }
  1944.         return true;
  1945.     }
  1946.     client.stalkingVictims[client.stalkingVictims.length] = e.inputData;
  1947.     client.currentObject.display( "Now stalking " + e.inputData, "STALK"
  1948. );
  1949.     return true;
  1950. }
  1951.  
  1952. client.onInputUnstalk =
  1953. function cli_iunstalk ( e )
  1954. {
  1955.     if ( !e.inputData )
  1956.         return false;
  1957.  
  1958.     for ( i in client.stalkingVictims ) {
  1959.         if ( client.stalkingVictims[i].match( "^" + e.inputData +"$", "i" ) ) {
  1960.             client.stalkingVictims.splice(i,1);
  1961.             client.currentObject.display( "No longer stalking " +
  1962.                 e.inputData, "UNSTALK" );
  1963.             return true;
  1964.         }
  1965.     }
  1966.  
  1967.     client.currentObject.display( "Not stalking " + e.inputData,
  1968.         "UNSTALK" );
  1969.     return true;
  1970. }
  1971.  
  1972. /* 'private' function, should only be used from inside */
  1973. CIRCChannel.prototype._addUserToGraph =
  1974. function my_addtograph (user)
  1975. {
  1976.     if (!user.TYPE)
  1977.         dd (getStackTrace());
  1978.     
  1979.     client.rdf.Assert (this.getGraphResource(), client.rdf.resChanUser,
  1980.                        user.getGraphResource(), true);
  1981.     
  1982. }
  1983.  
  1984. /* 'private' function, should only be used from inside */
  1985. CIRCChannel.prototype._removeUserFromGraph =
  1986. function my_remfgraph (user)
  1987. {
  1988.  
  1989.     client.rdf.Unassert (this.getGraphResource(), client.rdf.resChanUser,
  1990.                          user.getGraphResource());
  1991.     
  1992. }
  1993.  
  1994. CIRCNetwork.prototype.onInfo =
  1995. function my_netinfo (e)
  1996. {
  1997.     this.display (e.msg, "INFO");
  1998. }
  1999.  
  2000. CIRCNetwork.prototype.onUnknown =
  2001. function my_unknown (e)
  2002. {
  2003.     e.params.shift(); /* remove the code */
  2004.     e.params.shift(); /* and the dest. nick (always me) */
  2005.         /* if it looks like some kind of "end of foo" code, and we don't
  2006.          * already have a mapping for it, make one up */
  2007.     if (!client.responseCodeMap[e.code] && e.meat.search (/^end of/i) != -1)
  2008.         client.responseCodeMap[e.code] = "---";
  2009.     
  2010.     this.display (e.params.join(" ") + ": " + e.meat,
  2011.                   e.code.toUpperCase());
  2012. }
  2013.  
  2014. CIRCNetwork.prototype.on001 = /* Welcome! */
  2015. CIRCNetwork.prototype.on002 = /* your host is */
  2016. CIRCNetwork.prototype.on003 = /* server born-on date */
  2017. CIRCNetwork.prototype.on004 = /* server id */
  2018. CIRCNetwork.prototype.on005 = /* server features */
  2019. CIRCNetwork.prototype.on251 = /* users */
  2020. CIRCNetwork.prototype.on252 = /* opers online (in params[2]) */
  2021. CIRCNetwork.prototype.on254 = /* channels found (in params[2]) */
  2022. CIRCNetwork.prototype.on255 = /* link info */
  2023. CIRCNetwork.prototype.on265 = /* local user details */
  2024. CIRCNetwork.prototype.on266 = /* global user details */
  2025. CIRCNetwork.prototype.on375 = /* start of MOTD */
  2026. CIRCNetwork.prototype.on372 = /* MOTD line */
  2027. CIRCNetwork.prototype.on376 = /* end of MOTD */
  2028. function my_showtonet (e)
  2029. {
  2030.     var p = (e.params[2]) ? e.params[2] + " " : "";
  2031.     var str = "";
  2032.  
  2033.     switch (e.code)
  2034.     {
  2035.         case "004":
  2036.             str = e.params.slice(1).join (" ");
  2037.             break;
  2038.  
  2039.         case "001":
  2040.             updateTitle(this);
  2041.             updateNetwork (this);
  2042.             if (this.pendingURLs)
  2043.             {
  2044.                 var url = this.pendingURLs.pop();
  2045.                 while (url)
  2046.                 {
  2047.                     gotoIRCURL(url);
  2048.                     url = this.pendingURLs.pop();
  2049.                 }
  2050.                 delete this.pendingURLs;
  2051.             }
  2052.             str = e.meat;
  2053.             break;
  2054.             
  2055.         case "372":
  2056.         case "375":
  2057.         case "376":
  2058.             if (this.IGNORE_MOTD)
  2059.                 return;
  2060.             /* no break */
  2061.  
  2062.         default:
  2063.             str = e.meat;
  2064.             break;
  2065.     }
  2066.  
  2067.     this.displayHere (p + str, e.code.toUpperCase());
  2068.     
  2069. }
  2070.  
  2071. CIRCNetwork.prototype.onNotice = 
  2072. function my_notice (e)
  2073. {
  2074.     this.display (e.meat, "NOTICE", this, e.server.me);
  2075. }
  2076.  
  2077. CIRCNetwork.prototype.on303 = /* ISON (aka notify) reply */
  2078. function my_303 (e)
  2079. {
  2080.     var onList = stringTrim(e.meat.toLowerCase()).split(/\s+/);
  2081.     var offList = new Array();
  2082.     var newArrivals = new Array();
  2083.     var newDepartures = new Array();
  2084.     var i;
  2085.  
  2086.     for (i in this.notifyList)
  2087.         if (!arrayContains(onList, this.notifyList[i]))
  2088.             /* user is not on */
  2089.             offList.push (this.notifyList[i]);
  2090.         
  2091.     if (this.onList)
  2092.     {
  2093.         for (i in onList)
  2094.             if (!arrayContains(this.onList, onList[i]))
  2095.                 /* we didn't know this person was on */
  2096.                 newArrivals.push(onList[i]);
  2097.     }
  2098.     else
  2099.         this.onList = newArrivals = onList;
  2100.  
  2101.     if (this.offList)
  2102.     {
  2103.         for (i in offList)
  2104.             if (!arrayContains(this.offList, offList[i]))
  2105.                 /* we didn't know this person was off */
  2106.                 newDepartures.push(offList[i]);
  2107.     }
  2108.     else
  2109.         this.offList = newDepartures = offList;
  2110.     
  2111.     if (newArrivals.length > 0)
  2112.         this.display (arraySpeak (newArrivals, "is", "are") +
  2113.                       " online.", "NOTIFY-ON");
  2114.     
  2115.     if (newDepartures.length > 0)
  2116.         this.display (arraySpeak (newDepartures, "is", "are") +
  2117.                       " offline.", "NOTIFY-OFF");
  2118.  
  2119.     this.onList = onList;
  2120.     this.offList = offList;
  2121.     
  2122. }
  2123.  
  2124. CIRCNetwork.prototype.on322 = /* LIST reply */
  2125. function my_listrply (e)
  2126. {
  2127.     var span = document.createElementNS("http://www.w3.org/1999/xhtml",
  2128.                                         "html:span");
  2129.     var a = document.createElementNS ("http://www.w3.org/1999/xhtml",
  2130.                                       "html:a");
  2131.     a.setAttribute ("href", "irc://" + this.name + "/" + e.params[2]);
  2132.     a.setAttribute ("class", "chatzilla-link");
  2133.     var t = newInlineText (e.params[2]);
  2134.     a.appendChild (t);
  2135.  
  2136.     span.appendChild (a);
  2137.  
  2138.     t = client.munger.munge (" " + e.params[3] + " " + e.meat);
  2139.     
  2140.     span.appendChild (t);
  2141.     
  2142.     this.displayHere (span, "LIST");
  2143. }
  2144.     
  2145. CIRCNetwork.prototype.on311 = /* whois name */
  2146. CIRCNetwork.prototype.on319 = /* whois channels */
  2147. CIRCNetwork.prototype.on312 = /* whois server */
  2148. CIRCNetwork.prototype.on317 = /* whois idle time */
  2149. CIRCNetwork.prototype.on318 = /* whois end of whois*/
  2150. function my_whoisreply (e)
  2151. {
  2152.     var text = "egads!";
  2153.     
  2154.     switch (Number(e.code))
  2155.     {
  2156.         case 311:
  2157.             text = e.params[2] + " (" + e.params[3] + "@" + e.params[4] +
  2158.                 ") is " + e.meat;
  2159.             break;
  2160.             
  2161.         case 319:
  2162.             var ary = stringTrim(e.meat).split(" ");
  2163.             text = e.params[2] + " is a member of " + arraySpeak(ary);
  2164.             break;
  2165.             
  2166.         case 312:
  2167.             text = e.params[2] + " is attached to " + e.params[3] + " ``" +
  2168.                 e.meat + "''";
  2169.             break;
  2170.             
  2171.         case 317:
  2172.             text = e.params[2] + " has been idle for " +
  2173.                 formatDateOffset(Number(e.params[3])) + " (on since " +
  2174.                 new Date(Number(e.params[4]) * 1000) + ")";
  2175.             break;
  2176.             
  2177.         case 318:
  2178.             text = "End of WHOIS information for " + e.params[2];
  2179.             break;
  2180.             
  2181.     }
  2182.  
  2183.     e.server.parent.display(text, e.code);
  2184.     
  2185. }
  2186.  
  2187. CIRCNetwork.prototype.on433 = /* nickname in use */
  2188. function my_433 (e)
  2189. {
  2190.  
  2191.     e.server.parent.display ("The nickname ``" + e.params[2] +
  2192.                              "'' is already in use.", e.code);
  2193.     
  2194. }
  2195.  
  2196. CIRCNetwork.prototype.onError =
  2197. function my_neterror (e)
  2198. {
  2199.  
  2200.     e.server.parent.display (e.meat, "ERROR");
  2201.     
  2202. }
  2203.  
  2204. CIRCNetwork.prototype.onDisconnect =
  2205. function my_neterror (e)
  2206. {
  2207.     var msg = (this.connecting) ? "Could not connect to " :
  2208.         "You are no longer connected to ";
  2209.  
  2210.     this.display (msg + this.name + " (" +
  2211.                   e.server.connection.host + ").", "ERROR");
  2212.     this.connecting = false;
  2213.     updateTitle();
  2214. }
  2215.  
  2216. CIRCNetwork.prototype.onNick =
  2217. function my_cnick (e)
  2218. {
  2219.  
  2220.     if (userIsMe (e.user))
  2221.     {
  2222.         if (client.currentObject == this)
  2223.             this.displayHere ("YOU are now known as " + e.user.properNick, 
  2224.                               "NICK", "ME!", e.user, this);
  2225.         updateNetwork();
  2226.     }
  2227.     else
  2228.         this.display (e.oldNick + " is now known as " + e.user.properNick,
  2229.                       "NICK", e.user, this);
  2230.  
  2231. }
  2232.  
  2233. CIRCNetwork.prototype.onPing =
  2234. function my_netping (e)
  2235. {
  2236.  
  2237.     updateNetwork (e.network);
  2238.     
  2239. }
  2240.  
  2241. CIRCNetwork.prototype.onPong =
  2242. function my_netpong (e)
  2243. {
  2244.  
  2245.     updateNetwork (e.network);
  2246.     
  2247. }
  2248.  
  2249. CIRCChannel.prototype.onPrivmsg =
  2250. function my_cprivmsg (e)
  2251. {
  2252.     
  2253.     this.display (e.meat, "PRIVMSG", e.user, this);
  2254.     
  2255.     if ((typeof client.prefix == "string") &&
  2256.         e.meat.indexOf (client.prefix) == 0)
  2257.     {
  2258.         try
  2259.         {
  2260.             var v = eval(e.meat.substring (client.prefix.length,
  2261.                                            e.meat.length));
  2262.         }
  2263.         catch (ex)
  2264.         {
  2265.             this.say (e.user.nick + ": " + String(ex));
  2266.             return false;
  2267.         }
  2268.         
  2269.         if (typeof (v) != "undefined")
  2270.         {                        
  2271.             if (v != null)                
  2272.                 v = String(v);
  2273.             else
  2274.                 v = "null";
  2275.             
  2276.             var rsp = e.user.nick + ", your result is,";
  2277.             
  2278.             if (v.indexOf ("\n") != -1)
  2279.                 rsp += "\n";
  2280.             else
  2281.                 rsp += " ";
  2282.             
  2283.             this.display (rsp + v, "PRIVMSG", e.server.me, this);
  2284.             this.say (rsp + v);
  2285.         }
  2286.     }
  2287.  
  2288.     return true;
  2289.     
  2290. }
  2291.  
  2292. /* end of names */
  2293. CIRCChannel.prototype.on366 =
  2294. function my_366 (e)
  2295. {
  2296.     if (client.currentObject == this)    
  2297.         /* hide the tree while we add (possibly tons) of nodes */
  2298.         client.rdf.setTreeRoot("user-list", client.rdf.resNullChan);
  2299.     
  2300.     client.rdf.clearTargets(this.getGraphResource(), client.rdf.resChanUser);
  2301.  
  2302.     for (var u in this.users)
  2303.     {
  2304.         this.users[u].updateGraphResource();
  2305.         this._addUserToGraph (this.users[u]);
  2306.     }
  2307.  
  2308.     
  2309.     if (client.currentObject == this)
  2310.         /* redisplay the tree */
  2311.         client.rdf.setTreeRoot("user-list", this.getGraphResource());
  2312.     
  2313.     if (e.channel.pendingNamesReply)
  2314.     {       
  2315.         e.channel.display (e.meat, "366");
  2316.         e.channel.pendingNamesReply = false;
  2317.     }
  2318.     
  2319. }    
  2320.  
  2321. CIRCChannel.prototype.onTopic = /* user changed topic */
  2322. CIRCChannel.prototype.on332 = /* TOPIC reply */
  2323. function my_topic (e)
  2324. {
  2325.  
  2326.     if (e.code == "TOPIC")
  2327.         this.display (this.topicBy + " has changed the topic to ``" +
  2328.                       this.topic + "''", "TOPIC");
  2329.     
  2330.     if (e.code == "332")
  2331.     {
  2332.         if (this.topic)
  2333.             this.display ("Topic for " + this.name + " is ``" +
  2334.                           this.topic + "''", "TOPIC");
  2335.         else
  2336.             this.display ("No topic for channel " + this.name,
  2337.                           "TOPIC");
  2338.     }
  2339.     
  2340.     updateChannel (this);
  2341.     updateTitle (this);
  2342.     
  2343. }
  2344.  
  2345. CIRCChannel.prototype.on333 = /* Topic setter information */
  2346. function my_topicinfo (e)
  2347. {
  2348.     
  2349.     this.display ("Topic for " + this.name + " was set by " +
  2350.                   this.topicBy + " on " +
  2351.                   this.topicDate, "TOPIC");
  2352.     
  2353. }
  2354.  
  2355. CIRCChannel.prototype.on353 = /* names reply */
  2356. function my_topic (e)
  2357. {
  2358.     if (e.channel.pendingNamesReply)
  2359.         e.channel.display (e.meat, "NAMES");
  2360. }
  2361.  
  2362.  
  2363. CIRCChannel.prototype.onNotice =
  2364. function my_notice (e)
  2365. {
  2366.     this.display (e.meat, "NOTICE", e.user, this);   
  2367. }
  2368.  
  2369. CIRCChannel.prototype.onCTCPAction =
  2370. function my_caction (e)
  2371. {
  2372.  
  2373.     this.display (e.CTCPData, "ACTION", e.user, this);
  2374.  
  2375. }
  2376.  
  2377. CIRCChannel.prototype.onUnknownCTCP =
  2378. function my_unkctcp (e)
  2379. {
  2380.  
  2381.     this.display ("Unknown CTCP " + e.CTCPCode + "(" + e.CTCPData +
  2382.                   ") from " + e.user.properNick, "BAD-CTCP", e.user, this);
  2383.     
  2384. }   
  2385.  
  2386. CIRCChannel.prototype.onJoin =
  2387. function my_cjoin (e)
  2388. {
  2389.  
  2390.     if (userIsMe (e.user))
  2391.     {
  2392.         this.display ("YOU have joined " + e.channel.name, "JOIN", e.server.me,
  2393.                       this);
  2394.         setCurrentObject(this);
  2395.     }
  2396.     else
  2397.         this.display(e.user.properNick + " (" + e.user.name + "@" +
  2398.                      e.user.host + ") has joined " + e.channel.name, "JOIN",
  2399.                      e.user, this);
  2400.  
  2401.     this._addUserToGraph (e.user);
  2402.     
  2403.     updateChannel (e.channel);
  2404.     
  2405. }
  2406.  
  2407. CIRCChannel.prototype.onPart =
  2408. function my_cpart (e)
  2409. {
  2410.  
  2411.     this._removeUserFromGraph(e.user);
  2412.  
  2413.     if (userIsMe (e.user))
  2414.     {
  2415.         this.display ("YOU have left " + e.channel.name, "PART", e.user, this);
  2416.         if (client.currentObject == this)    
  2417.             /* hide the tree while we remove (possibly tons) of nodes */
  2418.             client.rdf.setTreeRoot("user-list", client.rdf.resNullChan);
  2419.         
  2420.         client.rdf.clearTargets(this.getGraphResource(),
  2421.                                 client.rdf.resChanUser, true);
  2422.  
  2423.         if (client.currentObject == this)
  2424.             /* redisplay the tree */
  2425.             client.rdf.setTreeRoot("user-list", this.getGraphResource());
  2426.  
  2427.         if (client.DELETE_ON_PART)
  2428.             client.onInputDelete(e);
  2429.     }
  2430.     else
  2431.         this.display (e.user.properNick + " has left " + e.channel.name,
  2432.                       "PART", e.user, this);
  2433.  
  2434.  
  2435.     updateChannel (e.channel);
  2436.     
  2437. }
  2438.  
  2439. CIRCChannel.prototype.onKick =
  2440. function my_ckick (e)
  2441. {
  2442.  
  2443.     if (userIsMe (e.lamer))
  2444.         this.display ("YOU have been booted from " + e.channel.name +
  2445.                       " by " + e.user.properNick + " (" + e.reason + ")",
  2446.                       "KICK", e.user, this);
  2447.     else
  2448.     {
  2449.         var enforcerProper, enforcerNick;
  2450.         if (userIsMe (e.user))
  2451.         {
  2452.             enforcerProper = "YOU";
  2453.             enforcerNick = "ME!";
  2454.         }
  2455.         else
  2456.         {
  2457.             enforcerProper = e.user.properNick;
  2458.             enforcerNick = e.user.nick;
  2459.         }
  2460.         
  2461.         this.display (e.lamer.properNick + " was booted from " +
  2462.                       e.channel.name + " by " + enforcerProper + " (" +
  2463.                       e.reason + ")", "KICK", e.user, this);
  2464.     }
  2465.     
  2466.     this._removeUserFromGraph(e.lamer);
  2467.  
  2468.     updateChannel (e.channel);
  2469.     
  2470. }
  2471.  
  2472. CIRCChannel.prototype.onChanMode =
  2473. function my_cmode (e)
  2474. {
  2475.  
  2476.     if (e.user)
  2477.         this.display ("Mode " + e.params.slice(1).join(" ") + " by " +
  2478.                       e.user.properNick, "MODE", e.user, this);
  2479.  
  2480.     for (var u in e.usersAffected)
  2481.         e.usersAffected[u].updateGraphResource();
  2482.  
  2483.     updateChannel (e.channel);
  2484.     updateTitle (e.channel);
  2485.     
  2486. }
  2487.  
  2488.     
  2489.  
  2490. CIRCChannel.prototype.onNick =
  2491. function my_cnick (e)
  2492. {
  2493.  
  2494.     if (userIsMe (e.user))
  2495.     {
  2496.         this.display ("YOU are now known as " + e.user.properNick, "NICK",
  2497.                       "ME!", e.user, this);
  2498.         updateNetwork();
  2499.     }
  2500.     else
  2501.         this.display (e.oldNick + " is now known as " + e.user.properNick,
  2502.                       "NICK", e.user, this);
  2503.  
  2504.     /*
  2505.       dd ("updating resource " + e.user.getGraphResource().Value +
  2506.         " to new nickname " + e.user.properNick);
  2507.     */
  2508.  
  2509.     e.user.updateGraphResource();
  2510.     
  2511. }
  2512.  
  2513. CIRCChannel.prototype.onQuit =
  2514. function my_cquit (e)
  2515. {
  2516.  
  2517.     if (userIsMe(e.user)) /* I dont think this can happen */
  2518.         this.display ("YOU have left " + e.server.parent.name +
  2519.                       " (" + e.reason + ")", "QUIT", e.user, this);
  2520.     else
  2521.         this.display (e.user.properNick + " has left " + e.server.parent.name +
  2522.                       " (" + e.reason + ")", "QUIT", e.user, this);
  2523.  
  2524.     this._removeUserFromGraph(e.user);
  2525.  
  2526.     updateChannel (e.channel);
  2527.     
  2528. }
  2529.  
  2530. CIRCUser.prototype.onPrivmsg =
  2531. function my_cprivmsg (e)
  2532. {
  2533.     this.display (e.meat, "PRIVMSG", e.user, e.server.me);
  2534.     if (client.sound)
  2535.         if (client.BEEP_URL)
  2536.             client.sound.play (client.BEEP_URL);
  2537.         else
  2538.             client.sound.beep ();
  2539.  
  2540. }
  2541.  
  2542. CIRCUser.prototype.onNick =
  2543. function my_unick (e)
  2544. {
  2545.  
  2546.     if (userIsMe(e.user))
  2547.     {
  2548.         updateNetwork();
  2549.         updateTitle (e.channel);
  2550.     }
  2551.     
  2552. }
  2553.  
  2554. CIRCUser.prototype.onNotice =
  2555. function my_notice (e)
  2556. {
  2557.     this.display (e.meat, "NOTICE", this, e.server.me);   
  2558. }
  2559.  
  2560. CIRCUser.prototype.onCTCPAction =
  2561. function my_uaction (e)
  2562. {
  2563.  
  2564.     e.user.display (e.CTCPData, "ACTION", this, e.server.me);
  2565.  
  2566. }
  2567.  
  2568. CIRCUser.prototype.onUnknownCTCP =
  2569. function my_unkctcp (e)
  2570. {
  2571.  
  2572.     this.parent.parent.display ("Unknown CTCP " + e.CTCPCode + "(" +
  2573.                                 e.CTCPData + ") from " + e.user.properNick,
  2574.                                 "BAD-CTCP", this, e.server.me);
  2575.     
  2576. }
  2577.