X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2Finsetcite.C;h=a8bf9a068e5a87daedc172ce1e9636476a567b06;hb=e28331ed63062dea10d0a21b9ec12034b4b17b9a;hp=579f55c1e94e93d1141655c6eacfd39485df9432;hpb=e80ad470cbc712632e53f9b2b240ce5d8dc06459;p=lyx.git diff --git a/src/insets/insetcite.C b/src/insets/insetcite.C index 579f55c1e9..a8bf9a068e 100644 --- a/src/insets/insetcite.C +++ b/src/insets/insetcite.C @@ -1,503 +1,468 @@ -#include - -#include -#include -#include +/** + * \file insetcite.C + * 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. + */ -#ifdef __GNUG__ -#pragma implementation -#endif +#include -#include FORMS_H_LOCATION #include "insetcite.h" + #include "buffer.h" +#include "bufferparams.h" #include "debug.h" -#include "lyx_gui_misc.h" -#include "BufferView.h" -#include "gettext.h" -#include "lyxtext.h" -#include "support/filetools.h" - -using std::getline; -using std::vector; -using std::pair; -using std::max; -using std::min; -using std::find; +#include "dispatchresult.h" +#include "funcrequest.h" +#include "LaTeXFeatures.h" -FD_citation_form * citation_form = 0; -FD_citation_form * create_form_citation_form(void); -void set_size_citation_form(FD_citation_form *, int, bool); +#include "frontends/controllers/biblio.h" -static vector > bibkeys_info; -static vector bibkeys; -static vector insetkeys; +#include "support/fs_extras.h" +#include "support/lstrings.h" -extern "C" void citation_cb( FL_OBJECT *, long data ) -{ - InsetCitation::Holder * holder = - static_cast(citation_form->form->u_vdata); +#include - holder->inset->callback( citation_form, - static_cast(data) ); -} +#include +#include -FD_citation_form *create_form_citation_form(void) -{ - FL_OBJECT *obj; - FD_citation_form *fdui = (FD_citation_form *) fl_calloc(1, sizeof(*fdui)); - - fdui->form = fl_bgn_form(FL_NO_BOX, 440, 790); - fdui->box = obj = fl_add_box(FL_UP_BOX,0,0,440,790,""); - fl_set_object_resize(obj, FL_RESIZE_X); - - fdui->citeBrsr = obj = - fl_add_browser(FL_HOLD_BROWSER,20,40,170,370,_("Inset keys")); - fl_set_object_lalign(obj,FL_ALIGN_TOP_LEFT); - fl_set_object_resize(obj, FL_RESIZE_X); - fl_set_object_callback(obj,citation_cb,InsetCitation::CITEBRSR); - - fdui->bibBrsr = obj = - fl_add_browser(FL_HOLD_BROWSER,250,40,170,370,_("Bibliography keys")); - fl_set_object_lalign(obj,FL_ALIGN_TOP_LEFT); - fl_set_object_resize(obj, FL_RESIZE_X); - fl_set_object_callback(obj,citation_cb,InsetCitation::BIBBRSR); - - fdui->addBtn = obj = - fl_add_button(FL_NORMAL_BUTTON,200,40,40,40,"@4->"); - fl_set_object_gravity(obj, FL_South, FL_South); - fl_set_object_resize(obj, FL_RESIZE_NONE); - fl_set_object_callback(obj,citation_cb,InsetCitation::ADD); - - fdui->delBtn = obj = - fl_add_button(FL_NORMAL_BUTTON,200,90,40,40,"@9+"); - fl_set_object_gravity(obj, FL_South, FL_South); - fl_set_object_resize(obj, FL_RESIZE_NONE); - fl_set_object_callback(obj,citation_cb,InsetCitation::DELETE); - - fdui->upBtn = obj = - fl_add_button(FL_NORMAL_BUTTON,200,140,40,40,"@8->"); - fl_set_object_gravity(obj, FL_South, FL_South); - fl_set_object_resize(obj, FL_RESIZE_NONE); - fl_set_object_callback(obj,citation_cb,InsetCitation::UP); - - fdui->downBtn = obj = - fl_add_button(FL_NORMAL_BUTTON,200,190,40,40,"@2->"); - fl_set_object_gravity(obj, FL_South, FL_South); - fl_set_object_resize(obj, FL_RESIZE_NONE); - fl_set_object_callback(obj,citation_cb,InsetCitation::DOWN); - - fdui->infoBrsr = obj = - fl_add_browser(FL_NORMAL_BROWSER,20,440,400,110,_("Info")); - fl_set_object_lalign(obj,FL_ALIGN_TOP_LEFT); - fl_set_object_resize(obj, FL_RESIZE_X); - - /* - fdui->style = obj = - fl_add_choice(FL_NORMAL_CHOICE,160,570,130,30,_("Citation style")); - fl_set_object_boxtype(obj,FL_DOWN_BOX); - fl_set_object_resize(obj, FL_RESIZE_X); - - fdui->textBefore = obj = - fl_add_input(FL_NORMAL_INPUT,100,620,250,30,_("Text before")); - fl_set_object_resize(obj, FL_RESIZE_X); - */ - - fdui->textAftr = obj = - fl_add_input(FL_NORMAL_INPUT,100,660,250,30,_("Text after")); - fl_set_object_gravity(obj, FL_SouthWest, FL_SouthEast); - fl_set_object_resize(obj, FL_RESIZE_X); - - fdui->ok = obj = - fl_add_button(FL_RETURN_BUTTON,190,730,110,40,_("OK")); - fl_set_object_gravity(obj, FL_SouthEast, FL_SouthEast); - fl_set_object_callback(obj,citation_cb,InsetCitation::OK); - - fdui->cancel = obj = - fl_add_button(FL_NORMAL_BUTTON,310,730,110,40,idex(_("Cancel|^["))); - fl_set_button_shortcut(obj, scex(_("Cancel|^[")), 1); - fl_set_object_gravity(obj, FL_SouthEast, FL_SouthEast); - fl_set_object_callback(obj,citation_cb,InsetCitation::CANCEL); - - fl_end_form(); - - return fdui; -} +namespace lyx { +using support::ascii_lowercase; +using support::contains; +using support::FileName; +using support::getStringFromVector; +using support::getVectorFromString; +using support::ltrim; +using support::rtrim; +using support::split; +using support::tokenPos; -InsetCitation::InsetCitation(string const & key, string const & note) - : InsetCommand("cite", key, note) -{ -} +using std::endl; +using std::replace; +using std::string; +using std::ostream; +using std::vector; +using std::map; +namespace fs = boost::filesystem; -InsetCitation::~InsetCitation() -{ - if(citation_form && citation_form->form - && citation_form->form->visible - && citation_form->form->u_vdata == &holder) - fl_hide_form(citation_form->form); -} +namespace { -void InsetCitation::Edit( BufferView * bv, int, int, unsigned int ) +docstring const getNatbibLabel(Buffer const & buffer, + string const & citeType, string const & keyList, + docstring const & before, docstring const & after, + biblio::CiteEngine engine) { - if ( !citation_form ) { - citation_form = create_form_citation_form(); - fl_set_form_atclose( citation_form->form, - CancelCloseBoxCB, 0 ); + // Only start the process off after the buffer is loaded from file. + if (!buffer.fully_loaded()) + return docstring(); + + // Cache the labels + typedef std::map CachedMap; + static CachedMap cached_keys; + + // and cache the timestamp of the bibliography files. + static std::map bibfileStatus; + + biblio::InfoMap infomap; + + vector const & bibfilesCache = buffer.getBibfilesCache(); + // compare the cached timestamps with the actual ones. + bool changed = false; + for (vector::const_iterator it = bibfilesCache.begin(); + it != bibfilesCache.end(); ++ it) { + FileName const f = *it; + try { + std::time_t lastw = fs::last_write_time(f.toFilesystemEncoding()); + if (lastw != bibfileStatus[f]) { + changed = true; + bibfileStatus[f] = lastw; + } + } + catch (fs::filesystem_error & fserr) { + changed = true; + lyxerr << "Couldn't find or read bibtex file " + << f << endl; + lyxerr[Debug::DEBUG] << "Fs error: " + << fserr.what() << endl; + } } - holder.inset = this; - holder.view = bv; - - citation_form->form->u_vdata = &holder; - - // update the browsers, noting the number of keys. - bibkeys_info = bv->buffer()->getBibkeyList(); - bibkeys.clear(); - insetkeys.clear(); - for( unsigned int i = 0; i < bibkeys_info.size(); ++i ) - bibkeys.push_back(bibkeys_info[i].first); - - string tmp; - string keys = getContents(); - keys = frontStrip( split(keys, tmp, ',') ); - while( !tmp.empty() ) { - insetkeys.push_back( tmp ); - keys = frontStrip( split(keys, tmp, ',') ); + // build the keylist only if the bibfiles have been changed + if (cached_keys[&buffer].empty() || bibfileStatus.empty() || changed) { + typedef vector > InfoType; + InfoType bibkeys; + buffer.fillWithBibKeys(bibkeys); + + InfoType::const_iterator bit = bibkeys.begin(); + InfoType::const_iterator bend = bibkeys.end(); + + for (; bit != bend; ++bit) + infomap[bit->first] = bit->second; + + cached_keys[&buffer] = infomap; + } else + // use the cached keys + infomap = cached_keys[&buffer]; + + if (infomap.empty()) + return docstring(); + + // the natbib citation-styles + // CITET: author (year) + // CITEP: (author,year) + // CITEALT: author year + // CITEALP: author, year + // CITEAUTHOR: author + // CITEYEAR: year + // CITEYEARPAR: (year) + // jurabib supports these plus + // CITE: author/ + + // We don't currently use the full or forceUCase fields. + string cite_type = biblio::asValidLatexCommand(citeType, engine); + if (cite_type[0] == 'C') + cite_type = string(1, 'c') + cite_type.substr(1); + if (cite_type[cite_type.size() - 1] == '*') + cite_type = cite_type.substr(0, cite_type.size() - 1); + + docstring before_str; + if (!before.empty()) { + // In CITET and CITEALT mode, the "before" string is + // attached to the label associated with each and every key. + // In CITEP, CITEALP and CITEYEARPAR mode, it is attached + // to the front of the whole only. + // In other modes, it is not used at all. + if (cite_type == "citet" || + cite_type == "citealt" || + cite_type == "citep" || + cite_type == "citealp" || + cite_type == "citeyearpar") + before_str = before + ' '; + // In CITE (jurabib), the "before" string is used to attach + // the annotator (of legal texts) to the author(s) of the + // first reference. + else if (cite_type == "cite") + before_str = '/' + before; } - updateBrowser( citation_form->bibBrsr, bibkeys ); - updateBrowser( citation_form->citeBrsr, insetkeys ); - fl_clear_browser( citation_form->infoBrsr ); - - // No keys have been selected yet, so... - setBibButtons( citation_form, OFF ); - setCiteButtons( citation_form, OFF ); - - int noKeys = max( bibkeys.size(), insetkeys.size() ); - - // Place bounds, so that 4 <= noKeys <= 15 - noKeys = max( 4, min(15, noKeys) ); - - // Re-size the form to accommodate the new browser size - int size = 20 * noKeys; - bool bibPresent = ( bibkeys.size() > 0 ); - setSize(citation_form, size, bibPresent); - - fl_set_input( citation_form->textAftr, getOptions().c_str() ); - if( holder.view->buffer()->isReadonly() ) - fl_deactivate_object( citation_form->textAftr ); - - if( citation_form->form->visible ) { - fl_raise_form( citation_form->form ); - } else { - fl_show_form(citation_form->form, - FL_PLACE_MOUSE | FL_FREE_SIZE, - FL_FULLBORDER, - _("Citation") ); + docstring after_str; + if (!after.empty()) { + // The "after" key is appended only to the end of the whole. + after_str = ", " + after; } -} - - -void InsetCitation::updateBrowser( FL_OBJECT * browser, - vector const & inkeys ) const -{ - fl_clear_browser( browser ); - fl_freeze_form( browser->form ); - for( unsigned int i = 0; i < inkeys.size(); ++i ) - fl_add_browser_line( browser, inkeys[i].c_str() ); - fl_unfreeze_form( browser->form ); -} - -void InsetCitation::callback( FD_citation_form * form, State cb ) -{ - switch( cb ) { - case BIBBRSR: { - fl_deselect_browser( form->citeBrsr ); - - unsigned int sel = fl_get_browser( form->bibBrsr ); - if( sel < 1 || sel > bibkeys.size() ) break; - - // Put into infoBrsr the additional info associated with - // the selected bibBrsr key - fl_clear_browser( form->infoBrsr ); - fl_add_browser_line( form->infoBrsr, - bibkeys_info[sel-1].second.c_str() ); - - // Highlight the selected bibBrsr key in citeBrsr if present - vector::iterator it = - find( insetkeys.begin(), insetkeys.end(), bibkeys[sel-1] ); - - if( it != insetkeys.end() ) { - int n = it - insetkeys.begin(); - fl_select_browser_line( form->citeBrsr, n+1 ); - fl_set_browser_topline( form->citeBrsr, n+1 ); - } + // One day, these might be tunable (as they are in BibTeX). + char const op = '('; // opening parenthesis. + char const cp = ')'; // closing parenthesis. + // puctuation mark separating citation entries. + char const * const sep = ";"; + + docstring const op_str(' ' + docstring(1, op)); + docstring const cp_str(docstring(1, cp) + ' '); + docstring const sep_str(from_ascii(sep) + ' '); + + docstring label; + vector keys = getVectorFromString(keyList); + vector::const_iterator it = keys.begin(); + vector::const_iterator end = keys.end(); + for (; it != end; ++it) { + // get the bibdata corresponding to the key + docstring const author(biblio::getAbbreviatedAuthor(infomap, *it)); + docstring const year(biblio::getYear(infomap, *it)); + + // Something isn't right. Fail safely. + if (author.empty() || year.empty()) + return docstring(); + + // authors1/; ... ; + // authors_last, + if (cite_type == "cite" && engine == biblio::ENGINE_JURABIB) { + if (it == keys.begin()) + label += author + before_str + sep_str; + else + label += author + sep_str; + + // (authors1 ( year); ... ; + // authors_last ( year, ) + } else if (cite_type == "citet") { + switch (engine) { + case biblio::ENGINE_NATBIB_AUTHORYEAR: + label += author + op_str + before_str + + year + cp + sep_str; + break; + case biblio::ENGINE_NATBIB_NUMERICAL: + // FIXME UNICODE + label += author + op_str + before_str + + '#' + from_utf8(*it) + cp + sep_str; + break; + case biblio::ENGINE_JURABIB: + label += before_str + author + op_str + + year + cp + sep_str; + break; + case biblio::ENGINE_BASIC: + break; + } - if( !holder.view->buffer()->isReadonly() ) { - if( it != insetkeys.end() ) { - setBibButtons( form, OFF ); - setCiteButtons( form, ON ); + // author, year; author, year; ... + } else if (cite_type == "citep" || + cite_type == "citealp") { + if (engine == biblio::ENGINE_NATBIB_NUMERICAL) { + // FIXME UNICODE + label += from_utf8(*it) + sep_str; } else { - setBibButtons( form, ON ); - setCiteButtons( form, OFF ); + label += author + ", " + year + sep_str; + } + + // (authors1 year; + // authors_last year, ) + } else if (cite_type == "citealt") { + switch (engine) { + case biblio::ENGINE_NATBIB_AUTHORYEAR: + label += author + ' ' + before_str + + year + sep_str; + break; + case biblio::ENGINE_NATBIB_NUMERICAL: + // FIXME UNICODE + label += author + ' ' + before_str + + '#' + from_utf8(*it) + sep_str; + break; + case biblio::ENGINE_JURABIB: + label += before_str + author + ' ' + + year + sep_str; + break; + case biblio::ENGINE_BASIC: + break; } - } - break; - } case CITEBRSR: { - unsigned int sel = fl_get_browser( form->citeBrsr ); - if( sel < 1 || sel > insetkeys.size() ) break; + // author; author; ... + } else if (cite_type == "citeauthor") { + label += author + sep_str; - if( !holder.view->buffer()->isReadonly() ) { - setBibButtons( form, OFF ); - setCiteButtons( form, ON ); + // year; year; ... + } else if (cite_type == "citeyear" || + cite_type == "citeyearpar") { + label += year + sep_str; } + } + label = rtrim(rtrim(label), sep); - // Highlight the selected citeBrsr key in bibBrsr - vector::iterator it = - find( bibkeys.begin(), bibkeys.end(), insetkeys[sel-1] ); + if (!after_str.empty()) { + if (cite_type == "citet") { + // insert "after" before last ')' + label.insert(label.size() - 1, after_str); + } else { + bool const add = + !(engine == biblio::ENGINE_NATBIB_NUMERICAL && + (cite_type == "citeauthor" || + cite_type == "citeyear")); + if (add) + label += after_str; + } + } - if (it != bibkeys.end()) { - int n = it - bibkeys.begin(); - fl_select_browser_line( form->bibBrsr, n+1 ); - fl_set_browser_topline( form->bibBrsr, n+1 ); + if (!before_str.empty() && (cite_type == "citep" || + cite_type == "citealp" || + cite_type == "citeyearpar")) { + label = before_str + label; + } - // Put into infoBrsr the additional info associated with - // the selected citeBrsr key - fl_clear_browser( form->infoBrsr ); - fl_add_browser_line( form->infoBrsr, - bibkeys_info[n].second.c_str() ); - } - break; + if (cite_type == "citep" || cite_type == "citeyearpar") + label = op + label + cp; - } case ADD: { - if( holder.view->buffer()->isReadonly() ) break; + return label; +} - unsigned int sel = fl_get_browser( form->bibBrsr ); - if( sel < 1 || sel > bibkeys.size() ) break; - // Add the selected bibBrsr key to citeBrsr - fl_addto_browser( form->citeBrsr, - bibkeys[sel-1].c_str() ); - insetkeys.push_back( bibkeys[sel-1] ); +docstring const getBasicLabel(docstring const & keyList, docstring const & after) +{ + docstring keys(keyList); + docstring label; + + if (contains(keys, ',')) { + // Final comma allows while loop to cover all keys + keys = ltrim(split(keys, label, ',')) + ','; + while (contains(keys, ',')) { + docstring key; + keys = ltrim(split(keys, key, ',')); + label += ", " + key; + } + } else + label = keys; - int n = insetkeys.size(); - fl_select_browser_line( form->citeBrsr, n ); + if (!after.empty()) + label += ", " + after; - setBibButtons( form, OFF ); - setCiteButtons( form, ON ); + return '[' + label + ']'; +} - break; +} // anon namespace - } case DELETE: { - if( holder.view->buffer()->isReadonly() ) break; - unsigned int sel = fl_get_browser( form->citeBrsr ); - if( sel < 1 || sel > insetkeys.size() ) break; +InsetCitation::InsetCitation(InsetCommandParams const & p) + : InsetCommand(p, "citation") +{} - // Remove the selected key from citeBrsr - fl_delete_browser_line( form->citeBrsr, sel ) ; - insetkeys.erase( insetkeys.begin() + sel-1 ); - setBibButtons( form, ON ); - setCiteButtons( form, OFF ); - break; +docstring const InsetCitation::generateLabel(Buffer const & buffer) const +{ + docstring const before = getParam("before"); + docstring const after = getParam("after"); + + docstring label; + biblio::CiteEngine const engine = buffer.params().cite_engine; + if (engine != biblio::ENGINE_BASIC) { + // FIXME UNICODE + label = getNatbibLabel(buffer, getCmdName(), to_utf8(getParam("key")), + before, after, engine); + } - } case UP: { - if( holder.view->buffer()->isReadonly() ) break; + // Fallback to fail-safe + if (label.empty()) { + label = getBasicLabel(getParam("key"), after); + } - unsigned int sel = fl_get_browser( form->citeBrsr ); - if( sel < 2 || sel > insetkeys.size() ) break; + return label; +} - // Move the selected key up one line - vector::iterator it = insetkeys.begin() + sel-1; - string tmp = *it; - fl_delete_browser_line( form->citeBrsr, sel ); - insetkeys.erase( it ); +docstring const InsetCitation::getScreenLabel(Buffer const & buffer) const +{ + biblio::CiteEngine const engine = biblio::getEngine(buffer); + if (cache.params == params() && cache.engine == engine) + return cache.screen_label; - fl_insert_browser_line( form->citeBrsr, sel-1, tmp.c_str() ); - fl_select_browser_line( form->citeBrsr, sel-1 ); - insetkeys.insert( it-1, tmp ); - setCiteButtons( form, ON ); + // The label has changed, so we have to re-create it. + string const before = getSecOptions(); + string const after = getOptions(); - break; + docstring const glabel = generateLabel(buffer); - } case DOWN: { - if( holder.view->buffer()->isReadonly() ) break; + unsigned int const maxLabelChars = 45; - unsigned int sel = fl_get_browser( form->citeBrsr ); - if( sel < 1 || sel > insetkeys.size()-1 ) break; + docstring label = glabel; + if (label.size() > maxLabelChars) { + label.erase(maxLabelChars-3); + label += "..."; + } - // Move the selected key down one line - vector::iterator it = insetkeys.begin() + sel-1; - string tmp = *it; + cache.engine = engine; + cache.params = params(); + cache.generated_label = glabel; + cache.screen_label = label; - fl_delete_browser_line( form->citeBrsr, sel ); - insetkeys.erase( it ); + return label; +} - fl_insert_browser_line( form->citeBrsr, sel+1, tmp.c_str() ); - fl_select_browser_line( form->citeBrsr, sel+1 ); - insetkeys.insert( it+1, tmp ); - setCiteButtons( form, ON ); - break; +int InsetCitation::plaintext(Buffer const & buffer, odocstream & os, + OutputParams const &) const +{ + if (cache.params == params() && + cache.engine == biblio::getEngine(buffer)) + os << cache.generated_label; + else + os << generateLabel(buffer); + return 0; +} - } case OK: { - // The inset contains a comma separated list of the keys - // in citeBrsr - if( !holder.view->buffer()->isReadonly() ) - { - string tmp; - for( unsigned int i = 0; i < insetkeys.size(); ++i ) { - if (i > 0) - tmp += ", "; - tmp += insetkeys[i]; - } - setContents( tmp ); - setOptions( fl_get_input(form->textAftr) ); - // shouldn't mark the buffer dirty unless something - // was actually altered - holder.view->updateInset( this, true ); - } - // fall through to Cancel - } case CANCEL: { - fl_hide_form( form->form ); - break; +namespace { - } default: - break; +docstring const cleanupWhitespace(docstring const & citelist) +{ + docstring::const_iterator it = citelist.begin(); + docstring::const_iterator end = citelist.end(); + // Paranoia check: make sure that there is no whitespace in here + // -- at least not behind commas or at the beginning + docstring result; + char_type last = ','; + for (; it != end; ++it) { + if (*it != ' ') + last = *it; + if (*it != ' ' || last != ',') + result += *it; } + return result; } +// end anon namyspace +} -void InsetCitation::setSize( FD_citation_form * form, - int brsrHeight, bool bibPresent ) const +int InsetCitation::docbook(Buffer const &, odocstream & os, OutputParams const &) const { - int const infoHeight = 110; - int const otherHeight = 140; - brsrHeight = max( brsrHeight, 175 ); - int formHeight = brsrHeight + otherHeight; - - if( bibPresent ) formHeight += infoHeight + 30; - fl_set_form_size( form->form, 430, formHeight ); - - // No resizing is alowed in the y-direction - fl_set_form_minsize( form->form, 430, formHeight ); - fl_set_form_maxsize( form->form, 1000, formHeight ); - - int ypos = 0; - fl_set_object_geometry( form->box, 0, ypos, 430, formHeight ); - ypos += 30; - fl_set_object_geometry( form->citeBrsr, 10, ypos, 180, brsrHeight ); - fl_set_object_geometry( form->bibBrsr, 240, ypos, 180, brsrHeight ); - fl_set_object_geometry( form->addBtn, 200, ypos, 30, 30 ); - ypos += 35; - fl_set_object_geometry( form->delBtn, 200, ypos, 30, 30 ); - ypos += 35; - fl_set_object_geometry( form->upBtn, 200, ypos, 30, 30 ); - ypos += 35; - fl_set_object_geometry( form->downBtn, 200, ypos, 30, 30 ); - - ypos = brsrHeight+30; // base of Citation/Bibliography browsers - - if( bibPresent ) { - ypos += 30; - fl_set_object_geometry( form->infoBrsr, 10, ypos, 410, infoHeight ); - fl_show_object( form->infoBrsr ); - ypos += infoHeight; - } - else - fl_hide_object( form->infoBrsr ); - - ypos += 20; - fl_set_object_geometry( form->textAftr, 100, ypos, 250, 30 ); - fl_set_object_geometry( form->ok, 230, ypos+50, 90, 30 ); - fl_set_object_geometry( form->cancel, 330, ypos+50, 90, 30 ); + os << "" + << cleanupWhitespace(getParam("key")) + << ""; + return 0; } -void InsetCitation::setBibButtons( FD_citation_form * form, State status ) const +int InsetCitation::textString(Buffer const & buf, odocstream & os, + OutputParams const & op) const { - switch (status) { - case ON: - { - fl_activate_object( form->addBtn ); - fl_set_object_lcol( form->addBtn, FL_BLACK ); - - break; - } - case OFF: - { - fl_deactivate_object( form->addBtn ); - fl_set_object_lcol( form->addBtn, FL_INACTIVE ); - } - default: - break; - } + return plaintext(buf, os, op); } -void InsetCitation::setCiteButtons( FD_citation_form * form, State status ) const +// Have to overwrite the default InsetCommand method in order to check that +// the \cite command is valid. Eg, the user has natbib enabled, inputs some +// citations and then changes his mind, turning natbib support off. The output +// should revert to \cite[]{} +int InsetCitation::latex(Buffer const & buffer, odocstream & os, + OutputParams const &) const { - switch( status ) { - case ON: - { - fl_activate_object( form->delBtn ); - fl_set_object_lcol( form->delBtn, FL_BLACK ); + biblio::CiteEngine const cite_engine = buffer.params().cite_engine; + // FIXME UNICODE + docstring const cite_str = from_utf8( + biblio::asValidLatexCommand(getCmdName(), cite_engine)); - int sel = fl_get_browser( form->citeBrsr ); + os << "\\" << cite_str; - if( sel != 1 ) { - fl_activate_object( form->upBtn ); - fl_set_object_lcol( form->upBtn, FL_BLACK ); - } else { - fl_deactivate_object( form->upBtn ); - fl_set_object_lcol( form->upBtn, FL_INACTIVE ); - } + docstring const & before = getParam("before"); + docstring const & after = getParam("after"); + if (!before.empty() && cite_engine != biblio::ENGINE_BASIC) + os << '[' << before << "][" << after << ']'; + else if (!after.empty()) + os << '[' << after << ']'; - if( sel != fl_get_browser_maxline(form->citeBrsr)) { - fl_activate_object( form->downBtn ); - fl_set_object_lcol( form->downBtn, FL_BLACK ); - } else { - fl_deactivate_object( form->downBtn ); - fl_set_object_lcol( form->downBtn, FL_INACTIVE ); - } + os << '{' << cleanupWhitespace(getParam("key")) << '}'; - break; - } - case OFF: - { - fl_deactivate_object( form->delBtn ); - fl_set_object_lcol( form->delBtn, FL_INACTIVE ); + return 0; +} - fl_deactivate_object( form->upBtn ); - fl_set_object_lcol( form->upBtn, FL_INACTIVE ); - fl_deactivate_object( form->downBtn ); - fl_set_object_lcol( form->downBtn, FL_INACTIVE ); - } - default: +void InsetCitation::validate(LaTeXFeatures & features) const +{ + switch (features.bufferParams().cite_engine) { + case biblio::ENGINE_BASIC: + break; + case biblio::ENGINE_NATBIB_AUTHORYEAR: + case biblio::ENGINE_NATBIB_NUMERICAL: + features.require("natbib"); + break; + case biblio::ENGINE_JURABIB: + features.require("jurabib"); break; } } -string InsetCitation::getScreenLabel() const +void InsetCitation::replaceContents(string const & from, string const & to) { - string temp("["); - - temp += getContents(); - - if( !getOptions().empty() ) { - temp += ", " + getOptions(); + if (tokenPos(getContents(), ',', from) != -1) { + vector items = getVectorFromString(getContents()); + replace(items.begin(), items.end(), from, to); + setContents(getStringFromVector(items)); } - - return temp + ']'; } + + +} // namespace lyx