// -*- C++ -*- /* This file is part of * ====================================================== * * LyX, The Document Processor * * Copyright 2000 The LyX Team. * * ====================================================== * * \file ControlCitation.C * \author Angus Leeming */ #include #ifdef __GNUG__ #pragma implementation #endif #include #include "ControlCitation.h" #include "buffer.h" #include "ButtonController.h" #include "Dialogs.h" #include "LyXView.h" #include "ViewBase.h" #include "support/lstrings.h" #include "support/LRegex.h" using std::find; using std::min; using std::pair; using std::vector; using std::sort; using SigC::slot; ControlCitation::ControlCitation(LyXView & lv, Dialogs & d) : ControlCommand(lv, d, LFUN_CITATION_INSERT) { // These are permanent connections so we won't bother // storing a copy because we won't be disconnecting. d_.showCitation.connect(slot(this, &ControlCitation::showInset)); d_.createCitation.connect(slot(this, &ControlCitation::createInset)); } void ControlCitation::hide() { bibkeysInfo_.clear(); ControlCommand::hide(); } // A functor for use with std::sort, leading to case insensitive sorting struct compareNoCase: public std::binary_function { bool operator()(string const & s1, string const & s2) const { return compare_no_case(s1, s2) < 0; } }; vector const ControlCitation::getBibkeys() { vector bibkeys; bibkeysInfo_.clear(); vector > blist = lv_.buffer()->getBibkeyList(); for (vector >::size_type i=0; isecond, "author"); if (author.empty()) author = parseBibTeX(it->second, "editor"); string year = parseBibTeX(it->second, "year"); string title = parseBibTeX(it->second, "title"); string booktitle = parseBibTeX(it->second, "booktitle"); string chapter = parseBibTeX(it->second, "chapter"); string pages = parseBibTeX(it->second, "pages"); string media = parseBibTeX(it->second, "journal"); if (media.empty()) media = parseBibTeX(it->second, "publisher"); if (media.empty()) media = parseBibTeX(it->second, "school"); if (media.empty()) media = parseBibTeX(it->second, "institution"); result = author; if (!year.empty()) result += ", " + year; if (!title.empty()) result += ", " + title; if (!booktitle.empty()) result += ", in " + booktitle; if (!chapter.empty()) result += ", Ch. " + chapter; if (!media.empty()) result += ", " + media; if (!pages.empty()) result += ", pp. " + pages; if (result.empty()) // not a BibTeX record result = it->second; } return result; } string const getStringFromVector(vector const & vec, char delim) { string str; for (vector::size_type i=0; i 0) str += tostr(delim); str += vec[i]; } return str; } vector const getVectorFromString(string const & str, char delim) { vector vec; string keys(str); string tmp; keys = frontStrip(split(keys, tmp, delim)); while (!tmp.empty()) { vec.push_back(tmp); keys = frontStrip(split(keys, tmp, delim)); } return vec; } vector::const_iterator searchKeys(ControlCitation const & controller, vector const & keys, string const & expr, vector::const_iterator start, ControlCitation::Search type, ControlCitation::Direction dir, bool caseSensitive) { // Preliminary checks if(start < keys.begin() || start >= keys.end()) return keys.end(); string search_expr = frontStrip(strip(expr)); if (search_expr.empty()) return start; if (type == ControlCitation::SIMPLE) return simpleSearch(controller, keys, search_expr, start, dir, caseSensitive); return regexSearch(controller, keys, search_expr, start, dir); } vector::const_iterator simpleSearch(ControlCitation const & controller, vector const & keys, string const & expr, vector::const_iterator start, ControlCitation::Direction dir, bool caseSensitive) { vector searchwords = getVectorFromString(expr, ' '); // Loop over all keys from start... for (vector::const_iterator it = start; // End condition is direction-dependent. (dir == ControlCitation::FORWARD) ? (it=keys.begin()); // increment is direction-dependent. (dir == ControlCitation::FORWARD) ? (++it) : (--it)) { string data = (*it); ControlCitation::InfoMap::const_iterator info = controller.bibkeysInfo().find(*it); if (info != controller.bibkeysInfo().end()) data += " " + info->second; if (!caseSensitive) data = lowercase(data); bool found = true; // Loop over all search words... if (caseSensitive) { for (vector::const_iterator sit= searchwords.begin(); sit::const_iterator sit= searchwords.begin(); sit::const_iterator regexSearch(ControlCitation const & controller, vector const & keys, string const & expr, vector::const_iterator start, ControlCitation::Direction dir) { LRegex reg(expr); for (vector::const_iterator it = start; // End condition is direction-dependent. (dir == ControlCitation::FORWARD) ? (it=keys.begin()); // increment is direction-dependent. (dir == ControlCitation::FORWARD) ? (++it) : (--it)) { string data = (*it); ControlCitation::InfoMap::const_iterator info = controller.bibkeysInfo().find(*it); if (info != controller.bibkeysInfo().end()) data += " " + info->second; if (reg.exec(data).size() > 0) return it; } return keys.end(); } string const parseBibTeX(string data, string const & findkey) { string keyvalue; for (string::iterator it=data.begin(); it1) { string tmp = data.substr(keypos, data.length()-1); while (tmp.find('{') != string::npos && tmp.find('}') != string::npos && tmp.find('{') < tmp.find('}') && tmp.find('{') < tmp.find(enclosing)) { keypos += tmp.find('{')+1; tmp = data.substr(keypos, data.length()-1); keypos += tmp.find('}')+1; tmp = data.substr(keypos, data.length()-1); } if (tmp.find(enclosing)==string::npos) return keyvalue; else { keypos += tmp.find(enclosing); tmp = data.substr(keypos, data.length()-1); } value = data.substr(1, keypos-1); if (keypos+1 data.find(',')) keypos = data.find(','); value = data.substr(0, keypos); if (keypos+1