From: Bo Peng Date: Wed, 25 Apr 2007 17:20:29 +0000 (+0000) Subject: merge src/frontends/controllers/biblio, character, frnt_lang, helper_funcs and tex_he... X-Git-Tag: 1.6.10~10081 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=5d80bf1a220cfef30a229df3aa20ea50c89d10fd;p=features.git merge src/frontends/controllers/biblio, character, frnt_lang, helper_funcs and tex_helpers to frontend_helpers, step 2 git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@17997 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/src/frontends/controllers/biblio.C b/src/frontends/controllers/biblio.C deleted file mode 100644 index ee917f6a94..0000000000 --- a/src/frontends/controllers/biblio.C +++ /dev/null @@ -1,837 +0,0 @@ -/** - * \file frontend_helpers.cpp - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Angus Leeming - * \author Herbert Voß - * - * Full author contact details are available in file CREDITS. - */ - -#include - -#include "biblio.h" - -#include "buffer.h" -#include "bufferparams.h" -#include "gettext.h" - -#include "support/lstrings.h" - -#include - -#include - -using std::string; -using std::vector; - - -namespace lyx { - -using support::ascii_lowercase; -using support::bformat; -using support::compare_ascii_no_case; -using support::contains; -using support::getVectorFromString; -using support::ltrim; -using support::prefixIs; -using support::rtrim; -using support::split; -using support::subst; -using support::token; -using support::trim; - -namespace biblio { - -namespace { - -vector const init_possible_cite_commands() -{ - char const * const pos[] = { - "cite", - "citet", "citep", "citealt", "citealp", - "citeauthor", "citeyear", "citeyearpar", - "citet*", "citep*", "citealt*", "citealp*", "citeauthor*", - "Citet", "Citep", "Citealt", "Citealp", "Citeauthor", - "Citet*", "Citep*", "Citealt*", "Citealp*", "Citeauthor*", - "fullcite", - "footcite", "footcitet", "footcitep", "footcitealt", - "footcitealp", "footciteauthor", "footciteyear", - "footciteyearpar", - "citefield", - "citetitle", - "cite*" - }; - size_t const size_pos = sizeof(pos) / sizeof(pos[0]); - - return vector(pos, pos + size_pos); -} - - -vector const & possible_cite_commands() -{ - static vector const pos = init_possible_cite_commands(); - return pos; -} - - -bool is_possible_cite_command(string const & input) -{ - vector const & possibles = possible_cite_commands(); - vector::const_iterator const end = possibles.end(); - return std::find(possibles.begin(), end, input) != end; -} - - -string const default_cite_command(CiteEngine engine) -{ - string str; - switch (engine) { - case ENGINE_BASIC: - str = "cite"; - break; - case ENGINE_NATBIB_AUTHORYEAR: - str = "citet"; - break; - case ENGINE_NATBIB_NUMERICAL: - str = "citep"; - break; - case ENGINE_JURABIB: - str = "cite"; - break; - } - return str; -} - - -static const docstring TheBibliographyRef(from_ascii("TheBibliographyRef")); - -} // namespace anon - - -string const asValidLatexCommand(string const & input, - CiteEngine const engine) -{ - string const default_str = default_cite_command(engine); - if (!is_possible_cite_command(input)) - return default_str; - - string output; - switch (engine) { - case ENGINE_BASIC: - output = default_str; - break; - - case ENGINE_NATBIB_AUTHORYEAR: - case ENGINE_NATBIB_NUMERICAL: - if (input == "cite" || input == "citefield" || - input == "citetitle" || input == "cite*") - output = default_str; - else if (prefixIs(input, "foot")) - output = input.substr(4); - else - output = input; - break; - - case ENGINE_JURABIB: { - // Jurabib does not support the 'uppercase' natbib style. - if (input[0] == 'C') - output = string(1, 'c') + input.substr(1); - else - output = input; - - // Jurabib does not support the 'full' natbib style. - string::size_type const n = output.size() - 1; - if (output != "cite*" && output[n] == '*') - output = output.substr(0, n); - - break; - } - } - - return output; -} - - -docstring const familyName(docstring const & name) -{ - // Very simple parser - docstring fname = name; - - // possible authorname combinations are: - // "Surname, FirstName" - // "Surname, F." - // "FirstName Surname" - // "F. Surname" - docstring::size_type idx = fname.find(','); - if (idx != docstring::npos) - return ltrim(fname.substr(0, idx)); - idx = fname.rfind('.'); - if (idx != docstring::npos) - fname = ltrim(fname.substr(idx + 1)); - // test if we have a LaTeX Space in front - if (fname[0] == '\\') - return fname.substr(2); - - return rtrim(fname); -} - - -docstring const getAbbreviatedAuthor(InfoMap const & map, string const & key) -{ - BOOST_ASSERT(!map.empty()); - - InfoMap::const_iterator it = map.find(key); - if (it == map.end()) - return docstring(); - docstring const & data = it->second; - - // Is the entry a BibTeX one or one from lyx-layout "bibliography"? - docstring::size_type const pos = data.find(TheBibliographyRef); - if (pos != docstring::npos) { - if (pos <= 2) { - return docstring(); - } - - docstring const opt = trim(data.substr(0, pos - 1)); - if (opt.empty()) - return docstring(); - - docstring authors; - split(opt, authors, '('); - return authors; - } - - docstring author = parseBibTeX(data, "author"); - - if (author.empty()) - author = parseBibTeX(data, "editor"); - - if (author.empty()) { - author = parseBibTeX(data, "key"); - if (author.empty()) - // FIXME UNICODE - return from_utf8(key); - return author; - } - - vector const authors = getVectorFromString(author, from_ascii(" and ")); - if (authors.empty()) - return author; - - if (authors.size() == 2) - return bformat(_("%1$s and %2$s"), - familyName(authors[0]), familyName(authors[1])); - - if (authors.size() > 2) - return bformat(_("%1$s et al."), familyName(authors[0])); - - return familyName(authors[0]); -} - - -docstring const getYear(InfoMap const & map, string const & key) -{ - BOOST_ASSERT(!map.empty()); - - InfoMap::const_iterator it = map.find(key); - if (it == map.end()) - return docstring(); - docstring const & data = it->second; - - // Is the entry a BibTeX one or one from lyx-layout "bibliography"? - docstring::size_type const pos = data.find(TheBibliographyRef); - if (pos != docstring::npos) { - if (pos <= 2) { - return docstring(); - } - - docstring const opt = - trim(data.substr(0, pos - 1)); - if (opt.empty()) - return docstring(); - - docstring authors; - docstring const tmp = split(opt, authors, '('); - docstring year; - split(tmp, year, ')'); - return year; - - } - - docstring year = parseBibTeX(data, "year"); - if (year.empty()) - year = _("No year"); - - return year; -} - - -namespace { - -// A functor for use with std::sort, leading to case insensitive sorting -class compareNoCase: public std::binary_function -{ -public: - bool operator()(string const & s1, string const & s2) const { - return compare_ascii_no_case(s1, s2) < 0; - } -}; - -} // namespace anon - - -vector const getKeys(InfoMap const & map) -{ - vector bibkeys; - InfoMap::const_iterator it = map.begin(); - InfoMap::const_iterator end = map.end(); - for (; it != end; ++it) { - bibkeys.push_back(it->first); - } - - std::sort(bibkeys.begin(), bibkeys.end(), compareNoCase()); - return bibkeys; -} - - -docstring const getInfo(InfoMap const & map, string const & key) -{ - BOOST_ASSERT(!map.empty()); - - InfoMap::const_iterator it = map.find(key); - if (it == map.end()) - return docstring(); - docstring const & data = it->second; - - // is the entry a BibTeX one or one from lyx-layout "bibliography"? - docstring::size_type const pos = data.find(TheBibliographyRef); - if (pos != docstring::npos) { - docstring::size_type const pos2 = pos + TheBibliographyRef.size(); - docstring const info = trim(data.substr(pos2)); - return info; - } - - // Search for all possible "required" keys - docstring author = parseBibTeX(data, "author"); - if (author.empty()) - author = parseBibTeX(data, "editor"); - - docstring year = parseBibTeX(data, "year"); - docstring title = parseBibTeX(data, "title"); - docstring booktitle = parseBibTeX(data, "booktitle"); - docstring chapter = parseBibTeX(data, "chapter"); - docstring number = parseBibTeX(data, "number"); - docstring volume = parseBibTeX(data, "volume"); - docstring pages = parseBibTeX(data, "pages"); - docstring annote = parseBibTeX(data, "annote"); - docstring media = parseBibTeX(data, "journal"); - if (media.empty()) - media = parseBibTeX(data, "publisher"); - if (media.empty()) - media = parseBibTeX(data, "school"); - if (media.empty()) - media = parseBibTeX(data, "institution"); - - odocstringstream result; - if (!author.empty()) - result << author << ", "; - if (!title.empty()) - result << title; - if (!booktitle.empty()) - result << ", in " << booktitle; - if (!chapter.empty()) - result << ", Ch. " << chapter; - if (!media.empty()) - result << ", " << media; - if (!volume.empty()) - result << ", vol. " << volume; - if (!number.empty()) - result << ", no. " << number; - if (!pages.empty()) - result << ", pp. " << pages; - if (!year.empty()) - result << ", " << year; - if (!annote.empty()) - result << "\n\n" << annote; - - docstring const result_str = rtrim(result.str()); - if (!result_str.empty()) - return result_str; - - // This should never happen (or at least be very unusual!) - return data; -} - - -namespace { - -// Escape special chars. -// All characters are literals except: '.|*?+(){}[]^$\' -// These characters are literals when preceded by a "\", which is done here -// @todo: This function should be moved to support, and then the test in tests -// should be moved there as well. -string const escape_special_chars(string const & expr) -{ - // Search for all chars '.|*?+(){}[^$]\' - // Note that '[' and '\' must be escaped. - // This is a limitation of boost::regex, but all other chars in BREs - // are assumed literal. - boost::regex reg("[].|*?+(){}^$\\[\\\\]"); - - // $& is a perl-like expression that expands to all - // of the current match - // The '$' must be prefixed with the escape character '\' for - // boost to treat it as a literal. - // Thus, to prefix a matched expression with '\', we use: - return boost::regex_replace(expr, reg, "\\\\$&"); -} - - -// A functor for use with std::find_if, used to ascertain whether a -// data entry matches the required regex_ -// @throws: boost::regex_error if the supplied regex pattern is not valid -// @todo: This function should be moved to support. -class RegexMatch : public std::unary_function -{ -public: - // re and icase are used to construct an instance of boost::RegEx. - // if icase is true, then matching is insensitive to case - RegexMatch(InfoMap const & m, string const & re, bool icase) - : map_(m), regex_(re, icase) {} - - bool operator()(string const & key) const { - // the data searched is the key + its associated BibTeX/biblio - // fields - string data = key; - InfoMap::const_iterator info = map_.find(key); - if (info != map_.end()) - // FIXME UNICODE - data += ' ' + to_utf8(info->second); - - // Attempts to find a match for the current RE - // somewhere in data. - return boost::regex_search(data, regex_); - } -private: - InfoMap const map_; - mutable boost::regex regex_; -}; - -} // namespace anon - - -vector::const_iterator -searchKeys(InfoMap const & theMap, - vector const & keys, - string const & search_expr, - vector::const_iterator start, - Search type, - Direction dir, - bool caseSensitive) -{ - // Preliminary checks - if (start < keys.begin() || start >= keys.end()) - return keys.end(); - - string expr = trim(search_expr); - if (expr.empty()) - return keys.end(); - - if (type == SIMPLE) - // We must escape special chars in the search_expr so that - // it is treated as a simple string by boost::regex. - expr = escape_special_chars(expr); - - try { - // Build the functor that will be passed to find_if. - RegexMatch const match(theMap, expr, !caseSensitive); - - // Search the vector of 'keys' from 'start' for one - // that matches the predicate 'match'. Searching can - // be forward or backward from start. - if (dir == FORWARD) - return std::find_if(start, keys.end(), match); - - vector::const_reverse_iterator rit(start); - vector::const_reverse_iterator rend = keys.rend(); - rit = std::find_if(rit, rend, match); - - if (rit == rend) - return keys.end(); - // This is correct and always safe. - // (See Meyer's Effective STL, Item 28.) - return (++rit).base(); - } - catch (boost::regex_error &) { - return keys.end(); - } -} - - -docstring const parseBibTeX(docstring data, string const & findkey) -{ - // at first we delete all characters right of '%' and - // replace tabs through a space and remove leading spaces - // we read the data line by line so that the \n are - // ignored, too. - docstring data_; - int Entries = 0; - docstring dummy = token(data,'\n', Entries); - while (!dummy.empty()) { - // no tabs - dummy = subst(dummy, '\t', ' '); - // no leading spaces - dummy = ltrim(dummy); - // ignore lines with a beginning '%' or ignore all right of % - docstring::size_type const idx = - dummy.empty() ? docstring::npos : dummy.find('%'); - if (idx != docstring::npos) - // Check if this is really a comment or just "\%" - if (idx == 0 || dummy[idx - 1] != '\\') - dummy.erase(idx, docstring::npos); - else - // This is "\%", so just erase the '\' - dummy.erase(idx - 1, 1); - // do we have a new token or a new line of - // the same one? In the first case we ignore - // the \n and in the second we replace it - // with a space - if (!dummy.empty()) { - if (!contains(dummy, '=')) - data_ += ' ' + dummy; - else - data_ += dummy; - } - dummy = token(data, '\n', ++Entries); - } - - // replace double commas with "" for easy scanning - data = subst(data_, from_ascii(",,"), from_ascii("\"\"")); - - // unlikely! - if (data.empty()) - return docstring(); - - // now get only the important line of the bibtex entry. - // all entries are devided by ',' except the last one. - data += ','; - // now we have same behaviour for all entries because the last one - // is "blah ... }" - Entries = 0; - bool found = false; - // parsing of title and booktitle is different from the - // others, because booktitle contains title - do { - dummy = token(data, ',', Entries++); - if (!dummy.empty()) { - found = contains(ascii_lowercase(dummy), from_ascii(findkey)); - if (findkey == "title" && - contains(ascii_lowercase(dummy), from_ascii("booktitle"))) - found = false; - } - } while (!found && !dummy.empty()); - if (dummy.empty()) - // no such keyword - return docstring(); - - // we are not sure, if we get all, because "key= "blah, blah" is - // allowed. - // Therefore we read all until the next "=" character, which follows a - // new keyword - docstring keyvalue = dummy; - dummy = token(data, ',', Entries++); - while (!contains(dummy, '=') && !dummy.empty()) { - keyvalue += ',' + dummy; - dummy = token(data, ',', Entries++); - } - - // replace double "" with originals ,, (two commas) - // leaving us with the all-important line - data = subst(keyvalue, from_ascii("\"\""), from_ascii(",,")); - - // Clean-up. - // 1. Spaces - data = rtrim(data); - // 2. if there is no opening '{' then a closing '{' is probably cruft. - if (!contains(data, '{')) - data = rtrim(data, "}"); - // happens, when last keyword - docstring::size_type const idx = - !data.empty() ? data.find('=') : docstring::npos; - - if (idx == docstring::npos) - return docstring(); - - data = trim(data.substr(idx)); - - // a valid entry? - if (data.length() < 2 || data[0] != '=') - return docstring(); - else { - // delete '=' and the following spaces - data = ltrim(data, " ="); - if (data.length() < 2) { - // not long enough to find delimiters - return data; - } else { - docstring::size_type keypos = 1; - char_type enclosing; - if (data[0] == '{') { - enclosing = '}'; - } else if (data[0] == '"') { - enclosing = '"'; - } else { - // no {} and no "", pure data but with a - // possible ',' at the end - return rtrim(data, ","); - } - docstring tmp = data.substr(keypos); - while (tmp.find('{') != docstring::npos && - tmp.find('}') != docstring::npos && - tmp.find('{') < tmp.find('}') && - tmp.find('{') < tmp.find(enclosing)) { - - keypos += tmp.find('{') + 1; - tmp = data.substr(keypos); - keypos += tmp.find('}') + 1; - tmp = data.substr(keypos); - } - if (tmp.find(enclosing) == docstring::npos) - return data; - else { - keypos += tmp.find(enclosing); - return data.substr(1, keypos - 1); - } - } - } -} - - -namespace { - - -char const * const citeCommands[] = { - "cite", "citet", "citep", "citealt", "citealp", "citeauthor", - "citeyear", "citeyearpar" }; - -unsigned int const nCiteCommands = - sizeof(citeCommands) / sizeof(char *); - -CiteStyle const citeStyles[] = { - CITE, CITET, CITEP, CITEALT, CITEALP, - CITEAUTHOR, CITEYEAR, CITEYEARPAR }; - -unsigned int const nCiteStyles = - sizeof(citeStyles) / sizeof(CiteStyle); - -CiteStyle const citeStylesFull[] = { - CITET, CITEP, CITEALT, CITEALP, CITEAUTHOR }; - -unsigned int const nCiteStylesFull = - sizeof(citeStylesFull) / sizeof(CiteStyle); - -CiteStyle const citeStylesUCase[] = { - CITET, CITEP, CITEALT, CITEALP, CITEAUTHOR }; - -unsigned int const nCiteStylesUCase = - sizeof(citeStylesUCase) / sizeof(CiteStyle); - -} // namespace anon - - -CitationStyle::CitationStyle(string const & command) - : style(CITE), full(false), forceUCase(false) -{ - if (command.empty()) - return; - - string cmd = command; - if (cmd[0] == 'C') { - forceUCase = true; - cmd[0] = 'c'; - } - - string::size_type const n = cmd.size() - 1; - if (cmd != "cite" && cmd[n] == '*') { - full = true; - cmd = cmd.substr(0,n); - } - - char const * const * const last = citeCommands + nCiteCommands; - char const * const * const ptr = std::find(citeCommands, last, cmd); - - if (ptr != last) { - size_t idx = ptr - citeCommands; - style = citeStyles[idx]; - } -} - - -string const CitationStyle::asLatexStr() const -{ - string cite = citeCommands[style]; - if (full) { - CiteStyle const * last = citeStylesFull + nCiteStylesFull; - if (std::find(citeStylesFull, last, style) != last) - cite += '*'; - } - - if (forceUCase) { - CiteStyle const * last = citeStylesUCase + nCiteStylesUCase; - if (std::find(citeStylesUCase, last, style) != last) - cite[0] = 'C'; - } - - return cite; -} - - -vector const getCiteStyles(CiteEngine const engine) -{ - unsigned int nStyles = 0; - unsigned int start = 0; - - switch (engine) { - case ENGINE_BASIC: - nStyles = 1; - start = 0; - break; - case ENGINE_NATBIB_AUTHORYEAR: - case ENGINE_NATBIB_NUMERICAL: - nStyles = nCiteStyles - 1; - start = 1; - break; - case ENGINE_JURABIB: - nStyles = nCiteStyles; - start = 0; - break; - } - - typedef vector cite_vec; - - cite_vec styles(nStyles); - cite_vec::size_type i = 0; - int j = start; - for (; i != styles.size(); ++i, ++j) - styles[i] = citeStyles[j]; - - return styles; -} - - -vector const -getNumericalStrings(string const & key, - InfoMap const & map, vector const & styles) -{ - if (map.empty()) - return vector(); - - docstring const author = getAbbreviatedAuthor(map, key); - docstring const year = getYear(map, key); - if (author.empty() || year.empty()) - return vector(); - - vector vec(styles.size()); - for (vector::size_type i = 0; i != vec.size(); ++i) { - docstring str; - - switch (styles[i]) { - case CITE: - case CITEP: - str = from_ascii("[#ID]"); - break; - - case CITET: - str = author + " [#ID]"; - break; - - case CITEALT: - str = author + " #ID"; - break; - - case CITEALP: - str = from_ascii("#ID"); - break; - - case CITEAUTHOR: - str = author; - break; - - case CITEYEAR: - str = year; - break; - - case CITEYEARPAR: - str = '(' + year + ')'; - break; - } - - vec[i] = str; - } - - return vec; -} - - -vector const -getAuthorYearStrings(string const & key, - InfoMap const & map, vector const & styles) -{ - if (map.empty()) - return vector(); - - docstring const author = getAbbreviatedAuthor(map, key); - docstring const year = getYear(map, key); - if (author.empty() || year.empty()) - return vector(); - - vector vec(styles.size()); - for (vector::size_type i = 0; i != vec.size(); ++i) { - docstring str; - - switch (styles[i]) { - case CITE: - // jurabib only: Author/Annotator - // (i.e. the "before" field, 2nd opt arg) - str = author + "/<" + _("before") + '>'; - break; - - case CITET: - str = author + " (" + year + ')'; - break; - - case CITEP: - str = '(' + author + ", " + year + ')'; - break; - - case CITEALT: - str = author + ' ' + year ; - break; - - case CITEALP: - str = author + ", " + year ; - break; - - case CITEAUTHOR: - str = author; - break; - - case CITEYEAR: - str = year; - break; - - case CITEYEARPAR: - str = '(' + year + ')'; - break; - } - - vec[i] = str; - } - - return vec; -} - -} // namespace biblio -} // namespace lyx diff --git a/src/frontends/controllers/biblio.h b/src/frontends/controllers/biblio.h deleted file mode 100644 index 4d8fe5f904..0000000000 --- a/src/frontends/controllers/biblio.h +++ /dev/null @@ -1,169 +0,0 @@ -// -*- C++ -*- -/** - * \file biblio.h - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Angus Leeming - * - * Full author contact details are available in file CREDITS. - */ - -#ifndef BIBLIOHELPERS_H -#define BIBLIOHELPERS_H - -#include "support/docstring.h" - -#include -#include - -class Buffer; - -/** Functions of use to citation and bibtex GUI controllers and views */ -namespace lyx { -namespace biblio { - -enum CiteEngine { - ENGINE_BASIC, - ENGINE_NATBIB_AUTHORYEAR, - ENGINE_NATBIB_NUMERICAL, - ENGINE_JURABIB -}; - - -enum CiteStyle { - CITE, - CITET, - CITEP, - CITEALT, - CITEALP, - CITEAUTHOR, - CITEYEAR, - CITEYEARPAR -}; - - -enum Search { - SIMPLE, - REGEX -}; - - -enum Direction { - FORWARD, - BACKWARD -}; - - -/** Each citation engine recognizes only a subset of all possible - * citation commands. Given a latex command \c input, this function - * returns an appropriate command, valid for \c engine. - */ -std::string const asValidLatexCommand(std::string const & input, - CiteEngine const engine); - -/// First entry is the bibliography key, second the data -typedef std::map InfoMap; - -/// Returns a vector of bibliography keys -std::vector const getKeys(InfoMap const &); - -/** Returns the BibTeX data associated with a given key. - Empty if no info exists. */ -docstring const getInfo(InfoMap const &, std::string const & key); - -/// return the year from the bibtex data record -docstring const getYear(InfoMap const & map, std::string const & key); - -/// return the short form of an authorlist -docstring const getAbbreviatedAuthor(InfoMap const & map, std::string const & key); - -// return only the family name -docstring const familyName(docstring const & name); - -/** Search a BibTeX info field for the given key and return the - associated field. */ -docstring const parseBibTeX(docstring data, std::string const & findkey); - -/** Returns an iterator to the first key that meets the search - criterion, or end() if unsuccessful. - - User supplies : - the InfoMap of bibkeys info, - the vector of keys to be searched, - the search criterion, - an iterator defining the starting point of the search, - an enum defining a Simple or Regex search, - an enum defining the search direction. -*/ - -std::vector::const_iterator -searchKeys(InfoMap const & map, - std::vector const & keys_to_search, - docstring const & search_expression, - std::vector::const_iterator start, - Search, - Direction, - bool caseSensitive=false); - - -class CitationStyle { -public: - /// - CitationStyle(CiteStyle s = CITE, bool f = false, bool force = false) - : style(s), full(f), forceUCase(force) {} - /// \param latex_str a LaTeX command, "cite", "Citep*", etc - CitationStyle(std::string const & latex_str); - /// - std::string const asLatexStr() const; - /// - CiteStyle style; - /// - bool full; - /// - bool forceUCase; -}; - - -/// Returns a vector of available Citation styles. -std::vector const getCiteStyles(CiteEngine const ); - -/** - "Translates" the available Citation Styles into strings for this key. - The returned string is displayed by the GUI. - - - [XX] is used in place of the actual reference - Eg, the vector will contain: [XX], Jones et al. [XX], ... - - User supplies : - the key, - the InfoMap of bibkeys info, - the available citation styles -*/ -std::vector const -getNumericalStrings(std::string const & key, - InfoMap const & map, - std::vector const & styles); - -/** - "Translates" the available Citation Styles into strings for this key. - The returned string is displayed by the GUI. - - Eg, the vector will contain: - Jones et al. (1990), (Jones et al. 1990), Jones et al. 1990, ... - - User supplies : - the key, - the InfoMap of bibkeys info, - the available citation styles -*/ -std::vector const -getAuthorYearStrings(std::string const & key, - InfoMap const & map, - std::vector const & styles); - -} // namespace biblio -} // namespace lyx - -#endif // BIBLIOHELPERS_H diff --git a/src/frontends/controllers/character.C b/src/frontends/controllers/character.C deleted file mode 100644 index ca5fa6d012..0000000000 --- a/src/frontends/controllers/character.C +++ /dev/null @@ -1,263 +0,0 @@ -/** - * \file frontend_helpers.cpp - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Angus Leeming - * - * Full author contact details are available in file CREDITS. - */ - -#include - - -#include "gettext.h" -#include "character.h" -#include "LColor.h" - -using std::vector; - -namespace lyx { -namespace frontend { - -vector const getFamilyData() -{ - vector family(5); - - FamilyPair pr; - - pr.first = _("No change"); - pr.second = LyXFont::IGNORE_FAMILY; - family[0] = pr; - - pr.first = _("Roman"); - pr.second = LyXFont::ROMAN_FAMILY; - family[1] = pr; - - pr.first = _("Sans Serif"); - pr.second = LyXFont::SANS_FAMILY; - family[2] = pr; - - pr.first = _("Typewriter"); - pr.second = LyXFont::TYPEWRITER_FAMILY; - family[3] = pr; - - pr.first = _("Reset"); - pr.second = LyXFont::INHERIT_FAMILY; - family[4] = pr; - - return family; -} - - -vector const getSeriesData() -{ - vector series(4); - - SeriesPair pr; - - pr.first = _("No change"); - pr.second = LyXFont::IGNORE_SERIES; - series[0] = pr; - - pr.first = _("Medium"); - pr.second = LyXFont::MEDIUM_SERIES; - series[1] = pr; - - pr.first = _("Bold"); - pr.second = LyXFont::BOLD_SERIES; - series[2] = pr; - - pr.first = _("Reset"); - pr.second = LyXFont::INHERIT_SERIES; - series[3] = pr; - - return series; -} - - -vector const getShapeData() -{ - vector shape(6); - - ShapePair pr; - - pr.first = _("No change"); - pr.second = LyXFont::IGNORE_SHAPE; - shape[0] = pr; - - pr.first = _("Upright"); - pr.second = LyXFont::UP_SHAPE; - shape[1] = pr; - - pr.first = _("Italic"); - pr.second = LyXFont::ITALIC_SHAPE; - shape[2] = pr; - - pr.first = _("Slanted"); - pr.second = LyXFont::SLANTED_SHAPE; - shape[3] = pr; - - pr.first = _("Small Caps"); - pr.second = LyXFont::SMALLCAPS_SHAPE; - shape[4] = pr; - - pr.first = _("Reset"); - pr.second = LyXFont::INHERIT_SHAPE; - shape[5] = pr; - - return shape; -} - - -vector const getSizeData() -{ - vector size(14); - - SizePair pr; - - pr.first = _("No change"); - pr.second = LyXFont::IGNORE_SIZE; - size[0] = pr; - - pr.first = _("Tiny"); - pr.second = LyXFont::SIZE_TINY; - size[1] = pr; - - pr.first = _("Smallest"); - pr.second = LyXFont::SIZE_SCRIPT; - size[2] = pr; - - pr.first = _("Smaller"); - pr.second = LyXFont::SIZE_FOOTNOTE; - size[3] = pr; - - pr.first = _("Small"); - pr.second = LyXFont::SIZE_SMALL; - size[4] = pr; - - pr.first = _("Normal"); - pr.second = LyXFont::SIZE_NORMAL; - size[5] = pr; - - pr.first = _("Large"); - pr.second = LyXFont::SIZE_LARGE; - size[6] = pr; - - pr.first = _("Larger"); - pr.second = LyXFont::SIZE_LARGER; - size[7] = pr; - - pr.first = _("Largest"); - pr.second = LyXFont::SIZE_LARGEST; - size[8] = pr; - - pr.first = _("Huge"); - pr.second = LyXFont::SIZE_HUGE; - size[9] = pr; - - pr.first = _("Huger"); - pr.second = LyXFont::SIZE_HUGER; - size[10] = pr; - - pr.first = _("Increase"); - pr.second = LyXFont::INCREASE_SIZE; - size[11] = pr; - - pr.first = _("Decrease"); - pr.second = LyXFont::DECREASE_SIZE; - size[12] = pr; - - pr.first = _("Reset"); - pr.second = LyXFont::INHERIT_SIZE; - size[13] = pr; - - return size; -} - - -vector const getBarData() -{ - vector bar(5); - - BarPair pr; - - pr.first = _("No change"); - pr.second = IGNORE; - bar[0] = pr; - - pr.first = _("Emph"); - pr.second = EMPH_TOGGLE; - bar[1] = pr; - - pr.first = _("Underbar"); - pr.second = UNDERBAR_TOGGLE; - bar[2] = pr; - - pr.first = _("Noun"); - pr.second = NOUN_TOGGLE; - bar[3] = pr; - - pr.first = _("Reset"); - pr.second = INHERIT; - bar[4] = pr; - - return bar; -} - - -vector const getColorData() -{ - vector color(11); - - ColorPair pr; - - pr.first = _("No change"); - pr.second = LColor::ignore; - color[0] = pr; - - pr.first = _("No color"); - pr.second = LColor::none; - color[1] = pr; - - pr.first = _("Black"); - pr.second = LColor::black; - color[2] = pr; - - pr.first = _("White"); - pr.second = LColor::white; - color[3] = pr; - - pr.first = _("Red"); - pr.second = LColor::red; - color[4] = pr; - - pr.first = _("Green"); - pr.second = LColor::green; - color[5] = pr; - - pr.first = _("Blue"); - pr.second = LColor::blue; - color[6] = pr; - - pr.first = _("Cyan"); - pr.second = LColor::cyan; - color[7] = pr; - - pr.first = _("Magenta"); - pr.second = LColor::magenta; - color[8] = pr; - - pr.first = _("Yellow"); - pr.second = LColor::yellow; - color[9] = pr; - - pr.first = _("Reset"); - pr.second = LColor::inherit; - color[10] = pr; - - return color; -} - -} // namespace frontend -} // namespace lyx diff --git a/src/frontends/controllers/character.h b/src/frontends/controllers/character.h deleted file mode 100644 index a63f432aef..0000000000 --- a/src/frontends/controllers/character.h +++ /dev/null @@ -1,72 +0,0 @@ -// -*- C++ -*- -/** - * \file character.h - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Angus Leeming - * - * Full author contact details are available in file CREDITS. - */ - -#ifndef CHARACTERHELPERS_H -#define CHARACTERHELPERS_H - - -#include "lyxfont.h" - -#include -#include - - -class LColor_color; - - -/** Functions of use to the character GUI controller and view */ -namespace lyx { -namespace frontend { - -/// -enum FONT_STATE { - /// - IGNORE, - /// - EMPH_TOGGLE, - /// - UNDERBAR_TOGGLE, - /// - NOUN_TOGGLE, - /// - INHERIT -}; - -/// -typedef std::pair FamilyPair; -/// -typedef std::pair SeriesPair; -/// -typedef std::pair ShapePair; -/// -typedef std::pair SizePair; -/// -typedef std::pair BarPair; -/// -typedef std::pair ColorPair; - -/// -std::vector const getFamilyData(); -/// -std::vector const getSeriesData(); -/// -std::vector const getShapeData(); -/// -std::vector const getSizeData(); -/// -std::vector const getBarData(); -/// -std::vector const getColorData(); - -} // namespace frontend -} // namespace lyx - -#endif // CHARACTERHELPERS diff --git a/src/frontends/controllers/frnt_lang.C b/src/frontends/controllers/frnt_lang.C deleted file mode 100644 index ce48d0f8ad..0000000000 --- a/src/frontends/controllers/frnt_lang.C +++ /dev/null @@ -1,76 +0,0 @@ -/** - * \file frontend_helpers.cpp - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Angus Leeming - * - * Full author contact details are available in file CREDITS. - */ - -#include - - -#include "frnt_lang.h" -#include "gettext.h" -#include "language.h" - -#include - - -using std::string; -using std::vector; - - -namespace lyx { -namespace frontend { - -namespace { - -class Sorter - : public std::binary_function -{ -public: - bool operator()(LanguagePair const & lhs, - LanguagePair const & rhs) const { - return lhs.first < rhs.first; - } -}; - -} // namespace anon - - -vector const getLanguageData(bool character_dlg) -{ - vector::size_type const size = character_dlg ? - languages.size() + 2 : languages.size(); - - vector langs(size); - - if (character_dlg) { - langs[0].first = _("No change"); - langs[0].second = "ignore"; - langs[1].first = _("Reset"); - langs[1].second = "reset"; - } - - vector::size_type i = character_dlg ? 2 : 0; - for (Languages::const_iterator cit = languages.begin(); - cit != languages.end(); ++cit) { - langs[i].first = _(cit->second.display()); - langs[i].second = cit->second.lang(); - ++i; - } - - // Don't sort "ignore" and "reset" - vector::iterator begin = character_dlg ? - langs.begin() + 2 : langs.begin(); - - std::sort(begin, langs.end(), Sorter()); - - return langs; -} - -} // namespace frontend -} // namespace lyx diff --git a/src/frontends/controllers/frnt_lang.h b/src/frontends/controllers/frnt_lang.h deleted file mode 100644 index c79ef4467a..0000000000 --- a/src/frontends/controllers/frnt_lang.h +++ /dev/null @@ -1,36 +0,0 @@ -// -*- C++ -*- -/** - * \file frnt_lang.h - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Angus Leeming - * - * Full author contact details are available in file CREDITS. - * - * Ease the use of internationalised language strings in the dialogs. - */ - -#ifndef FRNT_LANG_H -#define FRNT_LANG_H - -#include "support/docstring.h" - -#include -#include - -namespace lyx { -namespace frontend { - -/// -typedef std::pair LanguagePair; - -/** If the caller is the character dialog, add "No change" and "Reset" - * to the vector. - */ -std::vector const getLanguageData(bool character_dlg); - -} // namespace frontend -} // namespace lyx - -#endif // FRNT_LANG_H diff --git a/src/frontends/controllers/frontend_helpers.cpp b/src/frontends/controllers/frontend_helpers.cpp new file mode 100644 index 0000000000..434290ed68 --- /dev/null +++ b/src/frontends/controllers/frontend_helpers.cpp @@ -0,0 +1,1499 @@ +/** + * \file frontend_helpers.cpp + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Angus Leeming + * \author Herbert Voß + * + * Full author contact details are available in file CREDITS. + */ + +#include + +#include "biblio.h" + +#include "buffer.h" +#include "bufferparams.h" +#include "gettext.h" + +#include "support/lstrings.h" + +#include + +#include + +using std::string; +using std::vector; + + +namespace lyx { + +using support::ascii_lowercase; +using support::bformat; +using support::compare_ascii_no_case; +using support::contains; +using support::getVectorFromString; +using support::ltrim; +using support::prefixIs; +using support::rtrim; +using support::split; +using support::subst; +using support::token; +using support::trim; + +namespace biblio { + +namespace { + +vector const init_possible_cite_commands() +{ + char const * const pos[] = { + "cite", + "citet", "citep", "citealt", "citealp", + "citeauthor", "citeyear", "citeyearpar", + "citet*", "citep*", "citealt*", "citealp*", "citeauthor*", + "Citet", "Citep", "Citealt", "Citealp", "Citeauthor", + "Citet*", "Citep*", "Citealt*", "Citealp*", "Citeauthor*", + "fullcite", + "footcite", "footcitet", "footcitep", "footcitealt", + "footcitealp", "footciteauthor", "footciteyear", + "footciteyearpar", + "citefield", + "citetitle", + "cite*" + }; + size_t const size_pos = sizeof(pos) / sizeof(pos[0]); + + return vector(pos, pos + size_pos); +} + + +vector const & possible_cite_commands() +{ + static vector const pos = init_possible_cite_commands(); + return pos; +} + + +bool is_possible_cite_command(string const & input) +{ + vector const & possibles = possible_cite_commands(); + vector::const_iterator const end = possibles.end(); + return std::find(possibles.begin(), end, input) != end; +} + + +string const default_cite_command(CiteEngine engine) +{ + string str; + switch (engine) { + case ENGINE_BASIC: + str = "cite"; + break; + case ENGINE_NATBIB_AUTHORYEAR: + str = "citet"; + break; + case ENGINE_NATBIB_NUMERICAL: + str = "citep"; + break; + case ENGINE_JURABIB: + str = "cite"; + break; + } + return str; +} + + +static const docstring TheBibliographyRef(from_ascii("TheBibliographyRef")); + +} // namespace anon + + +string const asValidLatexCommand(string const & input, + CiteEngine const engine) +{ + string const default_str = default_cite_command(engine); + if (!is_possible_cite_command(input)) + return default_str; + + string output; + switch (engine) { + case ENGINE_BASIC: + output = default_str; + break; + + case ENGINE_NATBIB_AUTHORYEAR: + case ENGINE_NATBIB_NUMERICAL: + if (input == "cite" || input == "citefield" || + input == "citetitle" || input == "cite*") + output = default_str; + else if (prefixIs(input, "foot")) + output = input.substr(4); + else + output = input; + break; + + case ENGINE_JURABIB: { + // Jurabib does not support the 'uppercase' natbib style. + if (input[0] == 'C') + output = string(1, 'c') + input.substr(1); + else + output = input; + + // Jurabib does not support the 'full' natbib style. + string::size_type const n = output.size() - 1; + if (output != "cite*" && output[n] == '*') + output = output.substr(0, n); + + break; + } + } + + return output; +} + + +docstring const familyName(docstring const & name) +{ + // Very simple parser + docstring fname = name; + + // possible authorname combinations are: + // "Surname, FirstName" + // "Surname, F." + // "FirstName Surname" + // "F. Surname" + docstring::size_type idx = fname.find(','); + if (idx != docstring::npos) + return ltrim(fname.substr(0, idx)); + idx = fname.rfind('.'); + if (idx != docstring::npos) + fname = ltrim(fname.substr(idx + 1)); + // test if we have a LaTeX Space in front + if (fname[0] == '\\') + return fname.substr(2); + + return rtrim(fname); +} + + +docstring const getAbbreviatedAuthor(InfoMap const & map, string const & key) +{ + BOOST_ASSERT(!map.empty()); + + InfoMap::const_iterator it = map.find(key); + if (it == map.end()) + return docstring(); + docstring const & data = it->second; + + // Is the entry a BibTeX one or one from lyx-layout "bibliography"? + docstring::size_type const pos = data.find(TheBibliographyRef); + if (pos != docstring::npos) { + if (pos <= 2) { + return docstring(); + } + + docstring const opt = trim(data.substr(0, pos - 1)); + if (opt.empty()) + return docstring(); + + docstring authors; + split(opt, authors, '('); + return authors; + } + + docstring author = parseBibTeX(data, "author"); + + if (author.empty()) + author = parseBibTeX(data, "editor"); + + if (author.empty()) { + author = parseBibTeX(data, "key"); + if (author.empty()) + // FIXME UNICODE + return from_utf8(key); + return author; + } + + vector const authors = getVectorFromString(author, from_ascii(" and ")); + if (authors.empty()) + return author; + + if (authors.size() == 2) + return bformat(_("%1$s and %2$s"), + familyName(authors[0]), familyName(authors[1])); + + if (authors.size() > 2) + return bformat(_("%1$s et al."), familyName(authors[0])); + + return familyName(authors[0]); +} + + +docstring const getYear(InfoMap const & map, string const & key) +{ + BOOST_ASSERT(!map.empty()); + + InfoMap::const_iterator it = map.find(key); + if (it == map.end()) + return docstring(); + docstring const & data = it->second; + + // Is the entry a BibTeX one or one from lyx-layout "bibliography"? + docstring::size_type const pos = data.find(TheBibliographyRef); + if (pos != docstring::npos) { + if (pos <= 2) { + return docstring(); + } + + docstring const opt = + trim(data.substr(0, pos - 1)); + if (opt.empty()) + return docstring(); + + docstring authors; + docstring const tmp = split(opt, authors, '('); + docstring year; + split(tmp, year, ')'); + return year; + + } + + docstring year = parseBibTeX(data, "year"); + if (year.empty()) + year = _("No year"); + + return year; +} + + +namespace { + +// A functor for use with std::sort, leading to case insensitive sorting +class compareNoCase: public std::binary_function +{ +public: + bool operator()(string const & s1, string const & s2) const { + return compare_ascii_no_case(s1, s2) < 0; + } +}; + +} // namespace anon + + +vector const getKeys(InfoMap const & map) +{ + vector bibkeys; + InfoMap::const_iterator it = map.begin(); + InfoMap::const_iterator end = map.end(); + for (; it != end; ++it) { + bibkeys.push_back(it->first); + } + + std::sort(bibkeys.begin(), bibkeys.end(), compareNoCase()); + return bibkeys; +} + + +docstring const getInfo(InfoMap const & map, string const & key) +{ + BOOST_ASSERT(!map.empty()); + + InfoMap::const_iterator it = map.find(key); + if (it == map.end()) + return docstring(); + docstring const & data = it->second; + + // is the entry a BibTeX one or one from lyx-layout "bibliography"? + docstring::size_type const pos = data.find(TheBibliographyRef); + if (pos != docstring::npos) { + docstring::size_type const pos2 = pos + TheBibliographyRef.size(); + docstring const info = trim(data.substr(pos2)); + return info; + } + + // Search for all possible "required" keys + docstring author = parseBibTeX(data, "author"); + if (author.empty()) + author = parseBibTeX(data, "editor"); + + docstring year = parseBibTeX(data, "year"); + docstring title = parseBibTeX(data, "title"); + docstring booktitle = parseBibTeX(data, "booktitle"); + docstring chapter = parseBibTeX(data, "chapter"); + docstring number = parseBibTeX(data, "number"); + docstring volume = parseBibTeX(data, "volume"); + docstring pages = parseBibTeX(data, "pages"); + docstring annote = parseBibTeX(data, "annote"); + docstring media = parseBibTeX(data, "journal"); + if (media.empty()) + media = parseBibTeX(data, "publisher"); + if (media.empty()) + media = parseBibTeX(data, "school"); + if (media.empty()) + media = parseBibTeX(data, "institution"); + + odocstringstream result; + if (!author.empty()) + result << author << ", "; + if (!title.empty()) + result << title; + if (!booktitle.empty()) + result << ", in " << booktitle; + if (!chapter.empty()) + result << ", Ch. " << chapter; + if (!media.empty()) + result << ", " << media; + if (!volume.empty()) + result << ", vol. " << volume; + if (!number.empty()) + result << ", no. " << number; + if (!pages.empty()) + result << ", pp. " << pages; + if (!year.empty()) + result << ", " << year; + if (!annote.empty()) + result << "\n\n" << annote; + + docstring const result_str = rtrim(result.str()); + if (!result_str.empty()) + return result_str; + + // This should never happen (or at least be very unusual!) + return data; +} + + +namespace { + +// Escape special chars. +// All characters are literals except: '.|*?+(){}[]^$\' +// These characters are literals when preceded by a "\", which is done here +// @todo: This function should be moved to support, and then the test in tests +// should be moved there as well. +string const escape_special_chars(string const & expr) +{ + // Search for all chars '.|*?+(){}[^$]\' + // Note that '[' and '\' must be escaped. + // This is a limitation of boost::regex, but all other chars in BREs + // are assumed literal. + boost::regex reg("[].|*?+(){}^$\\[\\\\]"); + + // $& is a perl-like expression that expands to all + // of the current match + // The '$' must be prefixed with the escape character '\' for + // boost to treat it as a literal. + // Thus, to prefix a matched expression with '\', we use: + return boost::regex_replace(expr, reg, "\\\\$&"); +} + + +// A functor for use with std::find_if, used to ascertain whether a +// data entry matches the required regex_ +// @throws: boost::regex_error if the supplied regex pattern is not valid +// @todo: This function should be moved to support. +class RegexMatch : public std::unary_function +{ +public: + // re and icase are used to construct an instance of boost::RegEx. + // if icase is true, then matching is insensitive to case + RegexMatch(InfoMap const & m, string const & re, bool icase) + : map_(m), regex_(re, icase) {} + + bool operator()(string const & key) const { + // the data searched is the key + its associated BibTeX/biblio + // fields + string data = key; + InfoMap::const_iterator info = map_.find(key); + if (info != map_.end()) + // FIXME UNICODE + data += ' ' + to_utf8(info->second); + + // Attempts to find a match for the current RE + // somewhere in data. + return boost::regex_search(data, regex_); + } +private: + InfoMap const map_; + mutable boost::regex regex_; +}; + +} // namespace anon + + +vector::const_iterator +searchKeys(InfoMap const & theMap, + vector const & keys, + string const & search_expr, + vector::const_iterator start, + Search type, + Direction dir, + bool caseSensitive) +{ + // Preliminary checks + if (start < keys.begin() || start >= keys.end()) + return keys.end(); + + string expr = trim(search_expr); + if (expr.empty()) + return keys.end(); + + if (type == SIMPLE) + // We must escape special chars in the search_expr so that + // it is treated as a simple string by boost::regex. + expr = escape_special_chars(expr); + + try { + // Build the functor that will be passed to find_if. + RegexMatch const match(theMap, expr, !caseSensitive); + + // Search the vector of 'keys' from 'start' for one + // that matches the predicate 'match'. Searching can + // be forward or backward from start. + if (dir == FORWARD) + return std::find_if(start, keys.end(), match); + + vector::const_reverse_iterator rit(start); + vector::const_reverse_iterator rend = keys.rend(); + rit = std::find_if(rit, rend, match); + + if (rit == rend) + return keys.end(); + // This is correct and always safe. + // (See Meyer's Effective STL, Item 28.) + return (++rit).base(); + } + catch (boost::regex_error &) { + return keys.end(); + } +} + + +docstring const parseBibTeX(docstring data, string const & findkey) +{ + // at first we delete all characters right of '%' and + // replace tabs through a space and remove leading spaces + // we read the data line by line so that the \n are + // ignored, too. + docstring data_; + int Entries = 0; + docstring dummy = token(data,'\n', Entries); + while (!dummy.empty()) { + // no tabs + dummy = subst(dummy, '\t', ' '); + // no leading spaces + dummy = ltrim(dummy); + // ignore lines with a beginning '%' or ignore all right of % + docstring::size_type const idx = + dummy.empty() ? docstring::npos : dummy.find('%'); + if (idx != docstring::npos) + // Check if this is really a comment or just "\%" + if (idx == 0 || dummy[idx - 1] != '\\') + dummy.erase(idx, docstring::npos); + else + // This is "\%", so just erase the '\' + dummy.erase(idx - 1, 1); + // do we have a new token or a new line of + // the same one? In the first case we ignore + // the \n and in the second we replace it + // with a space + if (!dummy.empty()) { + if (!contains(dummy, '=')) + data_ += ' ' + dummy; + else + data_ += dummy; + } + dummy = token(data, '\n', ++Entries); + } + + // replace double commas with "" for easy scanning + data = subst(data_, from_ascii(",,"), from_ascii("\"\"")); + + // unlikely! + if (data.empty()) + return docstring(); + + // now get only the important line of the bibtex entry. + // all entries are devided by ',' except the last one. + data += ','; + // now we have same behaviour for all entries because the last one + // is "blah ... }" + Entries = 0; + bool found = false; + // parsing of title and booktitle is different from the + // others, because booktitle contains title + do { + dummy = token(data, ',', Entries++); + if (!dummy.empty()) { + found = contains(ascii_lowercase(dummy), from_ascii(findkey)); + if (findkey == "title" && + contains(ascii_lowercase(dummy), from_ascii("booktitle"))) + found = false; + } + } while (!found && !dummy.empty()); + if (dummy.empty()) + // no such keyword + return docstring(); + + // we are not sure, if we get all, because "key= "blah, blah" is + // allowed. + // Therefore we read all until the next "=" character, which follows a + // new keyword + docstring keyvalue = dummy; + dummy = token(data, ',', Entries++); + while (!contains(dummy, '=') && !dummy.empty()) { + keyvalue += ',' + dummy; + dummy = token(data, ',', Entries++); + } + + // replace double "" with originals ,, (two commas) + // leaving us with the all-important line + data = subst(keyvalue, from_ascii("\"\""), from_ascii(",,")); + + // Clean-up. + // 1. Spaces + data = rtrim(data); + // 2. if there is no opening '{' then a closing '{' is probably cruft. + if (!contains(data, '{')) + data = rtrim(data, "}"); + // happens, when last keyword + docstring::size_type const idx = + !data.empty() ? data.find('=') : docstring::npos; + + if (idx == docstring::npos) + return docstring(); + + data = trim(data.substr(idx)); + + // a valid entry? + if (data.length() < 2 || data[0] != '=') + return docstring(); + else { + // delete '=' and the following spaces + data = ltrim(data, " ="); + if (data.length() < 2) { + // not long enough to find delimiters + return data; + } else { + docstring::size_type keypos = 1; + char_type enclosing; + if (data[0] == '{') { + enclosing = '}'; + } else if (data[0] == '"') { + enclosing = '"'; + } else { + // no {} and no "", pure data but with a + // possible ',' at the end + return rtrim(data, ","); + } + docstring tmp = data.substr(keypos); + while (tmp.find('{') != docstring::npos && + tmp.find('}') != docstring::npos && + tmp.find('{') < tmp.find('}') && + tmp.find('{') < tmp.find(enclosing)) { + + keypos += tmp.find('{') + 1; + tmp = data.substr(keypos); + keypos += tmp.find('}') + 1; + tmp = data.substr(keypos); + } + if (tmp.find(enclosing) == docstring::npos) + return data; + else { + keypos += tmp.find(enclosing); + return data.substr(1, keypos - 1); + } + } + } +} + + +namespace { + + +char const * const citeCommands[] = { + "cite", "citet", "citep", "citealt", "citealp", "citeauthor", + "citeyear", "citeyearpar" }; + +unsigned int const nCiteCommands = + sizeof(citeCommands) / sizeof(char *); + +CiteStyle const citeStyles[] = { + CITE, CITET, CITEP, CITEALT, CITEALP, + CITEAUTHOR, CITEYEAR, CITEYEARPAR }; + +unsigned int const nCiteStyles = + sizeof(citeStyles) / sizeof(CiteStyle); + +CiteStyle const citeStylesFull[] = { + CITET, CITEP, CITEALT, CITEALP, CITEAUTHOR }; + +unsigned int const nCiteStylesFull = + sizeof(citeStylesFull) / sizeof(CiteStyle); + +CiteStyle const citeStylesUCase[] = { + CITET, CITEP, CITEALT, CITEALP, CITEAUTHOR }; + +unsigned int const nCiteStylesUCase = + sizeof(citeStylesUCase) / sizeof(CiteStyle); + +} // namespace anon + + +CitationStyle::CitationStyle(string const & command) + : style(CITE), full(false), forceUCase(false) +{ + if (command.empty()) + return; + + string cmd = command; + if (cmd[0] == 'C') { + forceUCase = true; + cmd[0] = 'c'; + } + + string::size_type const n = cmd.size() - 1; + if (cmd != "cite" && cmd[n] == '*') { + full = true; + cmd = cmd.substr(0,n); + } + + char const * const * const last = citeCommands + nCiteCommands; + char const * const * const ptr = std::find(citeCommands, last, cmd); + + if (ptr != last) { + size_t idx = ptr - citeCommands; + style = citeStyles[idx]; + } +} + + +string const CitationStyle::asLatexStr() const +{ + string cite = citeCommands[style]; + if (full) { + CiteStyle const * last = citeStylesFull + nCiteStylesFull; + if (std::find(citeStylesFull, last, style) != last) + cite += '*'; + } + + if (forceUCase) { + CiteStyle const * last = citeStylesUCase + nCiteStylesUCase; + if (std::find(citeStylesUCase, last, style) != last) + cite[0] = 'C'; + } + + return cite; +} + + +vector const getCiteStyles(CiteEngine const engine) +{ + unsigned int nStyles = 0; + unsigned int start = 0; + + switch (engine) { + case ENGINE_BASIC: + nStyles = 1; + start = 0; + break; + case ENGINE_NATBIB_AUTHORYEAR: + case ENGINE_NATBIB_NUMERICAL: + nStyles = nCiteStyles - 1; + start = 1; + break; + case ENGINE_JURABIB: + nStyles = nCiteStyles; + start = 0; + break; + } + + typedef vector cite_vec; + + cite_vec styles(nStyles); + cite_vec::size_type i = 0; + int j = start; + for (; i != styles.size(); ++i, ++j) + styles[i] = citeStyles[j]; + + return styles; +} + + +vector const +getNumericalStrings(string const & key, + InfoMap const & map, vector const & styles) +{ + if (map.empty()) + return vector(); + + docstring const author = getAbbreviatedAuthor(map, key); + docstring const year = getYear(map, key); + if (author.empty() || year.empty()) + return vector(); + + vector vec(styles.size()); + for (vector::size_type i = 0; i != vec.size(); ++i) { + docstring str; + + switch (styles[i]) { + case CITE: + case CITEP: + str = from_ascii("[#ID]"); + break; + + case CITET: + str = author + " [#ID]"; + break; + + case CITEALT: + str = author + " #ID"; + break; + + case CITEALP: + str = from_ascii("#ID"); + break; + + case CITEAUTHOR: + str = author; + break; + + case CITEYEAR: + str = year; + break; + + case CITEYEARPAR: + str = '(' + year + ')'; + break; + } + + vec[i] = str; + } + + return vec; +} + + +vector const +getAuthorYearStrings(string const & key, + InfoMap const & map, vector const & styles) +{ + if (map.empty()) + return vector(); + + docstring const author = getAbbreviatedAuthor(map, key); + docstring const year = getYear(map, key); + if (author.empty() || year.empty()) + return vector(); + + vector vec(styles.size()); + for (vector::size_type i = 0; i != vec.size(); ++i) { + docstring str; + + switch (styles[i]) { + case CITE: + // jurabib only: Author/Annotator + // (i.e. the "before" field, 2nd opt arg) + str = author + "/<" + _("before") + '>'; + break; + + case CITET: + str = author + " (" + year + ')'; + break; + + case CITEP: + str = '(' + author + ", " + year + ')'; + break; + + case CITEALT: + str = author + ' ' + year ; + break; + + case CITEALP: + str = author + ", " + year ; + break; + + case CITEAUTHOR: + str = author; + break; + + case CITEYEAR: + str = year; + break; + + case CITEYEARPAR: + str = '(' + year + ')'; + break; + } + + vec[i] = str; + } + + return vec; +} + +} // namespace biblio +} // namespace lyx +/** + * \file frontend_helpers.cpp + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Angus Leeming + * + * Full author contact details are available in file CREDITS. + */ + +#include + + +#include "gettext.h" +#include "character.h" +#include "LColor.h" + +using std::vector; + +namespace lyx { +namespace frontend { + +vector const getFamilyData() +{ + vector family(5); + + FamilyPair pr; + + pr.first = _("No change"); + pr.second = LyXFont::IGNORE_FAMILY; + family[0] = pr; + + pr.first = _("Roman"); + pr.second = LyXFont::ROMAN_FAMILY; + family[1] = pr; + + pr.first = _("Sans Serif"); + pr.second = LyXFont::SANS_FAMILY; + family[2] = pr; + + pr.first = _("Typewriter"); + pr.second = LyXFont::TYPEWRITER_FAMILY; + family[3] = pr; + + pr.first = _("Reset"); + pr.second = LyXFont::INHERIT_FAMILY; + family[4] = pr; + + return family; +} + + +vector const getSeriesData() +{ + vector series(4); + + SeriesPair pr; + + pr.first = _("No change"); + pr.second = LyXFont::IGNORE_SERIES; + series[0] = pr; + + pr.first = _("Medium"); + pr.second = LyXFont::MEDIUM_SERIES; + series[1] = pr; + + pr.first = _("Bold"); + pr.second = LyXFont::BOLD_SERIES; + series[2] = pr; + + pr.first = _("Reset"); + pr.second = LyXFont::INHERIT_SERIES; + series[3] = pr; + + return series; +} + + +vector const getShapeData() +{ + vector shape(6); + + ShapePair pr; + + pr.first = _("No change"); + pr.second = LyXFont::IGNORE_SHAPE; + shape[0] = pr; + + pr.first = _("Upright"); + pr.second = LyXFont::UP_SHAPE; + shape[1] = pr; + + pr.first = _("Italic"); + pr.second = LyXFont::ITALIC_SHAPE; + shape[2] = pr; + + pr.first = _("Slanted"); + pr.second = LyXFont::SLANTED_SHAPE; + shape[3] = pr; + + pr.first = _("Small Caps"); + pr.second = LyXFont::SMALLCAPS_SHAPE; + shape[4] = pr; + + pr.first = _("Reset"); + pr.second = LyXFont::INHERIT_SHAPE; + shape[5] = pr; + + return shape; +} + + +vector const getSizeData() +{ + vector size(14); + + SizePair pr; + + pr.first = _("No change"); + pr.second = LyXFont::IGNORE_SIZE; + size[0] = pr; + + pr.first = _("Tiny"); + pr.second = LyXFont::SIZE_TINY; + size[1] = pr; + + pr.first = _("Smallest"); + pr.second = LyXFont::SIZE_SCRIPT; + size[2] = pr; + + pr.first = _("Smaller"); + pr.second = LyXFont::SIZE_FOOTNOTE; + size[3] = pr; + + pr.first = _("Small"); + pr.second = LyXFont::SIZE_SMALL; + size[4] = pr; + + pr.first = _("Normal"); + pr.second = LyXFont::SIZE_NORMAL; + size[5] = pr; + + pr.first = _("Large"); + pr.second = LyXFont::SIZE_LARGE; + size[6] = pr; + + pr.first = _("Larger"); + pr.second = LyXFont::SIZE_LARGER; + size[7] = pr; + + pr.first = _("Largest"); + pr.second = LyXFont::SIZE_LARGEST; + size[8] = pr; + + pr.first = _("Huge"); + pr.second = LyXFont::SIZE_HUGE; + size[9] = pr; + + pr.first = _("Huger"); + pr.second = LyXFont::SIZE_HUGER; + size[10] = pr; + + pr.first = _("Increase"); + pr.second = LyXFont::INCREASE_SIZE; + size[11] = pr; + + pr.first = _("Decrease"); + pr.second = LyXFont::DECREASE_SIZE; + size[12] = pr; + + pr.first = _("Reset"); + pr.second = LyXFont::INHERIT_SIZE; + size[13] = pr; + + return size; +} + + +vector const getBarData() +{ + vector bar(5); + + BarPair pr; + + pr.first = _("No change"); + pr.second = IGNORE; + bar[0] = pr; + + pr.first = _("Emph"); + pr.second = EMPH_TOGGLE; + bar[1] = pr; + + pr.first = _("Underbar"); + pr.second = UNDERBAR_TOGGLE; + bar[2] = pr; + + pr.first = _("Noun"); + pr.second = NOUN_TOGGLE; + bar[3] = pr; + + pr.first = _("Reset"); + pr.second = INHERIT; + bar[4] = pr; + + return bar; +} + + +vector const getColorData() +{ + vector color(11); + + ColorPair pr; + + pr.first = _("No change"); + pr.second = LColor::ignore; + color[0] = pr; + + pr.first = _("No color"); + pr.second = LColor::none; + color[1] = pr; + + pr.first = _("Black"); + pr.second = LColor::black; + color[2] = pr; + + pr.first = _("White"); + pr.second = LColor::white; + color[3] = pr; + + pr.first = _("Red"); + pr.second = LColor::red; + color[4] = pr; + + pr.first = _("Green"); + pr.second = LColor::green; + color[5] = pr; + + pr.first = _("Blue"); + pr.second = LColor::blue; + color[6] = pr; + + pr.first = _("Cyan"); + pr.second = LColor::cyan; + color[7] = pr; + + pr.first = _("Magenta"); + pr.second = LColor::magenta; + color[8] = pr; + + pr.first = _("Yellow"); + pr.second = LColor::yellow; + color[9] = pr; + + pr.first = _("Reset"); + pr.second = LColor::inherit; + color[10] = pr; + + return color; +} + +} // namespace frontend +} // namespace lyx +/** + * \file frontend_helpers.cpp + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Angus Leeming + * + * Full author contact details are available in file CREDITS. + */ + +#include + + +#include "frnt_lang.h" +#include "gettext.h" +#include "language.h" + +#include + + +using std::string; +using std::vector; + + +namespace lyx { +namespace frontend { + +namespace { + +class Sorter + : public std::binary_function +{ +public: + bool operator()(LanguagePair const & lhs, + LanguagePair const & rhs) const { + return lhs.first < rhs.first; + } +}; + +} // namespace anon + + +vector const getLanguageData(bool character_dlg) +{ + vector::size_type const size = character_dlg ? + languages.size() + 2 : languages.size(); + + vector langs(size); + + if (character_dlg) { + langs[0].first = _("No change"); + langs[0].second = "ignore"; + langs[1].first = _("Reset"); + langs[1].second = "reset"; + } + + vector::size_type i = character_dlg ? 2 : 0; + for (Languages::const_iterator cit = languages.begin(); + cit != languages.end(); ++cit) { + langs[i].first = _(cit->second.display()); + langs[i].second = cit->second.lang(); + ++i; + } + + // Don't sort "ignore" and "reset" + vector::iterator begin = character_dlg ? + langs.begin() + 2 : langs.begin(); + + std::sort(begin, langs.end(), Sorter()); + + return langs; +} + +} // namespace frontend +} // namespace lyx +/** + * \file frontend_helpers.cpp + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Jean-Marc Lasgouttes + * \author Angus Leeming + * + * Full author contact details are available in file CREDITS. + */ + + +#include + +#include "helper_funcs.h" + +#include "gettext.h" +#include "lyxlength.h" + +#include "frontends/FileDialog.h" + +#include "support/filetools.h" +#include "support/lstrings.h" +#include "support/package.h" + +using std::pair; +using std::string; +using std::vector; + +namespace lyx { + +using support::addName; +using support::FileFilterList; +using support::getExtension; +using support::libFileSearch; +using support::makeAbsPath; +using support::makeRelPath; +using support::onlyFilename; +using support::onlyPath; +using support::package; +using support::prefixIs; +using support::removeExtension; + +namespace frontend { + + +docstring const browseFile(docstring const & filename, + docstring const & title, + FileFilterList const & filters, + bool save, + pair const & dir1, + pair const & dir2) +{ + docstring lastPath = from_ascii("."); + if (!filename.empty()) + lastPath = from_utf8(onlyPath(to_utf8(filename))); + + FileDialog fileDlg(title, LFUN_SELECT_FILE_SYNC, dir1, dir2); + + FileDialog::Result result; + + if (save) + result = fileDlg.save(lastPath, filters, + from_utf8(onlyFilename(to_utf8(filename)))); + else + result = fileDlg.open(lastPath, filters, + from_utf8(onlyFilename(to_utf8(filename)))); + + return result.second; +} + + +docstring const browseRelFile(docstring const & filename, + docstring const & refpath, + docstring const & title, + FileFilterList const & filters, + bool save, + pair const & dir1, + pair const & dir2) +{ + docstring const fname = from_utf8(makeAbsPath( + to_utf8(filename), to_utf8(refpath)).absFilename()); + + docstring const outname = browseFile(fname, title, filters, save, + dir1, dir2); + docstring const reloutname = makeRelPath(outname, refpath); + if (prefixIs(reloutname, from_ascii("../"))) + return outname; + else + return reloutname; +} + + + +docstring const browseLibFile(docstring const & dir, + docstring const & name, + docstring const & ext, + docstring const & title, + FileFilterList const & filters) +{ + // FIXME UNICODE + pair const dir1(_("System files|#S#s"), + from_utf8(addName(package().system_support().absFilename(), to_utf8(dir)))); + + pair const dir2(_("User files|#U#u"), + from_utf8(addName(package().user_support().absFilename(), to_utf8(dir)))); + + docstring const result = browseFile(from_utf8( + libFileSearch(to_utf8(dir), to_utf8(name), to_utf8(ext)).absFilename()), + title, filters, false, dir1, dir2); + + // remove the extension if it is the default one + docstring noextresult; + if (from_utf8(getExtension(to_utf8(result))) == ext) + noextresult = from_utf8(removeExtension(to_utf8(result))); + else + noextresult = result; + + // remove the directory, if it is the default one + docstring const file = from_utf8(onlyFilename(to_utf8(noextresult))); + if (from_utf8(libFileSearch(to_utf8(dir), to_utf8(file), to_utf8(ext)).absFilename()) == result) + return file; + else + return noextresult; +} + + +docstring const browseDir(docstring const & pathname, + docstring const & title, + pair const & dir1, + pair const & dir2) +{ + docstring lastPath = from_ascii("."); + if (!pathname.empty()) + lastPath = from_utf8(onlyPath(to_utf8(pathname))); + + FileDialog fileDlg(title, LFUN_SELECT_FILE_SYNC, dir1, dir2); + + FileDialog::Result const result = + fileDlg.opendir(lastPath, from_utf8(onlyFilename(to_utf8(pathname)))); + + return result.second; +} + + +vector const getLatexUnits() +{ + vector units; + int i = 0; + char const * str = stringFromUnit(i); + for (; str != 0; ++i, str = stringFromUnit(i)) + units.push_back(from_ascii(str)); + + return units; +} + +} // namespace frontend +} // namespace lyx +/** + * \file frontend_helpers.cpp + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Herbert Voß + * + * Full author contact details are available in file CREDITS. + */ + +#include + +#include "tex_helpers.h" + +#include "debug.h" +#include "gettext.h" + +#include "frontends/Alert.h" + +#include "support/filetools.h" +#include "support/lstrings.h" +#include "support/lyxalgo.h" +#include "support/os.h" +#include "support/package.h" +#include "support/path.h" +#include "support/systemcall.h" + +#include +#include + +using std::string; +using std::endl; + +namespace lyx { + +using support::bformat; +using support::contains; +using support::FileName; +using support::getExtension; +using support::getFileContents; +using support::getVectorFromString; +using support::libFileSearch; +using support::onlyFilename; +using support::package; +using support::quoteName; +using support::split; +using support::Systemcall; +using support::token; + +namespace frontend { + +void rescanTexStyles() +{ + // Run rescan in user lyx directory + support::Path p(package().user_support()); + FileName const command = libFileSearch("scripts", "TeXFiles.py"); + Systemcall one; + int const status = one.startscript(Systemcall::Wait, + lyx::support::os::python() + ' ' + + quoteName(command.toFilesystemEncoding())); + if (status == 0) + return; + // FIXME UNICODE + Alert::error(_("Could not update TeX information"), + bformat(_("The script `%s' failed."), lyx::from_utf8(command.absFilename()))); +} + + +void texhash() +{ + // Run texhash in user lyx directory + support::Path p(package().user_support()); + + //path to texhash through system + Systemcall one; + one.startscript(Systemcall::Wait,"texhash"); +} + + +void getTexFileList(string const & filename, std::vector & list) +{ + list.clear(); + FileName const file = libFileSearch("", filename); + if (file.empty()) + return; + + list = getVectorFromString(getFileContents(file), "\n"); + + // Normalise paths like /foo//bar ==> /foo/bar + boost::RegEx regex("/{2,}"); + std::vector::iterator it = list.begin(); + std::vector::iterator end = list.end(); + for (; it != end; ++it) { + *it = regex.Merge((*it), "/"); + } + + // remove empty items and duplicates + list.erase(std::remove(list.begin(), list.end(), ""), list.end()); + eliminate_duplicates(list); +} + + +string const getListOfOptions(string const & classname, string const & type) +{ + FileName const filename(getTexFileFromList(classname, type)); + if (filename.empty()) + return string(); + string optionList = string(); + std::ifstream is(filename.toFilesystemEncoding().c_str()); + while (is) { + string s; + is >> s; + if (contains(s,"DeclareOption")) { + s = s.substr(s.find("DeclareOption")); + s = split(s,'{'); // cut front + s = token(s,'}',0); // cut end + optionList += (s + '\n'); + } + } + return optionList; +} + + +string const getTexFileFromList(string const & file, + string const & type) +{ + string file_ = file; + // do we need to add the suffix? + if (!(getExtension(file) == type)) + file_ += '.' + type; + + lyxerr << "Searching for file " << file_ << endl; + + string lstfile; + if (type == "cls") + lstfile = "clsFiles.lst"; + else if (type == "sty") + lstfile = "styFiles.lst"; + else if (type == "bst") + lstfile = "bstFiles.lst"; + else if (type == "bib") + lstfile = "bibFiles.lst"; + FileName const abslstfile = libFileSearch(string(), lstfile); + if (abslstfile.empty()) { + lyxerr << "File `'" << lstfile << "' not found." << endl; + return string(); + } + string const allClasses = getFileContents(abslstfile); + int entries = 0; + string classfile = token(allClasses, '\n', entries); + int count = 0; + while ((!contains(classfile, file) || + (onlyFilename(classfile) != file)) && + (++count < 1000)) { + classfile = token(allClasses, '\n', ++entries); + } + + // now we have filename with full path + lyxerr << "with full path: " << classfile << endl; + + return classfile; +} + +} // namespace frontend +} // namespace lyx diff --git a/src/frontends/controllers/frontend_helpers.h b/src/frontends/controllers/frontend_helpers.h new file mode 100644 index 0000000000..96bed3f554 --- /dev/null +++ b/src/frontends/controllers/frontend_helpers.h @@ -0,0 +1,443 @@ +// -*- C++ -*- +/** + * \file biblio.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Angus Leeming + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef BIBLIOHELPERS_H +#define BIBLIOHELPERS_H + +#include "support/docstring.h" + +#include +#include + +class Buffer; + +/** Functions of use to citation and bibtex GUI controllers and views */ +namespace lyx { +namespace biblio { + +enum CiteEngine { + ENGINE_BASIC, + ENGINE_NATBIB_AUTHORYEAR, + ENGINE_NATBIB_NUMERICAL, + ENGINE_JURABIB +}; + + +enum CiteStyle { + CITE, + CITET, + CITEP, + CITEALT, + CITEALP, + CITEAUTHOR, + CITEYEAR, + CITEYEARPAR +}; + + +enum Search { + SIMPLE, + REGEX +}; + + +enum Direction { + FORWARD, + BACKWARD +}; + + +/** Each citation engine recognizes only a subset of all possible + * citation commands. Given a latex command \c input, this function + * returns an appropriate command, valid for \c engine. + */ +std::string const asValidLatexCommand(std::string const & input, + CiteEngine const engine); + +/// First entry is the bibliography key, second the data +typedef std::map InfoMap; + +/// Returns a vector of bibliography keys +std::vector const getKeys(InfoMap const &); + +/** Returns the BibTeX data associated with a given key. + Empty if no info exists. */ +docstring const getInfo(InfoMap const &, std::string const & key); + +/// return the year from the bibtex data record +docstring const getYear(InfoMap const & map, std::string const & key); + +/// return the short form of an authorlist +docstring const getAbbreviatedAuthor(InfoMap const & map, std::string const & key); + +// return only the family name +docstring const familyName(docstring const & name); + +/** Search a BibTeX info field for the given key and return the + associated field. */ +docstring const parseBibTeX(docstring data, std::string const & findkey); + +/** Returns an iterator to the first key that meets the search + criterion, or end() if unsuccessful. + + User supplies : + the InfoMap of bibkeys info, + the vector of keys to be searched, + the search criterion, + an iterator defining the starting point of the search, + an enum defining a Simple or Regex search, + an enum defining the search direction. +*/ + +std::vector::const_iterator +searchKeys(InfoMap const & map, + std::vector const & keys_to_search, + docstring const & search_expression, + std::vector::const_iterator start, + Search, + Direction, + bool caseSensitive=false); + + +class CitationStyle { +public: + /// + CitationStyle(CiteStyle s = CITE, bool f = false, bool force = false) + : style(s), full(f), forceUCase(force) {} + /// \param latex_str a LaTeX command, "cite", "Citep*", etc + CitationStyle(std::string const & latex_str); + /// + std::string const asLatexStr() const; + /// + CiteStyle style; + /// + bool full; + /// + bool forceUCase; +}; + + +/// Returns a vector of available Citation styles. +std::vector const getCiteStyles(CiteEngine const ); + +/** + "Translates" the available Citation Styles into strings for this key. + The returned string is displayed by the GUI. + + + [XX] is used in place of the actual reference + Eg, the vector will contain: [XX], Jones et al. [XX], ... + + User supplies : + the key, + the InfoMap of bibkeys info, + the available citation styles +*/ +std::vector const +getNumericalStrings(std::string const & key, + InfoMap const & map, + std::vector const & styles); + +/** + "Translates" the available Citation Styles into strings for this key. + The returned string is displayed by the GUI. + + Eg, the vector will contain: + Jones et al. (1990), (Jones et al. 1990), Jones et al. 1990, ... + + User supplies : + the key, + the InfoMap of bibkeys info, + the available citation styles +*/ +std::vector const +getAuthorYearStrings(std::string const & key, + InfoMap const & map, + std::vector const & styles); + +} // namespace biblio +} // namespace lyx + +#endif // BIBLIOHELPERS_H +// -*- C++ -*- +/** + * \file character.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Angus Leeming + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef CHARACTERHELPERS_H +#define CHARACTERHELPERS_H + + +#include "lyxfont.h" + +#include +#include + + +class LColor_color; + + +/** Functions of use to the character GUI controller and view */ +namespace lyx { +namespace frontend { + +/// +enum FONT_STATE { + /// + IGNORE, + /// + EMPH_TOGGLE, + /// + UNDERBAR_TOGGLE, + /// + NOUN_TOGGLE, + /// + INHERIT +}; + +/// +typedef std::pair FamilyPair; +/// +typedef std::pair SeriesPair; +/// +typedef std::pair ShapePair; +/// +typedef std::pair SizePair; +/// +typedef std::pair BarPair; +/// +typedef std::pair ColorPair; + +/// +std::vector const getFamilyData(); +/// +std::vector const getSeriesData(); +/// +std::vector const getShapeData(); +/// +std::vector const getSizeData(); +/// +std::vector const getBarData(); +/// +std::vector const getColorData(); + +} // namespace frontend +} // namespace lyx + +#endif // CHARACTERHELPERS +// -*- C++ -*- +/** + * \file frnt_lang.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Angus Leeming + * + * Full author contact details are available in file CREDITS. + * + * Ease the use of internationalised language strings in the dialogs. + */ + +#ifndef FRNT_LANG_H +#define FRNT_LANG_H + +#include "support/docstring.h" + +#include +#include + +namespace lyx { +namespace frontend { + +/// +typedef std::pair LanguagePair; + +/** If the caller is the character dialog, add "No change" and "Reset" + * to the vector. + */ +std::vector const getLanguageData(bool character_dlg); + +} // namespace frontend +} // namespace lyx + +#endif // FRNT_LANG_H +// -*- C++ -*- +/** + * \file helper_funcs.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Angus Leeming + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef HELPERFUNCS_H +#define HELPERFUNCS_H + +#include "support/docstring.h" + +#include +#include +#include +#include +#include + + +namespace lyx { + +namespace support { class FileFilterList; } + + +namespace frontend { + +/** Launch a file dialog and return the chosen file. + filename: a suggested filename. + title: the title of the dialog. + pattern: *.ps etc. + dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog. +*/ +docstring const +browseFile(docstring const & filename, + docstring const & title, + support::FileFilterList const & filters, + bool save = false, + std::pair const & dir1 = + std::make_pair(docstring(), docstring()), + std::pair const & dir2 = + std::make_pair(docstring(), docstring())); + + +/** Wrapper around browseFile which tries to provide a filename + relative to relpath. If the relative path is of the form "foo.txt" + or "bar/foo.txt", then it is returned as relative. OTOH, if it is + of the form "../baz/foo.txt", an absolute path is returned. This is + intended to be useful for insets which encapsulate files/ +*/ +docstring const +browseRelFile(docstring const & filename, + docstring const & refpath, + docstring const & title, + support::FileFilterList const & filters, + bool save = false, + std::pair const & dir1 = + std::make_pair(docstring(), docstring()), + std::pair const & dir2 = + std::make_pair(docstring(), docstring())); + + +/** Wrapper around browseFile which tries to provide a filename + * relative to the user or system directory. The dir, name and ext + * parameters have the same meaning as in the + * support::LibFileSearch function. + */ +docstring const +browseLibFile(docstring const & dir, + docstring const & name, + docstring const & ext, + docstring const & title, + support::FileFilterList const & filters); + + +/** Launch a file dialog and return the chosen directory. + pathname: a suggested pathname. + title: the title of the dialog. + dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog. +*/ +docstring const +browseDir(docstring const & pathname, + docstring const & title, + std::pair const & dir1 = + std::make_pair(docstring(), docstring()), + std::pair const & dir2 = + std::make_pair(docstring(), docstring())); + + +/// Returns a vector of units that can be used to create a valid LaTeX length. +std::vector const getLatexUnits(); + + +/** Functions to extract vectors of the first and second elems from a + vector > +*/ +template +std::vector const +getFirst(std::vector const & pr) +{ + std::vector tmp(pr.size()); + std::transform(pr.begin(), pr.end(), tmp.begin(), + boost::bind(&Pair::first, _1)); + return tmp; +} + +template +std::vector const +getSecond(std::vector const & pr) +{ + std::vector tmp(pr.size()); + std::transform(pr.begin(), pr.end(), tmp.begin(), + boost::bind(&Pair::second, _1)); + return tmp; +} + +} // namespace frontend +} // namespace lyx + +#endif // NOT HELPERFUNCS_H +// -*- C++ -*- +/** + * \file tex_helpers.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Herbert Voß + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef TEX_HELPERS_H +#define TEX_HELPERS_H + +#include +#include + +namespace lyx { +namespace frontend { + +/** Build filelists of all availabe bst/cls/sty-files. Done through + * kpsewhich and an external script, saved in *Files.lst. + */ +void rescanTexStyles(); + +/// rebuild the textree +void texhash(); + +/** Fill \c contents from one of the three texfiles. + * Each entry in the file list is returned as a name_with_path + */ +void getTexFileList(std::string const & filename, std::vector & contents); + +/// get the options of stylefile +std::string const getListOfOptions(std::string const & classname, std::string const & type); + +/// get a class with full path from the list +std::string const getTexFileFromList(std::string const & classname, std::string const & type); + +} // namespace frontend +} // namespace lyx + +#endif // TEX_HELPERS_H diff --git a/src/frontends/controllers/helper_funcs.C b/src/frontends/controllers/helper_funcs.C deleted file mode 100644 index 20006707f1..0000000000 --- a/src/frontends/controllers/helper_funcs.C +++ /dev/null @@ -1,158 +0,0 @@ -/** - * \file frontend_helpers.cpp - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Jean-Marc Lasgouttes - * \author Angus Leeming - * - * Full author contact details are available in file CREDITS. - */ - - -#include - -#include "helper_funcs.h" - -#include "gettext.h" -#include "lyxlength.h" - -#include "frontends/FileDialog.h" - -#include "support/filetools.h" -#include "support/lstrings.h" -#include "support/package.h" - -using std::pair; -using std::string; -using std::vector; - -namespace lyx { - -using support::addName; -using support::FileFilterList; -using support::getExtension; -using support::libFileSearch; -using support::makeAbsPath; -using support::makeRelPath; -using support::onlyFilename; -using support::onlyPath; -using support::package; -using support::prefixIs; -using support::removeExtension; - -namespace frontend { - - -docstring const browseFile(docstring const & filename, - docstring const & title, - FileFilterList const & filters, - bool save, - pair const & dir1, - pair const & dir2) -{ - docstring lastPath = from_ascii("."); - if (!filename.empty()) - lastPath = from_utf8(onlyPath(to_utf8(filename))); - - FileDialog fileDlg(title, LFUN_SELECT_FILE_SYNC, dir1, dir2); - - FileDialog::Result result; - - if (save) - result = fileDlg.save(lastPath, filters, - from_utf8(onlyFilename(to_utf8(filename)))); - else - result = fileDlg.open(lastPath, filters, - from_utf8(onlyFilename(to_utf8(filename)))); - - return result.second; -} - - -docstring const browseRelFile(docstring const & filename, - docstring const & refpath, - docstring const & title, - FileFilterList const & filters, - bool save, - pair const & dir1, - pair const & dir2) -{ - docstring const fname = from_utf8(makeAbsPath( - to_utf8(filename), to_utf8(refpath)).absFilename()); - - docstring const outname = browseFile(fname, title, filters, save, - dir1, dir2); - docstring const reloutname = makeRelPath(outname, refpath); - if (prefixIs(reloutname, from_ascii("../"))) - return outname; - else - return reloutname; -} - - - -docstring const browseLibFile(docstring const & dir, - docstring const & name, - docstring const & ext, - docstring const & title, - FileFilterList const & filters) -{ - // FIXME UNICODE - pair const dir1(_("System files|#S#s"), - from_utf8(addName(package().system_support().absFilename(), to_utf8(dir)))); - - pair const dir2(_("User files|#U#u"), - from_utf8(addName(package().user_support().absFilename(), to_utf8(dir)))); - - docstring const result = browseFile(from_utf8( - libFileSearch(to_utf8(dir), to_utf8(name), to_utf8(ext)).absFilename()), - title, filters, false, dir1, dir2); - - // remove the extension if it is the default one - docstring noextresult; - if (from_utf8(getExtension(to_utf8(result))) == ext) - noextresult = from_utf8(removeExtension(to_utf8(result))); - else - noextresult = result; - - // remove the directory, if it is the default one - docstring const file = from_utf8(onlyFilename(to_utf8(noextresult))); - if (from_utf8(libFileSearch(to_utf8(dir), to_utf8(file), to_utf8(ext)).absFilename()) == result) - return file; - else - return noextresult; -} - - -docstring const browseDir(docstring const & pathname, - docstring const & title, - pair const & dir1, - pair const & dir2) -{ - docstring lastPath = from_ascii("."); - if (!pathname.empty()) - lastPath = from_utf8(onlyPath(to_utf8(pathname))); - - FileDialog fileDlg(title, LFUN_SELECT_FILE_SYNC, dir1, dir2); - - FileDialog::Result const result = - fileDlg.opendir(lastPath, from_utf8(onlyFilename(to_utf8(pathname)))); - - return result.second; -} - - -vector const getLatexUnits() -{ - vector units; - int i = 0; - char const * str = stringFromUnit(i); - for (; str != 0; ++i, str = stringFromUnit(i)) - units.push_back(from_ascii(str)); - - return units; -} - -} // namespace frontend -} // namespace lyx diff --git a/src/frontends/controllers/helper_funcs.h b/src/frontends/controllers/helper_funcs.h deleted file mode 100644 index 68f88b81c6..0000000000 --- a/src/frontends/controllers/helper_funcs.h +++ /dev/null @@ -1,123 +0,0 @@ -// -*- C++ -*- -/** - * \file helper_funcs.h - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Angus Leeming - * - * Full author contact details are available in file CREDITS. - */ - -#ifndef HELPERFUNCS_H -#define HELPERFUNCS_H - -#include "support/docstring.h" - -#include -#include -#include -#include -#include - - -namespace lyx { - -namespace support { class FileFilterList; } - - -namespace frontend { - -/** Launch a file dialog and return the chosen file. - filename: a suggested filename. - title: the title of the dialog. - pattern: *.ps etc. - dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog. -*/ -docstring const -browseFile(docstring const & filename, - docstring const & title, - support::FileFilterList const & filters, - bool save = false, - std::pair const & dir1 = - std::make_pair(docstring(), docstring()), - std::pair const & dir2 = - std::make_pair(docstring(), docstring())); - - -/** Wrapper around browseFile which tries to provide a filename - relative to relpath. If the relative path is of the form "foo.txt" - or "bar/foo.txt", then it is returned as relative. OTOH, if it is - of the form "../baz/foo.txt", an absolute path is returned. This is - intended to be useful for insets which encapsulate files/ -*/ -docstring const -browseRelFile(docstring const & filename, - docstring const & refpath, - docstring const & title, - support::FileFilterList const & filters, - bool save = false, - std::pair const & dir1 = - std::make_pair(docstring(), docstring()), - std::pair const & dir2 = - std::make_pair(docstring(), docstring())); - - -/** Wrapper around browseFile which tries to provide a filename - * relative to the user or system directory. The dir, name and ext - * parameters have the same meaning as in the - * support::LibFileSearch function. - */ -docstring const -browseLibFile(docstring const & dir, - docstring const & name, - docstring const & ext, - docstring const & title, - support::FileFilterList const & filters); - - -/** Launch a file dialog and return the chosen directory. - pathname: a suggested pathname. - title: the title of the dialog. - dir1 = (name, dir), dir2 = (name, dir): extra buttons on the dialog. -*/ -docstring const -browseDir(docstring const & pathname, - docstring const & title, - std::pair const & dir1 = - std::make_pair(docstring(), docstring()), - std::pair const & dir2 = - std::make_pair(docstring(), docstring())); - - -/// Returns a vector of units that can be used to create a valid LaTeX length. -std::vector const getLatexUnits(); - - -/** Functions to extract vectors of the first and second elems from a - vector > -*/ -template -std::vector const -getFirst(std::vector const & pr) -{ - std::vector tmp(pr.size()); - std::transform(pr.begin(), pr.end(), tmp.begin(), - boost::bind(&Pair::first, _1)); - return tmp; -} - -template -std::vector const -getSecond(std::vector const & pr) -{ - std::vector tmp(pr.size()); - std::transform(pr.begin(), pr.end(), tmp.begin(), - boost::bind(&Pair::second, _1)); - return tmp; -} - -} // namespace frontend -} // namespace lyx - -#endif // NOT HELPERFUNCS_H diff --git a/src/frontends/controllers/tex_helpers.C b/src/frontends/controllers/tex_helpers.C deleted file mode 100644 index aba85a1d7a..0000000000 --- a/src/frontends/controllers/tex_helpers.C +++ /dev/null @@ -1,165 +0,0 @@ -/** - * \file frontend_helpers.cpp - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Herbert Voß - * - * Full author contact details are available in file CREDITS. - */ - -#include - -#include "tex_helpers.h" - -#include "debug.h" -#include "gettext.h" - -#include "frontends/Alert.h" - -#include "support/filetools.h" -#include "support/lstrings.h" -#include "support/lyxalgo.h" -#include "support/os.h" -#include "support/package.h" -#include "support/path.h" -#include "support/systemcall.h" - -#include -#include - -using std::string; -using std::endl; - -namespace lyx { - -using support::bformat; -using support::contains; -using support::FileName; -using support::getExtension; -using support::getFileContents; -using support::getVectorFromString; -using support::libFileSearch; -using support::onlyFilename; -using support::package; -using support::quoteName; -using support::split; -using support::Systemcall; -using support::token; - -namespace frontend { - -void rescanTexStyles() -{ - // Run rescan in user lyx directory - support::Path p(package().user_support()); - FileName const command = libFileSearch("scripts", "TeXFiles.py"); - Systemcall one; - int const status = one.startscript(Systemcall::Wait, - lyx::support::os::python() + ' ' + - quoteName(command.toFilesystemEncoding())); - if (status == 0) - return; - // FIXME UNICODE - Alert::error(_("Could not update TeX information"), - bformat(_("The script `%s' failed."), lyx::from_utf8(command.absFilename()))); -} - - -void texhash() -{ - // Run texhash in user lyx directory - support::Path p(package().user_support()); - - //path to texhash through system - Systemcall one; - one.startscript(Systemcall::Wait,"texhash"); -} - - -void getTexFileList(string const & filename, std::vector & list) -{ - list.clear(); - FileName const file = libFileSearch("", filename); - if (file.empty()) - return; - - list = getVectorFromString(getFileContents(file), "\n"); - - // Normalise paths like /foo//bar ==> /foo/bar - boost::RegEx regex("/{2,}"); - std::vector::iterator it = list.begin(); - std::vector::iterator end = list.end(); - for (; it != end; ++it) { - *it = regex.Merge((*it), "/"); - } - - // remove empty items and duplicates - list.erase(std::remove(list.begin(), list.end(), ""), list.end()); - eliminate_duplicates(list); -} - - -string const getListOfOptions(string const & classname, string const & type) -{ - FileName const filename(getTexFileFromList(classname, type)); - if (filename.empty()) - return string(); - string optionList = string(); - std::ifstream is(filename.toFilesystemEncoding().c_str()); - while (is) { - string s; - is >> s; - if (contains(s,"DeclareOption")) { - s = s.substr(s.find("DeclareOption")); - s = split(s,'{'); // cut front - s = token(s,'}',0); // cut end - optionList += (s + '\n'); - } - } - return optionList; -} - - -string const getTexFileFromList(string const & file, - string const & type) -{ - string file_ = file; - // do we need to add the suffix? - if (!(getExtension(file) == type)) - file_ += '.' + type; - - lyxerr << "Searching for file " << file_ << endl; - - string lstfile; - if (type == "cls") - lstfile = "clsFiles.lst"; - else if (type == "sty") - lstfile = "styFiles.lst"; - else if (type == "bst") - lstfile = "bstFiles.lst"; - else if (type == "bib") - lstfile = "bibFiles.lst"; - FileName const abslstfile = libFileSearch(string(), lstfile); - if (abslstfile.empty()) { - lyxerr << "File `'" << lstfile << "' not found." << endl; - return string(); - } - string const allClasses = getFileContents(abslstfile); - int entries = 0; - string classfile = token(allClasses, '\n', entries); - int count = 0; - while ((!contains(classfile, file) || - (onlyFilename(classfile) != file)) && - (++count < 1000)) { - classfile = token(allClasses, '\n', ++entries); - } - - // now we have filename with full path - lyxerr << "with full path: " << classfile << endl; - - return classfile; -} - -} // namespace frontend -} // namespace lyx diff --git a/src/frontends/controllers/tex_helpers.h b/src/frontends/controllers/tex_helpers.h deleted file mode 100644 index 7c73328196..0000000000 --- a/src/frontends/controllers/tex_helpers.h +++ /dev/null @@ -1,43 +0,0 @@ -// -*- C++ -*- -/** - * \file tex_helpers.h - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Herbert Voß - * - * Full author contact details are available in file CREDITS. - */ - -#ifndef TEX_HELPERS_H -#define TEX_HELPERS_H - -#include -#include - -namespace lyx { -namespace frontend { - -/** Build filelists of all availabe bst/cls/sty-files. Done through - * kpsewhich and an external script, saved in *Files.lst. - */ -void rescanTexStyles(); - -/// rebuild the textree -void texhash(); - -/** Fill \c contents from one of the three texfiles. - * Each entry in the file list is returned as a name_with_path - */ -void getTexFileList(std::string const & filename, std::vector & contents); - -/// get the options of stylefile -std::string const getListOfOptions(std::string const & classname, std::string const & type); - -/// get a class with full path from the list -std::string const getTexFileFromList(std::string const & classname, std::string const & type); - -} // namespace frontend -} // namespace lyx - -#endif // TEX_HELPERS_H