diff --git a/chrome/content/zotero/xpcom/citeproc.js b/chrome/content/zotero/xpcom/citeproc.js index 901494e75..370d437bb 100644 --- a/chrome/content/zotero/xpcom/citeproc.js +++ b/chrome/content/zotero/xpcom/citeproc.js @@ -1752,7 +1752,7 @@ CSL.DateParser = function (txt) { }; CSL.Engine = function (sys, style, lang, forceLang) { var attrs, langspec, localexml, locale; - this.processor_version = "1.0.124"; + this.processor_version = "1.0.125"; this.csl_version = "1.0"; this.sys = sys; this.sys.xml = new CSL.System.Xml.Parsing(); @@ -4464,14 +4464,6 @@ CSL.Node.names = { } else { frontnames = []; } - if (tnamesets.length > 0 && tnamesets.slice(-1)[0].species === "org") { - tnamesets[0].organization_first = true; - tnamesets.slice(-1)[0].organization_last = true; - if (frontnames.length) { - frontnames[0].free_agent_start = true; - tnamesets.slice(-1)[0].free_agent_end = true; - } - } if (frontnames.length === 0) { if (tnamesets.length > 1) { if (tnamesets[0].species === "pers") { @@ -4519,15 +4511,9 @@ CSL.Node.names = { } } } - namesets = namesets.slice(0, 1); if (namesets.length) { if (namesets[0].species === "pers") { - namesets[0].organization_first = false; namesets[0].after_people = false; - namesets[0].free_agent_start = false; - namesets[0].free_agent_end = false; - } else { - namesets[0].organization_last = true; } } } @@ -4579,32 +4565,65 @@ CSL.Node.names = { } cutinfo = state.tmp.names_cut; if (namesets[0].species === "pers") { - if (state.tmp.cut_var) { - namesets[0].names = namesets[0].names.slice(cutinfo.counts[state.tmp.cut_var]); - } - if (namesets[0].names.length === 0) { - if (namesets[0].free_agent_start) { - namesets[1].free_agent_start = true; - } - if (namesets[0].organization_first) { - namesets[1].organization_first = true; - } - namesets = namesets.slice(1); - } - } else { - namesets = namesets.slice(0, 1); - if (namesets[0].organization_first) { - namesets[0].organization_last = true; - } - } + if (state.tmp.cut_var) { + namesets[0].names = namesets[0].names.slice(cutinfo.counts[state.tmp.cut_var]); + } + if (namesets[0].names.length === 0) { + namesets = namesets.slice(1); + } + } if (state.tmp.cut_var && cutinfo.used === state.tmp.cut_var) { - llen = cutinfo.variable[state.tmp.cut_var].length - 1; - for (ppos = llen; ppos > -1; ppos += -1) { - obj = cutinfo.variable[state.tmp.cut_var][ppos]; - obj[0].blobs = obj[0].blobs.slice(0, obj[1]).concat(obj[0].blobs.slice(obj[1] + 1)); - } + llen = cutinfo.variable[state.tmp.cut_var].length - 1; + for (ppos = llen; ppos > -1; ppos += -1) { + obj = cutinfo.variable[state.tmp.cut_var][ppos]; + obj[0].blobs = obj[0].blobs.slice(0, obj[1]).concat(obj[0].blobs.slice(obj[1] + 1)); + } } } + if (!state.output.getToken("and-org")) { + state.output.addToken("and-org"); + } + var prefix_single_org = " "; + var prefix_multiple_org = ", "; + var and_org = state.getTerm("and", "long", 0); + var offset = 0; + if (namesets.length > 1 && namesets[1].after_people) { + var offset = 1 + } + var numnamesets = 0; + for (i = offset, ilen = namesets.length; i < ilen; i += 1) { + if (namesets[i].species === 'org') { + if (i > 0 && namesets[i - 1].species === 'pers' && !namesets[i].after_people) { + namesets[i - 1].organization_first = true; + } else { + namesets [i].organization_first = true; + } + namesets[i].organization_last = true; + numnamesets += 1; + } + } + var namesetcount = 0; + for (i = offset, ilen = namesets.length; i < ilen; i += 1) { + if (namesets[i].species === 'org' && numnamesets > 1) { + if ((i - offset) > 0 && numnamesets === (namesetcount + 1)) { + if (namesets[i - 1].species === 'pers') { + namesets[i - 2].institutions_and_join = true; + } else { + namesets[i - 1].institutions_and_join = true; + } + } + namesetcount += 1; + } + } + if (numnamesets > 1) { + state.output.getToken("and-org").strings.prefix = prefix_single_org; + if (numnamesets > 2) { + namesets[offset].institutions_penultimate_group_start = true; + namesets[namesets.length - 2].institutions_penultimate_group_end = true; + state.output.getToken("and-org").strings.prefix = prefix_multiple_org; + } + state.output.getToken("and-org").strings.suffix = " "; + } if (!state.output.getToken("institution")) { state.output.addToken("institution"); } @@ -4654,12 +4673,6 @@ CSL.Node.names = { state.output.getToken("and-pers").strings["prefix-single"] = " "; state.output.getToken("and-pers").strings["prefix-multiple"] = ", "; and_pers = state.getTerm("and", "long", 0); - if (!state.output.getToken("and-org")) { - state.output.addToken("and-org"); - } - state.output.getToken("and-org").strings["prefix-single"] = " "; - state.output.getToken("and-org").strings["prefix-multiple"] = ", "; - and_org = state.getTerm("and", "long", 0); state.output.addToken("with"); state.output.getToken("with").strings.prefix = ", "; state.output.getToken("with").strings.suffix = " "; @@ -4862,7 +4875,10 @@ CSL.Node.names = { state.output.openLevel("trailing-names", state.tmp.cut_var); } if (nameset.after_people) { - state.output.append("with", "with"); + state.output.append(with_term, "with"); + } + if (nameset.institutions_penultimate_group_start) { + state.output.openLevel("inner"); } if (nameset.organization_first) { state.output.openLevel("institution-outer"); @@ -4894,6 +4910,9 @@ CSL.Node.names = { state.output.closeLevel("trailing-names"); } state.output.closeLevel("institution-outer"); + if (nameset.institutions_penultimate_group_end) { + state.output.closeLevel("inner"); + } } else { if (nameset.trailers1b_end) { state.output.closeLevel("trailing-names"); @@ -4901,6 +4920,9 @@ CSL.Node.names = { state.output.closeLevel("inner"); state.output.openLevel("inner"); } + if (nameset.institutions_and_join) { + state.output.append(and_org, "and-org"); + } } if (nameset.trailers3_end) { state.output.closeLevel("trailing-names"); diff --git a/chrome/content/zotero/xpcom/integration.js b/chrome/content/zotero/xpcom/integration.js index 17f3e50c5..efe59b34c 100644 --- a/chrome/content/zotero/xpcom/integration.js +++ b/chrome/content/zotero/xpcom/integration.js @@ -35,6 +35,9 @@ const INTEGRATION_MIN_VERSION = "3.1a0"; Zotero.Integration = new function() { var _fifoFile = null; + var _tmpFile = null; + var _shCmd = null; + var _shProc = null; var _osascriptFile; var _inProgress = false; var _integrationVersionsOK = null; @@ -113,8 +116,7 @@ Zotero.Integration = new function() { // try to initialize pipe try { - var pipeInitialized = (Zotero.isFx4 ? _initializeIntegrationPipeFx4(_fifoFile) : - _initializeIntegrationPipeFx36(_fifoFile)); + var pipeInitialized = _initializeIntegration(); } catch(e) { Components.utils.reportError(e); } @@ -181,79 +183,45 @@ Zotero.Integration = new function() { } /** - * Initializes the Zotero Integration Pipe in Firefox 4+ + * Reads from the temp file set up to handle integration pipe and executes the appropriate + * integration command */ - function _initializeIntegrationPipeFx4(_fifoFile) { - // ensure Firefox 4.0b9 or later, since earlier versions do not support ChromeWorkers - // from XPCOM - var verComp = Components.classes["@mozilla.org/xpcom/version-comparator;1"] - .getService(Components.interfaces.nsIVersionComparator); - var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]. - getService(Components.interfaces.nsIXULAppInfo); - if(verComp.compare("2.0b9pre", appInfo.version) > 0) { - Components.utils.reportError("Zotero word processor integration requires "+ - "Firefox 4.0b9 or later. Please update to the latest Firefox 4.0 beta."); - return false; - } else { - Components.utils.import("resource://gre/modules/ctypes.jsm"); - - // get possible names for libc - if(Zotero.isMac) { - var possibleLibcs = ["/usr/lib/libc.dylib"]; - } else { - var possibleLibcs = [ - "libc.so.6", - "libc.so.6.1", - "libc.so" - ]; - } - - // try all possibilities - while(possibleLibcs.length) { - var libc = possibleLibcs.shift(); - try { - var lib = ctypes.open(libc); - break; - } catch(e) {} - } - - // throw appropriate error on failure - if(!lib) { - throw "libc could not be loaded. Please post on the Zotero Forums so we can add "+ - "support for your operating system."; - } - - // int mkfifo(const char *path, mode_t mode); - var mkfifo = lib.declare("mkfifo", ctypes.default_abi, ctypes.int, ctypes.char.ptr, ctypes.unsigned_int); - - // make pipe - var ret = mkfifo(_fifoFile.path, 0600); - if(!_fifoFile.exists()) return false; - lib.close(); - - // set up worker - var worker = Components.classes["@mozilla.org/threads/workerfactory;1"] - .createInstance(Components.interfaces.nsIWorkerFactory) - .newChromeWorker("chrome://zotero/content/xpcom/integration_worker.js"); - worker.onmessage = function(event) { - if(event.data[0] == "Exception") { - throw event.data[1]; - } else if(event.data[0] == "Debug") { - Zotero.debug(event.data[1]); - } else { - Zotero.Integration.execCommand(event.data[0], event.data[1], event.data[2]); + var _integrationPipeObserver = {"observe":function() { + var string = Zotero.File.getContents(_tmpFile); + + if(string != "") { + var parts = string.match(/^([^ \n]*) ([^ \n]*)(?: ([^\n]*))?\n?$/); + if(parts) { + var agent = parts[1].toString(); + var cmd = parts[2].toString(); + var document = parts[3] ? parts[3].toString() : null; + + // remove temp file and halt reading on shutdown + if(agent === "Zotero" && cmd === "shutdown") { + _tmpFile.remove(); + return; } + + Zotero.Integration.execCommand(agent, cmd, document); + } else { + Components.utils.reportError("Integration Worker: Invalid input received: "+string); } - worker.postMessage({"path":_fifoFile.path, "libc":libc}); - - return true; } - } + + _shProc.runAsync(_shCmd, _shCmd.length, _integrationPipeObserver); + }}; /** * Initializes the Zotero Integration Pipe in Firefox 3.6 */ - function _initializeIntegrationPipeFx36(_fifoFile) { + function _initializeIntegration() { + // make a tmp file + _tmpFile = Components.classes["@mozilla.org/file/directory_service;1"]. + getService(Components.interfaces.nsIProperties). + get("TmpD", Components.interfaces.nsIFile); + _tmpFile.append("zoteroIntegrationTmp"); + _tmpFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666); + // make a new pipe var mkfifo = Components.classes["@mozilla.org/file/local;1"]. createInstance(Components.interfaces.nsILocalFile); @@ -261,57 +229,36 @@ Zotero.Integration = new function() { if(!mkfifo.exists()) mkfifo.initWithPath("/bin/mkfifo"); if(!mkfifo.exists()) mkfifo.initWithPath("/usr/local/bin/mkfifo"); - if(mkfifo.exists()) { - var main = Components.classes["@mozilla.org/thread-manager;1"].getService().mainThread; - var background = Components.classes["@mozilla.org/thread-manager;1"].getService().newThread(0); + // get sh + var sh = Components.classes["@mozilla.org/file/local;1"]. + createInstance(Components.interfaces.nsILocalFile); + sh.initWithPath("/bin/sh"); + + if(mkfifo.exists() && sh.exists()) { + // create named pipe + var proc = Components.classes["@mozilla.org/process/util;1"]. + createInstance(Components.interfaces.nsIProcess); + proc.init(mkfifo); + proc.run(true, [_fifoFile.path], 1); - function mainThread(agent, cmd, doc) { - this.agent = agent; - this.cmd = cmd; - this.document = doc; - } - mainThread.prototype.run = function() { - Zotero.Integration.execCommand(this.agent, this.cmd, this.document); - } - - function fifoThread() {} - fifoThread.prototype.run = function() { - var proc = Components.classes["@mozilla.org/process/util;1"]. - createInstance(Components.interfaces.nsIProcess); - proc.init(mkfifo); - proc.run(true, [_fifoFile.path], 1); - - if(!_fifoFile.exists()) Zotero.debug("Could not initialize Zotero integration pipe"); - - var fifoStream = Components.classes["@mozilla.org/network/file-input-stream;1"]. - createInstance(Components.interfaces.nsIFileInputStream); - var line = {}; - while(true) { - fifoStream.QueryInterface(Components.interfaces.nsIFileInputStream); - fifoStream.init(_fifoFile, -1, 0, 0); - fifoStream.QueryInterface(Components.interfaces.nsILineInputStream); - fifoStream.readLine(line); - fifoStream.close(); + if(_fifoFile.exists()) { + // begin reading from named pipe + _shCmd = ["-c", "cat '"+_fifoFile.path.replace("'", "'\\''")+"' > '"+ + _tmpFile.path.replace("'", "'\\''")+"'"]; + Zotero.debug("Calling sh "+_shCmd.join(" ")); - var parts = line.value.split(" "); - var agent = parts[0]; - var cmd = parts[1]; - var document = parts.length >= 3 ? line.value.substr(agent.length+cmd.length+2) : null; - if(agent == "Zotero" && cmd == "shutdown") return; - main.dispatch(new mainThread(agent, cmd, document), background.DISPATCH_NORMAL); - } + _shProc = Components.classes["@mozilla.org/process/util;1"]. + createInstance(Components.interfaces.nsIProcess); + _shProc.init(sh); + _shProc.runAsync(_shCmd, _shCmd.length, _integrationPipeObserver); + + return true; } - fifoThread.prototype.QueryInterface = mainThread.prototype.QueryInterface = function(iid) { - if (iid.equals(Components.interfaces.nsIRunnable) || - iid.equals(Components.interfaces.nsISupports)) return this; - throw Components.results.NS_ERROR_NO_INTERFACE; - } - - background.dispatch(new fifoThread(), background.DISPATCH_NORMAL); - return true; + Components.utils.reportError("Zotero: mkfifo failed -- not initializing integration pipe"); + return false; } else { - Zotero.debug("mkfifo not found -- not initializing integration pipe"); + Components.utils.reportError("Zotero: mkfifo or sh not found -- not initializing integration pipe"); return false; } } diff --git a/chrome/content/zotero/xpcom/integration_worker.js b/chrome/content/zotero/xpcom/integration_worker.js deleted file mode 100644 index ce2da5a71..000000000 --- a/chrome/content/zotero/xpcom/integration_worker.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - ***** BEGIN LICENSE BLOCK ***** - - Copyright © 2009 Center for History and New Media - George Mason University, Fairfax, Virginia, USA - http://zotero.org - - This file is part of Zotero. - - Zotero is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Zotero is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Zotero. If not, see . - - ***** END LICENSE BLOCK ***** -*/ - -onmessage = function(event) { - var path = event.data.path; - - // ctypes declarations follow - var lib = ctypes.open(event.data.libc); - - // int open(const char *path, int oflag, ...); - var open = lib.declare("open", ctypes.default_abi, ctypes.int, ctypes.char.ptr, ctypes.int); - - // ssize_t read(int fildes, void *buf, size_t nbyte); - var read = lib.declare("read", ctypes.default_abi, ctypes.ssize_t, ctypes.int, - ctypes.char.ptr, ctypes.size_t); - - // int close(int fildes); - var close = lib.declare("close", ctypes.default_abi, ctypes.int, ctypes.int); - - // define buffer for reading from fifo - const BUFFER_SIZE = 4096; - - while(true) { - var buf = ctypes.char.array(BUFFER_SIZE)(""); - - // open fifo (this will block until something writes to it) - var fd = open(path, 0); - - // read from fifo and close it - read(fd, buf, BUFFER_SIZE-1); - close(fd); - - // extract message - var string = buf.readString(); - var parts = string.match(/^([^ \n]*) ([^ \n]*)(?: ([^\n]*))?\n?$/); - if(!parts) { - postMessage(["Exception", "Integration Worker: Invalid input received: "+string]); - continue; - } - var agent = parts[1].toString(); - var cmd = parts[2].toString(); - var document = parts[3] ? parts[3] : null; - if(agent == "Zotero" && cmd == "shutdown") { - postMessage(["Debug", "Integration Worker: Shutting down"]); - lib.close(); - return; - } - postMessage([agent, cmd, document]); - } -}; \ No newline at end of file