Index: js/lib/dcc.js =================================================================== RCS file: /cvsroot/mozilla/extensions/irc/js/lib/dcc.js,v retrieving revision 1.19 retrieving revision 1.20 diff -d -p -u -6 -r1.19 -r1.20 --- js/lib/dcc.js 1 Mar 2007 22:16:58 -0000 1.19 +++ js/lib/dcc.js 12 Feb 2008 11:52:32 -0000 1.20 @@ -1293,6 +1293,17 @@ function dfile_dataavailable(e) CIRCDCCFileTransfer.prototype.sendData = function dfile_say(data) { this.connection.sendData(data); } + +CIRCDCCFileTransfer.prototype.size = 0; +CIRCDCCFileTransfer.prototype.position = 0; +CIRCDCCFileTransfer.prototype.__defineGetter__("progress", + function dfile_get_progress() + { + if (this.size > 0) + return Math.floor(100 * this.position / this.size); + return 0; + }); + Index: js/lib/utils.js =================================================================== RCS file: /cvsroot/mozilla/extensions/irc/js/lib/utils.js,v retrieving revision 1.69 retrieving revision 1.70 diff -d -p -u -6 -r1.69 -r1.70 --- js/lib/utils.js 1 Mar 2007 22:16:58 -0000 1.69 +++ js/lib/utils.js 12 Feb 2008 11:38:01 -0000 1.70 @@ -389,13 +389,13 @@ function matchObject (o, pattern, negate function _match (o, pattern) { if (isinstance(pattern, Function)) return pattern(o); - for (p in pattern) + for (var p in pattern) { var val; /* nice to have, but slow as molases, allows you to match * properties of objects with obj$prop: "foo" syntax */ /* if (p[0] == "$") @@ -432,12 +432,28 @@ function matchObject (o, pattern, negate return !negate; return negate; } +function equalsObject(o1, o2) +{ + for (var p in o1) + { + if (!(p in o2) || (o1[p] != o2[p])) + return false; + } + for (p in o2) + { + // If the property did exist in o1, the previous loop tested it: + if (!(p in o1)) + return false; + } + return true; +} + function utils_lcfn(text) { return text.toLowerCase(); } function matchEntry (partialName, list, lcFn) Index: locales/en-US/chrome/chatzilla.properties =================================================================== RCS file: /cvsroot/mozilla/extensions/irc/locales/en-US/chrome/chatzilla.properties,v retrieving revision 1.152 retrieving revision 1.153 diff -d -p -u -6 -r1.152 -r1.153 --- locales/en-US/chrome/chatzilla.properties 20 Jan 2008 11:11:32 -0000 1.152 +++ locales/en-US/chrome/chatzilla.properties 12 Feb 2008 11:25:26 -0000 1.153 @@ -1177,13 +1177,13 @@ msg.ignore.list.2 = Currently ignoring msg.ignore.add = You are now ignoring %S. msg.ignore.adderr = You are already ignoring %S. msg.ignore.del = You are no longer ignoring %S. msg.ignore.delerr = "%S not found in your ignore list. msg.you.invite = You have invited %S to %S. -msg.invite.you = "%S (%S@%S) has invited you to %S. +msg.invite.you = "%S (%S@%S) has invited you to [[%S][Accept invitation to channel %S][goto-url %S]]. msg.nick.in.use = The nickname ``%S'' is already in use, use the /nick command to pick a new one. msg.retry.nick = The nickname ``%S'' is already in use, trying ``%S''. msg.nick.prompt = Enter a nickname to use: msg.list.rerouted = List reply will appear on the ``%S'' view. Index: xul/content/channels.js =================================================================== RCS file: /cvsroot/mozilla/extensions/irc/xul/content/channels.js,v retrieving revision 1.6 retrieving revision 1.7 diff -d -p -u -6 -r1.6 -r1.7 --- xul/content/channels.js 3 Nov 2007 23:47:58 -0000 1.6 +++ xul/content/channels.js 12 Feb 2008 11:38:01 -0000 1.7 @@ -75,13 +75,13 @@ delete s; // Store all the operation data here. var data = { list: { state: STATE_IDLE }, load: { state: STATE_IDLE }, - filter: { state: STATE_IDLE }, + filter: { state: STATE_IDLE } }; // This should keep things responsive enough, for the user to click buttons and // edit the filter text and options, without giving up too much time to letting // Gecko catch up. @@ -182,13 +182,21 @@ function onUnload() { delete network.joinDialog; } function onKeyPress(event) { - if (event.keyCode == event.DOM_VK_UP) + if (event.keyCode == event.DOM_VK_RETURN) + { + startOperation(OP_FILTER); + if (joinChannel()) + window.close(); + event.stopPropagation(); + event.preventDefault(); + } + else if (event.keyCode == event.DOM_VK_UP) { if (channelTreeView.selectedIndex > 0) { channelTreeView.selectedIndex = channelTreeView.selectedIndex - 1; ensureRowIsVisible(); } @@ -383,14 +391,15 @@ function processOperation(op) if (opData.state == STATE_START) fn += "Start"; else if (opData.state == STATE_RUN) fn += "Run"; else if (opData.state == STATE_STOP) fn += "Stop"; - else - return ASSERT(false, dbg + " invalid state: " + opData.state); + // assert and return if we're in a different state: + else if (!ASSERT(false, dbg + " invalid state: " + opData.state)) + return; try { var newState = window[fn](opData); if (typeof newState != "undefined") opData.state = newState; @@ -578,21 +587,37 @@ function processOpLoadStop(opData) return STATE_IDLE; } function processOpFilterStart(opData) { - opData.text = channelFilterText.value.toLowerCase(); - opData.searchTopics = channelSearchTopics.checked; - opData.minUsers = channelMinUsers.value * 1; - opData.maxUsers = channelMaxUsers.value * 1; + // Catch filtering with the same options on the same channels: + var newOptions = {text: channelFilterText.value.toLowerCase(), + min: channelMinUsers.value * 1, + max: channelMaxUsers.value * 1, + listLen: channels.length, + searchTopics: channelSearchTopics.checked}; + + if (("filterOptions" in window) && + equalsObject(window.filterOptions, newOptions)) + { + return STATE_IDLE; + } + + window.filterOptions = newOptions; + + opData.text = newOptions.text; + opData.searchTopics = newOptions.searchTopics; + opData.minUsers = newOptions.min; + opData.maxUsers = newOptions.max; opData.exactMatch = null; opData.currentIndex = 0; opData.channelText = opData.text; - if ((arrayIndexOf(["#", "&", "+", "!"], opData.channelText[0]) == -1) && + if (opData.channelText && + (arrayIndexOf(["#", "&", "+", "!"], opData.channelText[0]) == -1) && (arrayIndexOf(serverChannelPrefixes, opData.channelText[0]) == -1)) { opData.channelText = serverChannelPrefixes[0] + opData.channelText; } // Update special "create channel" row, and select it. Index: xul/content/commands.js =================================================================== RCS file: /cvsroot/mozilla/extensions/irc/xul/content/commands.js,v retrieving revision 1.144 retrieving revision 1.147 diff -d -p -u -6 -r1.144 -r1.147 --- xul/content/commands.js 20 Jan 2008 16:34:11 -0000 1.144 +++ xul/content/commands.js 12 Feb 2008 11:52:32 -0000 1.147 @@ -252,13 +252,17 @@ function initCommands() ["ltr", "text-direction ltr", CMD_CONSOLE], ["toggle-text-dir", "text-direction toggle", 0], ["irtl", "input-text-direction rtl", CMD_CONSOLE], ["iltr", "input-text-direction ltr", CMD_CONSOLE], // Instrumentation aliases ["allow-inst1", "pref instrumentation.inst1 1", 0], - ["deny-inst1", "pref instrumentation.inst1 2", 0] + ["deny-inst1", "pref instrumentation.inst1 2", 0], + // Services aliases + ["cs", "quote cs", 0], + ["ms", "quote ms", 0], + ["ns", "quote ns", 0] ]; // set the stringbundle associated with these commands. cmdary.stringBundle = client.defaultBundle; client.commandManager = new CommandManager(client.defaultBundle); @@ -2270,14 +2274,17 @@ function cmdGotoURL(e) return; } if (e.url.search(/^x-cz-command:/i) == 0) { var ary = e.url.match(/^x-cz-command:(.*)$/i); - getContentWindow(e.sourceObject.frame).location.href = - "javascript:void(view.dispatch('" + decodeURI(ary[1]) + "', null, true))"; + // Do the escaping dance: + var commandStr = decodeURI(ary[1]).quote(); + var jsStr = "void(view.dispatch(" + commandStr + ", null, true))"; + var jsURI = "javascript:" + encodeURI(jsStr); + getContentWindow(e.sourceObject.frame).location.href = jsURI; return; } try { var uri = client.iosvc.newURI(e.url, "UTF-8", null); @@ -2389,79 +2396,85 @@ function cmdCTCP(e) function cmdJoin(e) { /* This check makes sure we only check if the *user* entered anything, and * ignore any contextual information, like the channel the command was * run on. */ - if (!e.hasOwnProperty("channelName") || !e.channelName) + if ((!e.hasOwnProperty("channelName") || !e.channelName) && + !e.channelToJoin) { if (e.network.joinDialog) return e.network.joinDialog.focus(); window.openDialog("chrome://chatzilla/content/channels.xul", "", "resizable=yes", { client: client, network: e.network, opener: window }); return null; } - if (!("charset" in e)) - { - e.charset = null; - } - else if (e.charset && !checkCharset(e.charset)) - { - display (getMsg(MSG_ERR_INVALID_CHARSET, e.charset), MT_ERROR); - return null; - } - - if (e.channelName.search(",") != -1) + var chan; + if (!e.channelToJoin) { - // We can join multiple channels! Woo! - var chan; - var chans = e.channelName.split(","); - var keys = []; - if (e.key) - keys = e.key.split(","); - for (var c in chans) + if (!("charset" in e)) { - chan = dispatch("join", { charset: e.charset, - channelName: chans[c], - key: keys.shift() }); + e.charset = null; } - return chan; + else if (e.charset && !checkCharset(e.charset)) + { + display (getMsg(MSG_ERR_INVALID_CHARSET, e.charset), MT_ERROR); + return null; + } + + if (e.channelName.search(",") != -1) + { + // We can join multiple channels! Woo! + var chans = e.channelName.split(","); + var keys = []; + if (e.key) + keys = e.key.split(","); + for (var c in chans) + { + chan = dispatch("join", { charset: e.charset, + channelName: chans[c], + key: keys.shift() }); + } + return chan; + } + + if ((arrayIndexOf(["#", "&", "+", "!"], e.channelName[0]) == -1) && + (arrayIndexOf(e.server.channelTypes, e.channelName[0]) == -1)) + { + e.channelName = e.server.channelTypes[0] + e.channelName; + } + + var charset = e.charset ? e.charset : e.network.prefs["charset"]; + chan = e.server.addChannel(e.channelName, charset); + if (e.charset) + chan.prefs["charset"] = e.charset; } - - if ((arrayIndexOf(["#", "&", "+", "!"], e.channelName[0]) == -1) && - (arrayIndexOf(e.server.channelTypes, e.channelName[0]) == -1)) + else { - e.channelName = e.server.channelTypes[0] + e.channelName; + chan = e.channelToJoin; } - var charset = e.charset ? e.charset : e.network.prefs["charset"]; - e.channel = e.server.addChannel(e.channelName, charset); - if (e.charset) - e.channel.prefs["charset"] = e.charset; - - e.channel.join(e.key); + chan.join(e.key); /* !-channels are "safe" channels, and get a server-generated prefix. For * this reason, we shouldn't do anything client-side until the server * replies (since the reply will have the appropriate prefix). */ - if (e.channelName[0] != "!") + if (chan.unicodeName[0] != "!") { - if (!("messages" in e.channel)) - { - e.channel.displayHere(getMsg(MSG_CHANNEL_OPENED, - e.channel.unicodeName), MT_INFO); - } + var chanName = chan.unicodeName; + if (!("messages" in chan)) + chan.displayHere(getMsg(MSG_CHANNEL_OPENED, chanName), MT_INFO); - dispatch("set-current-view", { view: e.channel }); + dispatch("set-current-view", { view: chan }); } - return e.channel; + return chan; } function cmdLeave(e) { if (!e.server) { @@ -4148,13 +4161,13 @@ function cmdDCCList(e) { case DCC_STATE_CONNECTED: state = MSG_DCC_STATE_CONNECT; cmds = getMsg(MSG_DCC_COMMAND_CLOSE, "dcc-close " + c.id); if (c.TYPE == "IRCDCCFileTransfer") { state = getMsg(MSG_DCC_STATE_CONNECTPRO, - [Math.floor(100 * c.position / c.size), + [c.progress, getSISize(c.position), getSISize(c.size), getSISpeed(c.speed)]); } counts.connected++; break; case DCC_STATE_DONE: Index: xul/content/handlers.js =================================================================== RCS file: /cvsroot/mozilla/extensions/irc/xul/content/handlers.js,v retrieving revision 1.169 retrieving revision 1.171 diff -d -p -u -6 -r1.169 -r1.171 --- xul/content/handlers.js 1 Feb 2008 21:33:25 -0000 1.169 +++ xul/content/handlers.js 12 Feb 2008 11:52:32 -0000 1.171 @@ -1771,15 +1771,20 @@ function my_341 (e) "341"); } CIRCNetwork.prototype.onInvite = /* invite message */ function my_invite (e) { + client.munger.getRule(".inline-buttons").enabled = true; this.display(getMsg(MSG_INVITE_YOU, [e.user.unicodeName, e.user.name, - e.user.host, e.channel.unicodeName]), + e.user.host, + e.channel.unicodeName, + e.channel.unicodeName, + e.channel.getURL()]), "INVITE"); + client.munger.getRule(".inline-buttons").enabled = false; if ("messages" in e.channel) e.channel.join(); } CIRCNetwork.prototype.on433 = /* nickname in use */ @@ -3019,13 +3024,12 @@ function my_dccdisconnect(e) CIRCDCCFileTransfer.prototype.onInit = function my_dccfileinit(e) { this.busy = false; - this.progress = -1; updateProgress(); } CIRCDCCFileTransfer.prototype._getParams = function my_dccfilegetparams() { @@ -3043,33 +3047,31 @@ function my_dccfilegetparams() CIRCDCCFileTransfer.prototype.onConnect = function my_dccfileconnect(e) { this.displayHere(getMsg(MSG_DCCFILE_OPENED, this._getParams()), "DCC-FILE"); this.busy = true; - this.progress = 0; this.speed = 0; updateProgress(); this._lastUpdate = new Date(); this._lastPosition = 0; this._lastSpeedTime = new Date(); } CIRCDCCFileTransfer.prototype.onProgress = function my_dccfileprogress(e) { var now = new Date(); - var pcent = Math.floor(100 * this.position / this.size); + var pcent = this.progress; var tab = getTabForObject(this); // If we've moved 100KiB or waited 10s, update the progress bar. if ((this.position > this._lastPosition + 102400) || (now - this._lastUpdate > 10000)) { - this.progress = pcent; updateProgress(); updateTitle(); if (tab) tab.setAttribute("label", this.viewName + " (" + pcent + "%)"); @@ -3101,29 +3103,32 @@ function my_dccfileprogress(e) CIRCDCCFileTransfer.prototype.onAbort = function my_dccfileabort(e) { this.busy = false; updateProgress(); + updateTitle(); this.display(getMsg(MSG_DCCFILE_ABORTED, this._getParams()), "DCC-FILE"); } CIRCDCCFileTransfer.prototype.onFail = function my_dccfilefail(e) { this.busy = false; updateProgress(); + updateTitle(); this.display(getMsg(MSG_DCCFILE_FAILED, this._getParams()), "DCC-FILE"); } CIRCDCCFileTransfer.prototype.onDisconnect = function my_dccfiledisconnect(e) { this.busy = false; updateProgress(); this.updateHeader(); + updateTitle(); var msg, tab = getTabForObject(this); if (tab) tab.setAttribute("label", this.viewName + " (DONE)"); if (this.state.dir == DCC_DIR_GETTING) Index: xul/content/mungers.js =================================================================== RCS file: /cvsroot/mozilla/extensions/irc/xul/content/mungers.js,v retrieving revision 1.12 retrieving revision 1.13 diff -d -p -u -6 -r1.12 -r1.13 --- xul/content/mungers.js 6 Jan 2008 12:00:54 -0000 1.12 +++ xul/content/mungers.js 12 Feb 2008 11:43:24 -0000 1.13 @@ -289,14 +289,13 @@ function insertChannelLink(matchText, co } var linkText = removeColorCodes(matchText); var encodedLinkText = fromUnicode(linkText, eventData.sourceObject); var anchor = document.createElementNS("http://www.w3.org/1999/xhtml", "html:a"); - anchor.setAttribute("href", eventData.network.getURL() + - ecmaEscape(encodedLinkText)); + anchor.setAttribute("href", eventData.network.getURL(encodedLinkText)); // Carry over formatting. var otherFormatting = calcClass(eventData); if (otherFormatting) anchor.setAttribute("class", "chatzilla-link " + otherFormatting); else Index: xul/content/output-window.js =================================================================== RCS file: /cvsroot/mozilla/extensions/irc/xul/content/output-window.js,v retrieving revision 1.19 retrieving revision 1.20 diff -d -p -u -6 -r1.19 -r1.20 --- xul/content/output-window.js 1 Nov 2007 20:00:32 -0000 1.19 +++ xul/content/output-window.js 12 Feb 2008 11:52:32 -0000 1.20 @@ -510,13 +510,13 @@ function updateDCCChat() setText("title", getMsg(MSG_TITLE_DCCCHAT, view.user.unicodeName)); } function updateDCCFile() { - var pcent = Math.floor(100 * view.position / view.size); + var pcent = view.progress; setText("file", view.filename); setText("progress", getMsg(MSG_DCCFILE_PROGRESS, [pcent, mainWindow.getSISize(view.position), mainWindow.getSISize(view.size), mainWindow.getSISpeed(view.speed)])); Index: xul/content/static.js =================================================================== RCS file: /cvsroot/mozilla/extensions/irc/xul/content/static.js,v retrieving revision 1.264 retrieving revision 1.265 diff -d -p -u -6 -r1.264 -r1.265 --- xul/content/static.js 20 Jan 2008 16:34:11 -0000 1.264 +++ xul/content/static.js 12 Feb 2008 11:25:27 -0000 1.265 @@ -1829,14 +1829,13 @@ function gotoIRCURL(url, e) target = "#" + target; } var chan = new CIRCChannel(serv, null, target); client.pendingViewContext = e; - d = { channelName: chan.unicodeName, key: key, - charset: url.charset }; + d = {channelToJoin: chan, key: key}; targetObject = network.dispatch("join", d); delete client.pendingViewContext; } if (!targetObject) return;