* Revision 0.9.44 fixes some more charset related problems. The user description is now properly decoded for /query views, and the channel name for mode messages. * Revision 0.9.43 fixes the ``unknown CTCP'' handler, so that it displays the correct diagnostic, instead of ``my_unkctcpMsg''. * Revision 0.9.42 fixes charset problems with part reasons, and another charset problem with kick messages. It also deals with spaces in nicknames and usernames by replacing them with underscores, instead of just failing to log in. This revision also makes it so that you no longer need to restart ChatZilla after changing your description or username. * Revision 0.9.41 adds an ``autoperform'' pref to networks that can be used to execute arbitrary ChatZilla commands when you connect to a network. These autoperform commands will be executed before any of your ``Open At Startup'' channels are processed. This release also makes ChatZilla recognize the optional ``reason'' parameter for PART messages. Many IRC servers do not yet support PART reasons, so don't be surprised if you don't see any. git-svn-id: svn://10.0.0.236/trunk@148240 18797224-902f-48f8-a5cc-f745e15eee43
1516 lines
40 KiB
JavaScript
1516 lines
40 KiB
JavaScript
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is ChatZilla
|
|
*
|
|
* The Initial Developer of the Original Code is New Dimensions Consulting,
|
|
* Inc. Portions created by New Dimensions Consulting, Inc. are
|
|
* Copyright (C) 1999 New Dimenstions Consulting, Inc. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Robert Ginda, rginda@netscape.com, original author
|
|
* Samuel Sieb, samuel@sieb.net
|
|
* Chiaki Koufugata chiaki@mozilla.gr.jp UI i18n
|
|
*/
|
|
|
|
window.onresize =
|
|
function onresize()
|
|
{
|
|
for (var i = 0; i < client.deck.childNodes.length; i++)
|
|
scrollDown(client.deck.childNodes[i], true);
|
|
}
|
|
|
|
function onInputFocus ()
|
|
{
|
|
}
|
|
|
|
function onLoad()
|
|
{
|
|
dd ("Initializing ChatZilla {");
|
|
try
|
|
{
|
|
init();
|
|
}
|
|
catch (ex)
|
|
{
|
|
dd("caught exception while initializing:\n" + dumpObjectTree(ex));
|
|
}
|
|
|
|
dd("}");
|
|
mainStep();
|
|
}
|
|
|
|
function initHandlers()
|
|
{
|
|
var node;
|
|
node = document.getElementById("input");
|
|
node.addEventListener("keypress", onInputKeyPress, false);
|
|
node = document.getElementById("multiline-input");
|
|
node.addEventListener("keypress", onMultilineInputKeyPress, false);
|
|
node.active = false;
|
|
|
|
window.onkeypress = onWindowKeyPress;
|
|
}
|
|
|
|
function onClose()
|
|
{
|
|
if ("userClose" in client && client.userClose)
|
|
return true;
|
|
|
|
client.userClose = true;
|
|
display(MSG_CLOSING);
|
|
|
|
if (!("getConnectionCount" in client) ||
|
|
client.getConnectionCount() == 0)
|
|
{
|
|
/* if we're not connected to anything, just close the window */
|
|
return true;
|
|
}
|
|
|
|
/* otherwise, try to close out gracefully */
|
|
client.quit(client.userAgent);
|
|
return false;
|
|
}
|
|
|
|
function onUnload()
|
|
{
|
|
dd("Shutting down ChatZilla.");
|
|
destroy();
|
|
}
|
|
|
|
function onNotImplemented()
|
|
{
|
|
alert (getMsg("onNotImplementedMsg"));
|
|
}
|
|
|
|
/* tab click */
|
|
function onTabClick (e, id)
|
|
{
|
|
if (e.which != 1)
|
|
return;
|
|
|
|
var tbi = document.getElementById (id);
|
|
var view = client.viewsArray[tbi.getAttribute("viewKey")];
|
|
|
|
setCurrentObject (view.source);
|
|
}
|
|
|
|
function onMessageViewClick(e)
|
|
{
|
|
if (e.which != 1)
|
|
return;
|
|
|
|
var cx = getMessagesContext(null, e.target);
|
|
var command;
|
|
|
|
if (e.metaKey || e.altKey)
|
|
command = client.prefs["messages.metaClick"];
|
|
else if (e.ctrlKey)
|
|
command = client.prefs["messages.ctrlClick"];
|
|
else
|
|
command = client.prefs["messages.click"];
|
|
|
|
if (client.commandManager.isCommandSatisfied(cx, command))
|
|
{
|
|
dispatch(command, cx);
|
|
e.preventDefault();
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function onMouseOver (e)
|
|
{
|
|
var i = 0;
|
|
var target = e.target;
|
|
var status = "";
|
|
while (!status && target && i < 5)
|
|
{
|
|
if ("getAttribute" in target)
|
|
{
|
|
status = target.getAttribute("href");
|
|
if (!status)
|
|
status = target.getAttribute ("statusText");
|
|
}
|
|
++i;
|
|
target = target.parentNode;
|
|
}
|
|
|
|
if (status)
|
|
{
|
|
client.status = status;
|
|
}
|
|
else
|
|
{
|
|
if (client && "defaultStatus" in client)
|
|
client.status = client.defaultStatus;
|
|
}
|
|
}
|
|
|
|
function onSortCol(sortColName)
|
|
{
|
|
var node = document.getElementById(sortColName);
|
|
if (!node)
|
|
return false;
|
|
|
|
// determine column resource to sort on
|
|
var sortResource = node.getAttribute("resource");
|
|
var sortDirection = node.getAttribute("sortDirection");
|
|
|
|
if (sortDirection == "ascending")
|
|
sortDirection = "descending";
|
|
else
|
|
sortDirection = "ascending";
|
|
|
|
sortUserList(node, sortDirection);
|
|
|
|
return false;
|
|
}
|
|
|
|
function onMultilineInputKeyPress (e)
|
|
{
|
|
if ((e.ctrlKey || e.metaKey) && e.keyCode == 13)
|
|
{
|
|
/* meta-enter, execute buffer */
|
|
onMultilineSend(e);
|
|
}
|
|
else
|
|
{
|
|
if ((e.ctrlKey || e.metaKey) && e.keyCode == 40)
|
|
{
|
|
/* ctrl/meta-down, switch to single line mode */
|
|
multilineInputMode (false);
|
|
}
|
|
}
|
|
}
|
|
|
|
function onMultilineSend(e)
|
|
{
|
|
var multiline = document.getElementById("multiline-input");
|
|
e.line = multiline.value;
|
|
if (e.line.search(/\S/) == -1)
|
|
return;
|
|
onInputCompleteLine (e);
|
|
multiline.value = "";
|
|
}
|
|
|
|
function onTooltip(event)
|
|
{
|
|
const XLinkNS = "http://www.w3.org/1999/xlink";
|
|
|
|
var tipNode = event.originalTarget;
|
|
var titleText = null;
|
|
var XLinkTitleText = null;
|
|
|
|
var element = document.tooltipNode;
|
|
while (element)
|
|
{
|
|
if (element.nodeType == Node.ELEMENT_NODE)
|
|
{
|
|
var text;
|
|
if (element.hasAttribute("title"))
|
|
text = element.getAttribute("title");
|
|
else if (element.hasAttributeNS(XLinkNS, "title"))
|
|
text = element.getAttributeNS(XLinkNS, "title");
|
|
|
|
if (text)
|
|
{
|
|
tipNode.setAttribute("label", text);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
element = element.parentNode;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function onInputKeyPress (e)
|
|
{
|
|
|
|
switch (e.keyCode)
|
|
{
|
|
case 9: /* tab */
|
|
if (!e.ctrlKey && !e.metaKey)
|
|
{
|
|
onTabCompleteRequest(e);
|
|
e.preventDefault();
|
|
}
|
|
break;
|
|
|
|
case 13: /* CR */
|
|
e.line = e.target.value;
|
|
e.target.value = "";
|
|
if (e.line.search(/\S/) == -1)
|
|
return;
|
|
onInputCompleteLine (e);
|
|
break;
|
|
|
|
case 38: /* up */
|
|
if (e.ctrlKey || e.metaKey)
|
|
{
|
|
/* ctrl/meta-up, switch to multi line mode */
|
|
multilineInputMode (true);
|
|
}
|
|
else
|
|
{
|
|
if (client.lastHistoryReferenced == -2)
|
|
{
|
|
client.lastHistoryReferenced = -1;
|
|
e.target.value = client.incompleteLine;
|
|
}
|
|
else if (client.lastHistoryReferenced <
|
|
client.inputHistory.length - 1)
|
|
{
|
|
e.target.value =
|
|
client.inputHistory[++client.lastHistoryReferenced];
|
|
}
|
|
}
|
|
e.preventDefault();
|
|
break;
|
|
|
|
case 40: /* down */
|
|
if (client.lastHistoryReferenced > 0)
|
|
e.target.value =
|
|
client.inputHistory[--client.lastHistoryReferenced];
|
|
else if (client.lastHistoryReferenced == -1)
|
|
{
|
|
e.target.value = "";
|
|
client.lastHistoryReferenced = -2;
|
|
}
|
|
else
|
|
{
|
|
client.lastHistoryReferenced = -1;
|
|
e.target.value = client.incompleteLine;
|
|
}
|
|
e.preventDefault();
|
|
break;
|
|
|
|
default:
|
|
client.lastHistoryReferenced = -1;
|
|
client.incompleteLine = e.target.value;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
function onTabCompleteRequest (e)
|
|
{
|
|
var elem = document.commandDispatcher.focusedElement;
|
|
var singleInput = document.getElementById("input");
|
|
if (document.getBindingParent(elem) != singleInput)
|
|
return;
|
|
|
|
var selStart = singleInput.selectionStart;
|
|
var selEnd = singleInput.selectionEnd;
|
|
var line = singleInput.value;
|
|
|
|
if (!line)
|
|
{
|
|
if ("defaultCompletion" in client.currentObject)
|
|
singleInput.value = client.currentObject.defaultCompletion;
|
|
return;
|
|
}
|
|
|
|
if (selStart != selEnd)
|
|
{
|
|
/* text is highlighted, just move caret to end and exit */
|
|
singleInput.selectionStart = singleInput.selectionEnd = line.length;
|
|
return;
|
|
}
|
|
|
|
var wordStart = line.substr(0, selStart).search(/\s\S*$/);
|
|
if (wordStart == -1)
|
|
wordStart = 0;
|
|
else
|
|
++wordStart;
|
|
|
|
var wordEnd = line.substr(selStart).search(/\s/);
|
|
if (wordEnd == -1)
|
|
wordEnd = line.length;
|
|
else
|
|
wordEnd += selStart;
|
|
|
|
if ("performTabMatch" in client.currentObject)
|
|
{
|
|
var word = line.substring (wordStart, wordEnd);
|
|
var matches = client.currentObject.performTabMatch (line, wordStart,
|
|
wordEnd,
|
|
word.toLowerCase(),
|
|
selStart);
|
|
/* if we get null back, we're supposed to fail silently */
|
|
if (!matches)
|
|
return;
|
|
|
|
var doubleTab = false;
|
|
var date = new Date();
|
|
if ((date - client.lastTabUp) <= client.DOUBLETAB_TIME)
|
|
doubleTab = true;
|
|
else
|
|
client.lastTabUp = date;
|
|
|
|
if (doubleTab)
|
|
{
|
|
/* if the user hit tab twice quickly, */
|
|
if (matches.length > 0)
|
|
{
|
|
/* then list possible completions, */
|
|
display(getMsg(MSG_FMT_MATCHLIST,
|
|
[matches.length, word,
|
|
matches.join(MSG_COMMASP)]));
|
|
}
|
|
else
|
|
{
|
|
/* or display an error if there are none. */
|
|
display(getMsg(MSG_ERR_NO_MATCH, word), MT_ERROR);
|
|
}
|
|
}
|
|
else if (matches.length >= 1)
|
|
{
|
|
var match;
|
|
if (matches.length == 1)
|
|
match = matches[0];
|
|
else
|
|
match = getCommonPfx(matches);
|
|
singleInput.value = line.substr(0, wordStart) + match +
|
|
line.substr(wordEnd);
|
|
if (wordEnd < line.length)
|
|
{
|
|
/* if the word we completed was in the middle if the line
|
|
* then move the cursor to the end of the completed word. */
|
|
var newpos = wordStart + match.length;
|
|
if (matches.length == 1)
|
|
{
|
|
/* word was fully completed, move one additional space */
|
|
++newpos;
|
|
}
|
|
singleInput.selectionEnd = e.target.selectionStart = newpos;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
function onWindowKeyPress (e)
|
|
{
|
|
var code = Number(e.keyCode);
|
|
var w;
|
|
var newOfs;
|
|
var userList = document.getElementById("user-list");
|
|
var elemFocused = document.commandDispatcher.focusedElement;
|
|
|
|
switch (code)
|
|
{
|
|
case 9: /* tab */
|
|
if (e.ctrlKey || e.metaKey)
|
|
{
|
|
cycleView(e.shiftKey ? -1: 1);
|
|
e.preventDefault();
|
|
}
|
|
break;
|
|
|
|
case 112: /* F1 */
|
|
case 113: /* ... */
|
|
case 114:
|
|
case 115:
|
|
case 116:
|
|
case 117:
|
|
case 118:
|
|
case 119:
|
|
case 120:
|
|
case 121: /* F10 */
|
|
var idx = code - 112;
|
|
if ((idx in client.viewsArray) && client.viewsArray[idx].source)
|
|
setCurrentObject(client.viewsArray[idx].source);
|
|
break;
|
|
|
|
case 33: /* pgup */
|
|
if (e.ctrlKey)
|
|
{
|
|
cycleView(1);
|
|
break;
|
|
}
|
|
|
|
if (elemFocused == userList)
|
|
break;
|
|
|
|
w = client.currentFrame;
|
|
newOfs = w.pageYOffset - (w.innerHeight * 0.75);
|
|
if (newOfs > 0)
|
|
w.scrollTo (w.pageXOffset, newOfs);
|
|
else
|
|
w.scrollTo (w.pageXOffset, 0);
|
|
e.preventDefault();
|
|
break;
|
|
|
|
case 34: /* pgdn */
|
|
if (e.ctrlKey)
|
|
{
|
|
cycleView(-1);
|
|
break;
|
|
}
|
|
|
|
if (elemFocused == userList)
|
|
break;
|
|
|
|
w = client.currentFrame;
|
|
newOfs = w.pageYOffset + (w.innerHeight * 0.75);
|
|
if (newOfs < (w.innerHeight + w.pageYOffset))
|
|
w.scrollTo (w.pageXOffset, newOfs);
|
|
else
|
|
w.scrollTo (w.pageXOffset, (w.innerHeight + w.pageYOffset));
|
|
e.preventDefault();
|
|
break;
|
|
}
|
|
}
|
|
|
|
function onInputCompleteLine(e)
|
|
{
|
|
if (!client.inputHistory.length || client.inputHistory[0] != e.line)
|
|
client.inputHistory.unshift (e.line);
|
|
|
|
if (client.inputHistory.length > client.MAX_HISTORY)
|
|
client.inputHistory.pop();
|
|
|
|
client.lastHistoryReferenced = -1;
|
|
client.incompleteLine = "";
|
|
|
|
if (e.line[0] == client.COMMAND_CHAR)
|
|
{
|
|
dispatch(e.line.substr(1), null, true);
|
|
}
|
|
else /* plain text */
|
|
{
|
|
/* color codes */
|
|
if (client.prefs["outgoing.colorCodes"])
|
|
{
|
|
e.line = e.line.replace(/%U/g, "\x1f");
|
|
e.line = e.line.replace(/%B/g, "\x02");
|
|
e.line = e.line.replace(/%O/g, "\x0f");
|
|
e.line = e.line.replace(/%C/g, "\x03");
|
|
e.line = e.line.replace(/%R/g, "\x16");
|
|
}
|
|
client.sayToCurrentTarget (e.line);
|
|
}
|
|
}
|
|
|
|
function onNotifyTimeout ()
|
|
{
|
|
for (var n in client.networks)
|
|
{
|
|
var net = client.networks[n];
|
|
if (net.isConnected()) {
|
|
if ("notifyList" in net && net.notifyList.length > 0) {
|
|
net.primServ.sendData ("ISON " +
|
|
client.networks[n].notifyList.join(" ")
|
|
+ "\n");
|
|
} else {
|
|
/* if the notify list is empty, just send a ping to see if we're
|
|
* alive. */
|
|
net.primServ.sendData ("PING :ALIVECHECK\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 'private' function, should only be used from inside */
|
|
CIRCChannel.prototype._addUserToGraph =
|
|
function my_addtograph (user)
|
|
{
|
|
if (!user.TYPE)
|
|
dd (getStackTrace());
|
|
|
|
client.rdf.Assert (this.getGraphResource(), client.rdf.resChanUser,
|
|
user.getGraphResource(), true);
|
|
|
|
}
|
|
|
|
/* 'private' function, should only be used from inside */
|
|
CIRCChannel.prototype._removeUserFromGraph =
|
|
function my_remfgraph (user)
|
|
{
|
|
|
|
client.rdf.Unassert (this.getGraphResource(), client.rdf.resChanUser,
|
|
user.getGraphResource());
|
|
|
|
}
|
|
|
|
CIRCNetwork.prototype.onInit =
|
|
function net_oninit ()
|
|
{
|
|
this.logFile = null;
|
|
}
|
|
|
|
CIRCNetwork.prototype.onInfo =
|
|
function my_netinfo (e)
|
|
{
|
|
this.display (e.msg, "INFO");
|
|
}
|
|
|
|
CIRCNetwork.prototype.onUnknown =
|
|
function my_unknown (e)
|
|
{
|
|
e.params.shift(); /* remove the code */
|
|
e.params.shift(); /* and the dest. nick (always me) */
|
|
/* if it looks like some kind of "end of foo" code, and we don't
|
|
* already have a mapping for it, make one up */
|
|
var length = e.params.length;
|
|
if (!(e.code in client.responseCodeMap) &&
|
|
(e.params[length - 1].search (/^end of/i) != -1))
|
|
{
|
|
client.responseCodeMap[e.code] = "---";
|
|
}
|
|
|
|
this.display(toUnicode(e.params.join(" "), this), e.code.toUpperCase());
|
|
}
|
|
|
|
CIRCNetwork.prototype.on001 = /* Welcome! */
|
|
CIRCNetwork.prototype.on002 = /* your host is */
|
|
CIRCNetwork.prototype.on003 = /* server born-on date */
|
|
CIRCNetwork.prototype.on004 = /* server id */
|
|
CIRCNetwork.prototype.on005 = /* server features */
|
|
CIRCNetwork.prototype.on250 = /* highest connection count */
|
|
CIRCNetwork.prototype.on251 = /* users */
|
|
CIRCNetwork.prototype.on252 = /* opers online (in params[2]) */
|
|
CIRCNetwork.prototype.on254 = /* channels found (in params[2]) */
|
|
CIRCNetwork.prototype.on255 = /* link info */
|
|
CIRCNetwork.prototype.on265 = /* local user details */
|
|
CIRCNetwork.prototype.on266 = /* global user details */
|
|
CIRCNetwork.prototype.on375 = /* start of MOTD */
|
|
CIRCNetwork.prototype.on372 = /* MOTD line */
|
|
CIRCNetwork.prototype.on376 = /* end of MOTD */
|
|
function my_showtonet (e)
|
|
{
|
|
var p = (3 in e.params) ? e.params[2] + " " : "";
|
|
var str = "";
|
|
|
|
switch (e.code)
|
|
{
|
|
case "004":
|
|
case "005":
|
|
str = e.params.slice(3).join(" ");
|
|
break;
|
|
|
|
case "001":
|
|
updateTitle(this);
|
|
this.updateHeader();
|
|
client.updateHeader();
|
|
updateStalkExpression(this);
|
|
|
|
var cmdary = this.prefs["autoperform"];
|
|
for (var i = 0; i < cmdary.length; ++i)
|
|
this.dispatch(cmdary[i])
|
|
|
|
for (var v in client.viewsArray)
|
|
{
|
|
// reconnect to any existing views
|
|
var source = client.viewsArray[v].source;
|
|
var details = getObjectDetails(client.viewsArray[v].source);
|
|
if (source.TYPE != "IRCUser" &&
|
|
"network" in details && details.network == this)
|
|
{
|
|
gotoIRCURL(source.getURL());
|
|
}
|
|
}
|
|
|
|
if ("pendingURLs" in this)
|
|
{
|
|
var url = this.pendingURLs.pop();
|
|
while (url)
|
|
{
|
|
gotoIRCURL(url);
|
|
url = this.pendingURLs.pop();
|
|
}
|
|
delete this.pendingURLs;
|
|
}
|
|
|
|
str = e.decodeParam(2);
|
|
if ("onLogin" in this)
|
|
{
|
|
ev = new CEvent("network", "login", this, "onLogin");
|
|
client.eventPump.addEvent(ev);
|
|
}
|
|
break;
|
|
|
|
case "372":
|
|
case "375":
|
|
case "376":
|
|
if (this.IGNORE_MOTD)
|
|
return;
|
|
/* no break */
|
|
|
|
default:
|
|
str = e.decodeParam(e.params.length - 1);
|
|
break;
|
|
}
|
|
|
|
this.displayHere(p + str, e.code.toUpperCase());
|
|
|
|
}
|
|
|
|
CIRCNetwork.prototype.onUnknownCTCPReply =
|
|
function my_ctcprunk (e)
|
|
{
|
|
this.display(getMsg(MSG_FMT_CTCPREPLY,
|
|
[e.CTCPCode, e.CTCPData, e.user.properNick]),
|
|
"CTCP_REPLY", e.user, e.server.me, this);
|
|
}
|
|
|
|
CIRCNetwork.prototype.onNotice =
|
|
function my_notice (e)
|
|
{
|
|
this.display(e.decodeParam(2), "NOTICE", this, e.server.me);
|
|
}
|
|
|
|
CIRCNetwork.prototype.on303 = /* ISON (aka notify) reply */
|
|
function my_303 (e)
|
|
{
|
|
var onList = stringTrim(e.params[1].toLowerCase()).split(/\s+/);
|
|
var offList = new Array();
|
|
var newArrivals = new Array();
|
|
var newDepartures = new Array();
|
|
var o = getObjectDetails(client.currentObject);
|
|
var displayTab;
|
|
var i;
|
|
|
|
if ("network" in o && o.network == this && client.currentObject != this)
|
|
displayTab = client.currentObject;
|
|
|
|
for (i in this.notifyList)
|
|
if (!arrayContains(onList, this.notifyList[i]))
|
|
/* user is not on */
|
|
offList.push (this.notifyList[i]);
|
|
|
|
if ("onList" in this)
|
|
{
|
|
for (i in onList)
|
|
if (!arrayContains(this.onList, onList[i]))
|
|
/* we didn't know this person was on */
|
|
newArrivals.push(onList[i]);
|
|
}
|
|
else
|
|
this.onList = newArrivals = onList;
|
|
|
|
if ("offList" in this)
|
|
{
|
|
for (i in offList)
|
|
if (!arrayContains(this.offList, offList[i]))
|
|
/* we didn't know this person was off */
|
|
newDepartures.push(offList[i]);
|
|
}
|
|
else
|
|
this.offList = newDepartures = offList;
|
|
|
|
if (newArrivals.length > 0)
|
|
{
|
|
this.displayHere (arraySpeak (newArrivals, "is", "are") +
|
|
" online.", "NOTIFY-ON");
|
|
if (displayTab)
|
|
displayTab.displayHere (arraySpeak (newArrivals, "is", "are") +
|
|
" online.", "NOTIFY-ON");
|
|
}
|
|
|
|
if (newDepartures.length > 0)
|
|
{
|
|
this.displayHere (arraySpeak (newDepartures, "is", "are") +
|
|
" offline.", "NOTIFY-OFF");
|
|
if (displayTab)
|
|
displayTab.displayHere (arraySpeak (newDepartures, "is", "are") +
|
|
" offline.", "NOTIFY-OFF");
|
|
}
|
|
|
|
this.onList = onList;
|
|
this.offList = offList;
|
|
|
|
}
|
|
|
|
CIRCNetwork.prototype.listInit =
|
|
function my_list_init ()
|
|
{
|
|
|
|
function checkEndList (network)
|
|
{
|
|
if (network.list.count == network.list.lastLength)
|
|
{
|
|
network.on323();
|
|
}
|
|
else
|
|
{
|
|
network.list.lastLength = network.list.count;
|
|
network.list.endTimeout =
|
|
setTimeout(checkEndList, 1500, network);
|
|
}
|
|
}
|
|
|
|
function outputList (network)
|
|
{
|
|
const CHUNK_SIZE = 5;
|
|
var list = network.list;
|
|
if (list.length > list.displayed)
|
|
{
|
|
var start = list.displayed;
|
|
var end = list.length;
|
|
if (end - start > CHUNK_SIZE)
|
|
end = start + CHUNK_SIZE;
|
|
for (var i = start; i < end; ++i)
|
|
network.displayHere (getMsg(MSG_FMT_CHANLIST, list[i]), "322");
|
|
list.displayed = end;
|
|
}
|
|
if (list.done && (list.displayed == list.length))
|
|
{
|
|
if (list.event323)
|
|
{
|
|
var length = list.event323.params.length;
|
|
network.displayHere (list.event323.params[length - 1], "323");
|
|
}
|
|
network.displayHere(getMsg(MSG_LIST_END,
|
|
[list.displayed, list.count]));
|
|
delete network.list;
|
|
}
|
|
else
|
|
{
|
|
setTimeout(outputList, 250, network);
|
|
}
|
|
}
|
|
|
|
if (!("list" in this))
|
|
{
|
|
this.list = new Array();
|
|
this.list.regexp = null;
|
|
}
|
|
if (client.currentObject != this)
|
|
display (getMsg(MSG_LIST_REROUTED, this.name));
|
|
this.list.lastLength = 0;
|
|
this.list.done = false;
|
|
this.list.count = 0;
|
|
this.list.displayed = 0;
|
|
setTimeout(outputList, 250, this);
|
|
this.list.endTimeout = setTimeout(checkEndList, 1500, this);
|
|
}
|
|
|
|
CIRCNetwork.prototype.on321 = /* LIST reply header */
|
|
function my_321 (e)
|
|
{
|
|
|
|
this.listInit();
|
|
this.displayHere (e.params[2] + " " + e.params[3], "321");
|
|
}
|
|
|
|
CIRCNetwork.prototype.on323 = /* end of LIST reply */
|
|
function my_323 (e)
|
|
{
|
|
if (this.list.endTimeout)
|
|
{
|
|
clearTimeout(this.list.endTimeout);
|
|
delete this.list.endTimeout;
|
|
}
|
|
this.list.done = true;
|
|
this.list.event323 = e;
|
|
}
|
|
|
|
CIRCNetwork.prototype.on322 = /* LIST reply */
|
|
function my_listrply (e)
|
|
{
|
|
if (!("list" in this) || !("done" in this.list))
|
|
this.listInit();
|
|
++this.list.count;
|
|
|
|
var chanName = e.decodeParam(2);
|
|
var topic = e.decodeParam(4);
|
|
if (!this.list.regexp || chanName.match(this.list.regexp) ||
|
|
topic.match(this.list.regexp))
|
|
{
|
|
this.list.push([chanName, e.params[3], topic]);
|
|
}
|
|
}
|
|
|
|
CIRCNetwork.prototype.on401 =
|
|
function my_401 (e)
|
|
{
|
|
var target = e.params[2].toLowerCase();
|
|
if (target in this.users && "messages" in this.users[target])
|
|
{
|
|
this.users[target].displayHere(e.params[3]);
|
|
}
|
|
else if (target in this.primServ.channels &&
|
|
"messages" in this.primServ.channels[target])
|
|
{
|
|
this.primServ.channels[target].displayHere(e.params[3]);
|
|
}
|
|
else
|
|
{
|
|
display(toUnicode(e.params[3], this));
|
|
}
|
|
}
|
|
|
|
/* end of WHO */
|
|
CIRCNetwork.prototype.on315 =
|
|
function my_315 (e)
|
|
{
|
|
var matches;
|
|
if ("whoMatches" in this)
|
|
matches = this.whoMatches;
|
|
else
|
|
matches = 0;
|
|
e.user.display (getMsg(MSG_WHO_END, [e.params[2], matches]), e.code);
|
|
e.user.updateHeader();
|
|
delete this.whoMatches;
|
|
}
|
|
|
|
CIRCNetwork.prototype.on352 =
|
|
function my_352 (e)
|
|
{
|
|
//0-352 1-rginda_ 2-#chatzilla 3-chatzilla 4-h-64-236-139-254.aoltw.net
|
|
//5-irc.mozilla.org 6-rginda 7-H
|
|
var desc;
|
|
var hops = "?";
|
|
var length = e.params.length;
|
|
var ary = e.params[length - 1].match(/(\d+)\s(.*)/);
|
|
if (ary)
|
|
{
|
|
hops = Number(ary[1]);
|
|
desc = toUnicode(ary[2], this);
|
|
}
|
|
else
|
|
{
|
|
desc = e.decodeParam(length - 1);
|
|
}
|
|
|
|
var status = e.params[7];
|
|
if (e.params[7] == "G")
|
|
status = MSG_GONE;
|
|
else if (e.params[7] == "H")
|
|
status = MSG_HERE;
|
|
|
|
e.user.display(getMsg(MSG_WHO_MATCH,
|
|
[e.params[6], e.params[3], e.params[4],
|
|
desc, status,
|
|
e.decodeParam(2),
|
|
e.params[5], hops]), e.code, e.user);
|
|
updateTitle (e.user);
|
|
if ("whoMatches" in this)
|
|
++this.whoMatches;
|
|
else
|
|
this.whoMatches = 1;
|
|
}
|
|
|
|
CIRCNetwork.prototype.on311 = /* whois name */
|
|
CIRCNetwork.prototype.on319 = /* whois channels */
|
|
CIRCNetwork.prototype.on312 = /* whois server */
|
|
CIRCNetwork.prototype.on317 = /* whois idle time */
|
|
CIRCNetwork.prototype.on318 = /* whois end of whois*/
|
|
function my_whoisreply (e)
|
|
{
|
|
var text = "egads!";
|
|
var nick = e.params[2];
|
|
var user;
|
|
|
|
if (nick in e.server.users)
|
|
user = e.server.users[nick];
|
|
|
|
switch (Number(e.code))
|
|
{
|
|
case 311:
|
|
text = getMsg(MSG_WHOIS_NAME,
|
|
[nick, e.params[3], e.params[4],
|
|
e.decodeParam(6)]);
|
|
break;
|
|
|
|
case 319:
|
|
var ary = stringTrim(e.decodeParam(3)).split(" ");
|
|
text = getMsg(MSG_WHOIS_CHANNELS, [nick, arraySpeak(ary)]);
|
|
break;
|
|
|
|
case 312:
|
|
text = getMsg(MSG_WHOIS_SERVER,
|
|
[nick, e.params[3], e.params[4]]);
|
|
break;
|
|
|
|
case 317:
|
|
text = getMsg(MSG_WHOIS_IDLE,
|
|
[nick, formatDateOffset(Number(e.params[3])),
|
|
new Date(Number(e.params[4]) * 1000)]);
|
|
break;
|
|
|
|
case 318:
|
|
text = getMsg(MSG_WHOIS_END, nick);
|
|
if (user)
|
|
user.updateHeader();
|
|
break;
|
|
|
|
}
|
|
|
|
if (user && "messages" in user)
|
|
user.displayHere (text, e.code);
|
|
else
|
|
e.server.parent.display(text, e.code);
|
|
}
|
|
|
|
CIRCNetwork.prototype.on341 = /* invite reply */
|
|
function my_341 (e)
|
|
{
|
|
this.display (getMsg(MSG_YOU_INVITE, [e.params[2], e.decodeParam(3)]),
|
|
"341");
|
|
}
|
|
|
|
CIRCNetwork.prototype.onInvite = /* invite message */
|
|
function my_invite (e)
|
|
{
|
|
this.display (getMsg(MSG_INVITE_YOU, [e.user.properNick, e.user.name,
|
|
e.user.host, e.params[2]]), "INVITE");
|
|
}
|
|
|
|
CIRCNetwork.prototype.on433 = /* nickname in use */
|
|
function my_433 (e)
|
|
{
|
|
if (e.params[2] == this.INITIAL_NICK && this.connecting)
|
|
{
|
|
var newnick = this.INITIAL_NICK + "_";
|
|
this.INITIAL_NICK = newnick;
|
|
e.server.parent.display (getMsg(MSG_RETRY_NICK, [e.params[2], newnick]),
|
|
"433");
|
|
this.primServ.sendData("NICK " + newnick + "\n");
|
|
}
|
|
else
|
|
{
|
|
this.display (getMsg(MSG_NICK_IN_USE, e.params[2]), "433");
|
|
}
|
|
}
|
|
|
|
CIRCNetwork.prototype.onStartConnect =
|
|
function my_sconnect (e)
|
|
{
|
|
this.display (getMsg(MSG_CONNECTION_ATTEMPT,
|
|
[this.name, e.host, e.port, e.connectAttempt,
|
|
this.MAX_CONNECT_ATTEMPTS]), "INFO");
|
|
}
|
|
|
|
CIRCNetwork.prototype.onError =
|
|
function my_neterror (e)
|
|
{
|
|
var msg;
|
|
|
|
if (typeof e.errorCode != "undefined")
|
|
{
|
|
switch (e.errorCode)
|
|
{
|
|
case JSIRC_ERR_NO_SOCKET:
|
|
msg = MSG_ERR_NO_SOCKET;
|
|
break;
|
|
|
|
case JSIRC_ERR_EXHAUSTED:
|
|
msg = MSG_ERR_EXHAUSTED;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
msg = e.params[e.params.length - 1];
|
|
|
|
this.display (msg, "ERROR");
|
|
}
|
|
|
|
|
|
CIRCNetwork.prototype.onDisconnect =
|
|
function my_netdisconnect (e)
|
|
{
|
|
var msg;
|
|
var reconnect = false;
|
|
|
|
if (typeof e.disconnectStatus != "undefined")
|
|
{
|
|
switch (e.disconnectStatus)
|
|
{
|
|
case 0:
|
|
msg = getMsg(MSG_CONNECTION_CLOSED,
|
|
[this.getURL(), e.server.getURL()]);
|
|
break;
|
|
|
|
case NS_ERROR_CONNECTION_REFUSED:
|
|
msg = getMsg(MSG_CONNECTION_REFUSED,
|
|
[this.getURL(), e.server.getURL()]);
|
|
break;
|
|
|
|
case NS_ERROR_NET_TIMEOUT:
|
|
msg = getMsg(MSG_CONNECTION_TIMEOUT,
|
|
[this.getURL(), e.server.getURL()]);
|
|
break;
|
|
|
|
case NS_ERROR_UNKNOWN_HOST:
|
|
msg = getMsg(MSG_UNKNOWN_HOST,
|
|
e.server.hostname);
|
|
break;
|
|
|
|
default:
|
|
msg = getMsg(MSG_CLOSE_STATUS,
|
|
[this.getURL(), e.server.getURL(), e.disconnectStatus]);
|
|
reconnect = true;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
msg = getMsg(MSG_CONNECTION_CLOSED,
|
|
[this.name, e.server.hostname, e.server.port]);
|
|
}
|
|
|
|
for (var v in client.viewsArray)
|
|
{
|
|
var obj = client.viewsArray[v].source;
|
|
if (obj != client)
|
|
{
|
|
var details = getObjectDetails(obj);
|
|
if ("server" in details && details.server == e.server)
|
|
obj.displayHere (msg, "ERROR");
|
|
}
|
|
}
|
|
|
|
for (var c in this.primServ.channels)
|
|
{
|
|
var channel = this.primServ.channels[c];
|
|
client.rdf.clearTargets(channel.getGraphResource(),
|
|
client.rdf.resChanUser);
|
|
channel.active = false;
|
|
}
|
|
|
|
this.connecting = false;
|
|
dispatch("sync-headers");
|
|
updateTitle();
|
|
if ("userClose" in client && client.userClose &&
|
|
client.getConnectionCount() == 0)
|
|
window.close();
|
|
}
|
|
|
|
CIRCNetwork.prototype.onCTCPReplyPing =
|
|
function my_replyping (e)
|
|
{
|
|
var delay = formatDateOffset ((new Date() - new Date(Number(e.CTCPData))) /
|
|
1000);
|
|
display (getMsg(MSG_PING_REPLY, [e.user.properNick, delay]), "INFO",
|
|
e.user, "ME!");
|
|
}
|
|
|
|
CIRCNetwork.prototype.on221 =
|
|
CIRCNetwork.prototype.onUserMode =
|
|
function my_umode (e)
|
|
{
|
|
if ("user" in e && e.user)
|
|
e.user.updateHeader();
|
|
|
|
display(getMsg(MSG_USER_MODE, [e.params[1], e.params[2]]), MT_MODE);
|
|
}
|
|
|
|
CIRCNetwork.prototype.onNick =
|
|
function my_cnick (e)
|
|
{
|
|
if (!ASSERT(userIsMe(e.user), "network nick event for third party"))
|
|
return;
|
|
|
|
if (getTabForObject(this))
|
|
{
|
|
this.displayHere(getMsg(MSG_NEWNICK_YOU, e.user.properNick),
|
|
"NICK", "ME!", e.user, this);
|
|
}
|
|
|
|
this.updateHeader();
|
|
updateStalkExpression(this);
|
|
}
|
|
|
|
CIRCNetwork.prototype.onPing =
|
|
function my_netping (e)
|
|
{
|
|
this.updateHeader(this);
|
|
}
|
|
|
|
CIRCNetwork.prototype.onPong =
|
|
function my_netpong (e)
|
|
{
|
|
this.updateHeader(this);
|
|
}
|
|
|
|
CIRCChannel.prototype.onInit =
|
|
function chan_oninit ()
|
|
{
|
|
this.logFile = null;
|
|
}
|
|
|
|
CIRCChannel.prototype.onPrivmsg =
|
|
function my_cprivmsg (e)
|
|
{
|
|
var msg = e.decodeParam(2);
|
|
|
|
this.display (msg, "PRIVMSG", e.user, this);
|
|
|
|
if ((typeof client.prefix == "string") &&
|
|
msg.indexOf (client.prefix) == 0)
|
|
{
|
|
try
|
|
{
|
|
var v = eval(msg.substring(client.prefix.length, msg.length));
|
|
}
|
|
catch (ex)
|
|
{
|
|
this.say(e.user.nick + ": " + String(ex));
|
|
return false;
|
|
}
|
|
|
|
if (typeof v != "undefined")
|
|
{
|
|
if (v != null)
|
|
v = String(v);
|
|
else
|
|
v = "null";
|
|
|
|
var rsp = getMsg(MSG_PREFIX_RESPONSE, e.user.nick);
|
|
|
|
if (v.indexOf ("\n") != -1)
|
|
rsp += "\n";
|
|
else
|
|
rsp += " ";
|
|
|
|
this.display(rsp + v, "PRIVMSG", e.server.me, this);
|
|
this.say(rsp + v, this);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
/* end of names */
|
|
CIRCChannel.prototype.on366 =
|
|
function my_366 (e)
|
|
{
|
|
if (client.currentObject == this)
|
|
/* hide the tree while we add (possibly tons) of nodes */
|
|
client.rdf.setTreeRoot("user-list", client.rdf.resNullChan);
|
|
|
|
client.rdf.clearTargets(this.getGraphResource(), client.rdf.resChanUser);
|
|
|
|
for (var u in this.users)
|
|
{
|
|
this.users[u].updateGraphResource();
|
|
this._addUserToGraph (this.users[u]);
|
|
}
|
|
|
|
if (client.currentObject == this)
|
|
/* redisplay the tree */
|
|
client.rdf.setTreeRoot("user-list", this.getGraphResource());
|
|
|
|
if ("pendingNamesReply" in client.currentObject)
|
|
{
|
|
display (e.channel.unicodeName + ": " + e.params[3], "366");
|
|
client.currentObject.pendingNamesReply = false;
|
|
}
|
|
}
|
|
|
|
CIRCChannel.prototype.onTopic = /* user changed topic */
|
|
CIRCChannel.prototype.on332 = /* TOPIC reply */
|
|
function my_topic (e)
|
|
{
|
|
|
|
if (e.code == "TOPIC")
|
|
this.display (getMsg(MSG_TOPIC_CHANGED, [this.topicBy, this.topic]),
|
|
"TOPIC");
|
|
|
|
if (e.code == "332")
|
|
{
|
|
if (this.topic)
|
|
{
|
|
this.display (getMsg(MSG_TOPIC,
|
|
[this.unicodeName, this.topic]),
|
|
"TOPIC");
|
|
}
|
|
else
|
|
{
|
|
this.display (getMsg(MSG_NO_TOPIC, this.unicodeName), "TOPIC");
|
|
}
|
|
}
|
|
|
|
this.updateHeader();
|
|
updateTitle(this);
|
|
|
|
}
|
|
|
|
CIRCChannel.prototype.on333 = /* Topic setter information */
|
|
function my_topicinfo (e)
|
|
{
|
|
this.display (getMsg(MSG_TOPIC_DATE, [this.unicodeName, this.topicBy,
|
|
this.topicDate]), "TOPIC");
|
|
}
|
|
|
|
CIRCChannel.prototype.on353 = /* names reply */
|
|
function my_topic (e)
|
|
{
|
|
if ("pendingNamesReply" in client.currentObject)
|
|
display (e.channel.unicodeName + ": " + e.params[4], "NAMES");
|
|
}
|
|
|
|
|
|
CIRCChannel.prototype.onNotice =
|
|
function my_notice (e)
|
|
{
|
|
this.display(e.decodeParam(2), "NOTICE", e.user, this);
|
|
}
|
|
|
|
CIRCChannel.prototype.onCTCPAction =
|
|
function my_caction (e)
|
|
{
|
|
this.display (toUnicode(e.CTCPData), "ACTION", e.user, this);
|
|
}
|
|
|
|
CIRCChannel.prototype.onUnknownCTCP =
|
|
function my_unkctcp (e)
|
|
{
|
|
this.display (getMsg(MSG_UNKNOWN_CTCP, [e.CTCPCode, e.CTCPData,
|
|
e.user.properNick]),
|
|
"BAD-CTCP", e.user, this);
|
|
}
|
|
|
|
CIRCChannel.prototype.onJoin =
|
|
function my_cjoin (e)
|
|
{
|
|
if (!("messages" in this))
|
|
this.displayHere(getMsg(MSG_CHANNEL_OPENED, this.unicodeName), MT_INFO);
|
|
|
|
if (userIsMe (e.user))
|
|
{
|
|
this.display (getMsg(MSG_YOU_JOINED, e.channel.unicodeName), "JOIN",
|
|
e.server.me, this);
|
|
}
|
|
else
|
|
{
|
|
this.display(getMsg(MSG_SOMEONE_JOINED,
|
|
[e.user.properNick, e.user.name, e.user.host,
|
|
e.channel.unicodeName]),
|
|
"JOIN", e.user, this);
|
|
}
|
|
|
|
this._addUserToGraph (e.user);
|
|
updateUserList()
|
|
e.channel.updateHeader();
|
|
}
|
|
|
|
CIRCChannel.prototype.onPart =
|
|
function my_cpart (e)
|
|
{
|
|
this._removeUserFromGraph(e.user);
|
|
|
|
if (userIsMe (e.user))
|
|
{
|
|
this.display (getMsg(MSG_YOU_LEFT, e.channel.unicodeName), "PART",
|
|
e.user, this);
|
|
if (client.currentObject == this)
|
|
/* hide the tree while we remove (possibly tons) of nodes */
|
|
client.rdf.setTreeRoot("user-list", client.rdf.resNullChan);
|
|
|
|
client.rdf.clearTargets(this.getGraphResource(),
|
|
client.rdf.resChanUser, true);
|
|
|
|
if (client.currentObject == this)
|
|
/* redisplay the tree */
|
|
client.rdf.setTreeRoot("user-list", this.getGraphResource());
|
|
|
|
if ("noDelete" in this)
|
|
delete this.noDelete;
|
|
else if (client.prefs["deleteOnPart"])
|
|
this.dispatch("delete");
|
|
}
|
|
else
|
|
{
|
|
if (e.reason)
|
|
{
|
|
this.display (getMsg(MSG_SOMEONE_LEFT_REASON,
|
|
[e.user.properNick, e.channel.unicodeName,
|
|
e.reason]),
|
|
"PART", e.user, this);
|
|
}
|
|
else
|
|
{
|
|
this.display (getMsg(MSG_SOMEONE_LEFT,
|
|
[e.user.properNick, e.channel.unicodeName]),
|
|
"PART", e.user, this);
|
|
}
|
|
}
|
|
|
|
e.channel.updateHeader();
|
|
}
|
|
|
|
CIRCChannel.prototype.onKick =
|
|
function my_ckick (e)
|
|
{
|
|
if (userIsMe (e.lamer))
|
|
{
|
|
this.display (getMsg(MSG_YOURE_GONE,
|
|
[e.channel.unicodeName, e.user.properNick,
|
|
e.reason]),
|
|
"KICK", e.user, this);
|
|
}
|
|
else
|
|
{
|
|
var enforcerProper, enforcerNick;
|
|
if (userIsMe (e.user))
|
|
{
|
|
enforcerProper = "YOU";
|
|
enforcerNick = "ME!";
|
|
}
|
|
else
|
|
{
|
|
enforcerProper = e.user.properNick;
|
|
enforcerNick = e.user.nick;
|
|
}
|
|
|
|
this.display (getMsg(MSG_SOMEONE_GONE,
|
|
[e.lamer.properNick, e.channel.unicodeName,
|
|
enforcerProper, e.reason]), "KICK", e.user, this);
|
|
}
|
|
|
|
this._removeUserFromGraph(e.lamer);
|
|
|
|
e.channel.updateHeader();
|
|
}
|
|
|
|
CIRCChannel.prototype.onChanMode =
|
|
function my_cmode (e)
|
|
{
|
|
if ("user" in e)
|
|
{
|
|
var msg = e.decodeParam(1) + " " + e.params.slice(2).join(" ");
|
|
this.display (getMsg(MSG_MODE_CHANGED, [msg, e.user.properNick]),
|
|
"MODE", e.user, this);
|
|
}
|
|
|
|
for (var u in e.usersAffected)
|
|
e.usersAffected[u].updateGraphResource();
|
|
|
|
e.channel.updateHeader();
|
|
updateTitle(e.channel);
|
|
if (client.currentObject == this)
|
|
updateUserList();
|
|
}
|
|
|
|
CIRCChannel.prototype.onNick =
|
|
function my_cnick (e)
|
|
{
|
|
if (userIsMe (e.user))
|
|
{
|
|
if (getTabForObject(this))
|
|
{
|
|
this.displayHere(getMsg(MSG_NEWNICK_YOU, e.user.properNick),
|
|
"NICK", "ME!", e.user, this);
|
|
}
|
|
this.parent.parent.updateHeader();
|
|
}
|
|
else
|
|
{
|
|
this.display(getMsg(MSG_NEWNICK_NOTYOU, [e.oldNick, e.user.properNick]),
|
|
"NICK", e.user, this);
|
|
}
|
|
|
|
e.user.updateGraphResource();
|
|
updateUserList();
|
|
}
|
|
|
|
CIRCChannel.prototype.onQuit =
|
|
function my_cquit (e)
|
|
{
|
|
if (userIsMe(e.user))
|
|
{
|
|
/* I dont think this can happen */
|
|
this.display (getMsg(MSG_YOU_QUIT, [e.server.parent.name, e.reason]),
|
|
"QUIT", e.user, this);
|
|
}
|
|
else
|
|
{
|
|
this.display (getMsg(MSG_SOMEONE_QUIT,
|
|
[e.user.properNick, e.server.parent.name,
|
|
e.reason]),
|
|
"QUIT", e.user, this);
|
|
}
|
|
|
|
this._removeUserFromGraph(e.user);
|
|
|
|
e.channel.updateHeader();
|
|
}
|
|
|
|
CIRCUser.prototype.onInit =
|
|
function user_oninit ()
|
|
{
|
|
this.logFile = null;
|
|
}
|
|
|
|
CIRCUser.prototype.onPrivmsg =
|
|
function my_cprivmsg (e)
|
|
{
|
|
if ("messages" in this)
|
|
{
|
|
playSounds(client.prefs["queryBeep"]);
|
|
}
|
|
else
|
|
{
|
|
playSounds(client.prefs["msgBeep"]);
|
|
var limit = client.prefs["newTabLimit"];
|
|
if (limit == 0 || client.viewsArray.length < limit)
|
|
{
|
|
var tab = openQueryTab (e.server, e.user.nick);
|
|
if (client.FOCUS_NEW_TAB)
|
|
setCurrentObject(tab);
|
|
}
|
|
}
|
|
|
|
this.display(e.decodeParam(2), "PRIVMSG", e.user, e.server.me);
|
|
}
|
|
|
|
CIRCUser.prototype.onNick =
|
|
function my_unick (e)
|
|
{
|
|
if (userIsMe(e.user))
|
|
{
|
|
this.parent.parent.updateHeader();
|
|
updateTitle();
|
|
}
|
|
else if ("messages" in this && this.messages)
|
|
{
|
|
this.display(getMsg(MSG_NEWNICK_NOTYOU, [e.oldNick, e.user.properNick]),
|
|
"NICK", e.user, this);
|
|
}
|
|
|
|
this.updateHeader();
|
|
var tab = getTabForObject(this);
|
|
if (tab)
|
|
tab.setAttribute("label", this.properNick);
|
|
}
|
|
|
|
CIRCUser.prototype.onNotice =
|
|
function my_notice (e)
|
|
{
|
|
this.display (e.decodeParam(2), "NOTICE", this, e.server.me);
|
|
}
|
|
|
|
CIRCUser.prototype.onCTCPAction =
|
|
function my_uaction (e)
|
|
{
|
|
e.user.display(toUnicode(e.CTCPData), "ACTION", this, e.server.me);
|
|
}
|
|
|
|
CIRCUser.prototype.onUnknownCTCP =
|
|
function my_unkctcp (e)
|
|
{
|
|
this.parent.parent.display (getMsg(MSG_UNKNOWN_CTCP,
|
|
[e.CTCPCode, e.CTCPData,
|
|
e.user.properNick]),
|
|
"BAD-CTCP", this, e.server.me);
|
|
}
|
|
|