X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2Finsetbib.C;h=03f020b745ab229dce07b2501f8aaaf4a0b1124f;hb=dbd7a961fc46bb10c85bdd8c7fb6626477ae63d8;hp=467f0bb718cc392a8727b70243cc21633ca05f33;hpb=d0950acedaa91320340af398bb06d790486a2207;p=lyx.git diff --git a/src/insets/insetbib.C b/src/insets/insetbib.C index 467f0bb718..03f020b745 100644 --- a/src/insets/insetbib.C +++ b/src/insets/insetbib.C @@ -1,239 +1,66 @@ #include -#include -using std::ifstream; - -#include - #ifdef __GNUG__ #pragma implementation #endif -#include FORMS_H_LOCATION #include "insetbib.h" -#include "combox.h" #include "buffer.h" #include "debug.h" -#include "lyx_gui_misc.h" #include "BufferView.h" #include "gettext.h" -#include "bibforms.h" #include "lyxtext.h" -#include "support/filetools.h" - -using std::ostream; -using std::endl; - -extern BufferView * current_view; - -FD_citation_form * citation_form = 0; -FD_bibitem_form * bibitem_form = 0; -static Combox * bibcombox = 0; - -void BibitemUpdate(Combox *); -FD_citation_form * create_form_citation_form(void); -FD_bibitem_form * create_form_bibitem_form(void); - - -extern "C" void bibitem_cb(FL_OBJECT *, long data) -{ - switch (data) { - case 1: // OK, citation - { - InsetCitation::Holder * holder = - static_cast - (citation_form->citation_form->u_vdata); - if(!holder->view->buffer()->isReadonly()) { - - InsetCitation * inset = holder->inset; - inset->setContents(bibcombox->getline()); - inset->setOptions(fl_get_input(citation_form->label)); - fl_hide_form(citation_form->citation_form); - // shouldn't mark the buffer dirty unless something - // was actually altered - holder->view->updateInset(inset, true); - break; - } - // fall through to Cancel on RO-mode - } - case 0: fl_hide_form(citation_form->citation_form); - break; - case 3: // OK, bibitem - { - InsetBibKey::Holder * holder = - static_cast - (bibitem_form->bibitem_form->u_vdata); - - if(!holder->view->buffer()->isReadonly()) { - InsetBibKey * inset = holder->inset; - inset->setContents(fl_get_input(bibitem_form->key)); - inset->setOptions(fl_get_input(bibitem_form->label)); - fl_hide_form(bibitem_form->bibitem_form); - // Does look like a hack? It is! (but will change at 0.13) - holder->view->text->RedoParagraph(); - holder->view->update(1); - break; - } // fall through to Cancel on RO-mode - } - case 2: // Cancel, bibitem - fl_hide_form(bibitem_form->bibitem_form); // Cancel, bibitem - break; - } -} - - -FD_citation_form * create_form_citation_form(void) -{ - FL_OBJECT * obj; - FD_citation_form * fdui = (FD_citation_form *) fl_calloc(1, sizeof(FD_citation_form)); - - fdui->citation_form = fl_bgn_form(FL_NO_BOX, 220, 130); - obj = fl_add_box(FL_UP_BOX, 0, 0, 220, 130, ""); - fdui->key = obj = fl_add_text(FL_NORMAL_TEXT, 20, 10, 60, 30, _("Key:")); - fl_set_object_lsize(obj, FL_NORMAL_SIZE); - fl_set_object_lalign(obj, FL_ALIGN_RIGHT); - - bibcombox = new Combox(FL_COMBOX_INPUT); - bibcombox->add(80, 10, 130, 30, 300); - - obj = fl_add_button(FL_RETURN_BUTTON, 20, 90, 90, 30, _("OK")); - fl_set_object_lsize(obj, FL_NORMAL_SIZE); - fl_set_object_callback(obj, bibitem_cb, 1); - obj = fl_add_button(FL_NORMAL_BUTTON, 120, 90, 90, 30, idex(_("Cancel|^["))); - fl_set_button_shortcut(obj, scex(_("Cancel|^[")), 1); - fl_set_object_lsize(obj, FL_NORMAL_SIZE); - fl_set_object_callback(obj, bibitem_cb, 0); - fdui->label = obj = fl_add_input(FL_NORMAL_INPUT, 80, 50, 130, 30, idex(_("Remark:|#R"))); - fl_set_input_shortcut(obj, scex(_("Remark:|#R")), 1); - fl_set_object_lsize(obj, FL_NORMAL_SIZE); - fl_end_form(); - - //fdui->citation_form->fdui = fdui; - - return fdui; -} -/*---------------------------------------*/ - -FD_bibitem_form * create_form_bibitem_form(void) -{ - FL_OBJECT * obj; - FD_bibitem_form * fdui = (FD_bibitem_form *) fl_calloc(1, sizeof(FD_bibitem_form)); - - fdui->bibitem_form = fl_bgn_form(FL_NO_BOX, 220, 130); - obj = fl_add_box(FL_UP_BOX, 0, 0, 220, 130, ""); - fdui->key = obj = fl_add_input(FL_NORMAL_INPUT, 80, 10, 130, 30, idex(_("Key:|#K"))); - fl_set_input_shortcut(obj, scex(_("Key:|#K")), 1); - fl_set_object_lsize(obj, FL_NORMAL_SIZE); - obj = fl_add_button(FL_RETURN_BUTTON, 20, 90, 90, 30, _("OK")); - fl_set_object_lsize(obj, FL_NORMAL_SIZE); - fl_set_object_callback(obj, bibitem_cb, 3); - obj = fl_add_button(FL_NORMAL_BUTTON, 120, 90, 90, 30, idex(_("Cancel|^["))); - fl_set_button_shortcut(obj, scex(_("Cancel|^[")), 1); - fl_set_object_lsize(obj, FL_NORMAL_SIZE); - fl_set_object_callback(obj, bibitem_cb, 2); - fdui->label = obj = fl_add_input(FL_NORMAL_INPUT, 80, 50, 130, 30, idex(_("Label:|#L"))); - fl_set_input_shortcut(obj, scex(_("Label:|#L")), 1); - fl_set_object_lsize(obj, FL_NORMAL_SIZE); - fl_end_form(); - - //fdui->bibitem_form->fdui = fdui; - - return fdui; -} -/*---------------------------------------*/ - - -InsetCitation::InsetCitation(string const & key, string const & note) - : InsetCommand("cite", key, note) -{ - -} +#include "lyxrc.h" +#include "font.h" +#include "LyXView.h" +#include "lyxtextclasslist.h" +#include "frontends/Dialogs.h" -InsetCitation::~InsetCitation() -{ - if(citation_form && citation_form->citation_form - && citation_form->citation_form->visible - && citation_form->citation_form->u_vdata == &holder) - fl_hide_form(citation_form->citation_form); -} - - -void InsetCitation::Edit(BufferView * bv, int, int, unsigned int) -{ - if(bv->buffer()->isReadonly()) - WarnReadonly(bv->buffer()->fileName()); +#include "support/filetools.h" +#include "support/path.h" +#include "support/os.h" +#include "support/lstrings.h" +#include "support/LAssert.h" - if (!citation_form) { - citation_form = create_form_citation_form(); - fl_set_form_atclose(citation_form->citation_form, - CancelCloseBoxCB, 0); - } +#include +#include - holder.inset = this; - holder.view = bv; - - citation_form->citation_form->u_vdata = &holder; - - BibitemUpdate(bibcombox); - if (!bibcombox->select_text(getContents().c_str())) - bibcombox->addline(getContents().c_str()); - - fl_set_input(citation_form->label, getOptions().c_str()); - if (citation_form->citation_form->visible) { - fl_raise_form(citation_form->citation_form); - } else { - fl_show_form(citation_form->citation_form, - FL_PLACE_MOUSE, FL_FULLBORDER, - _("Citation")); - } -} +using std::ostream; +using std::ifstream; +using std::getline; +using std::endl; +using std::vector; +using std::pair; +using std::max; +int InsetBibKey::key_counter = 0; +const string key_prefix = "key-"; -string InsetCitation::getScreenLabel() const +InsetBibKey::InsetBibKey(InsetCommandParams const & p) + : InsetCommand(p), counter(1) { - string temp("["); - - temp += contents; - - if (!options.empty()) { - temp += ", " + options; - } - - return temp + ']'; + if (getContents().empty()) + setContents(key_prefix + tostr(++key_counter)); } -InsetBibKey::InsetBibKey(string const & key, string const & label): - InsetCommand("bibitem", key, label) +InsetBibKey::~InsetBibKey() { - counter = 1; - if (key.empty()) - contents = ' '; } -InsetBibKey::InsetBibKey(InsetBibKey const * b): - InsetCommand("bibitem", b->contents, b->options) +Inset * InsetBibKey::clone(Buffer const &, bool) const { - counter = b->counter; + InsetBibKey * b = new InsetBibKey(params()); + b->setCounter(counter); + return b; } -InsetBibKey::~InsetBibKey() -{ - if(bibitem_form && bibitem_form->bibitem_form - && bibitem_form->bibitem_form->visible - && bibitem_form->bibitem_form->u_vdata == &holder) - fl_hide_form(bibitem_form->bibitem_form); -} - void InsetBibKey::setCounter(int c) { counter = c; - - if (contents.empty()) - contents += tostr(counter); } @@ -241,214 +68,234 @@ void InsetBibKey::setCounter(int c) // as a LyX 2.x command, and lyxlex is not enough smart to understand // real LaTeX commands. Yes, that could be fixed, but would be a waste // of time cause LyX3 won't use lyxlex anyway. (ale) -void InsetBibKey::Write(ostream & os) const +void InsetBibKey::write(Buffer const *, ostream & os) const { os << "\\bibitem "; - if (!options.empty()) { + if (! getOptions().empty()) { os << '[' - << options << ']'; + << getOptions() << ']'; } os << '{' - << contents << "}\n"; + << getContents() << "}\n"; } -string InsetBibKey::getScreenLabel() const +// This is necessary here because this is written without begin_inset +// This should be changed!!! (Jug) +void InsetBibKey::read(Buffer const *, LyXLex & lex) { - if (!options.empty()) - return options; - - return tostr(counter); -} + if (lex.eatLine()) { + string const token = lex.getString(); + scanCommand(token); + } else { + lex.printError("InsetCommand: Parse error: `$$Token'"); + } + if (prefixIs(getContents(), key_prefix)) { + int key = strToInt(getContents().substr(key_prefix.length())); + key_counter = max(key_counter, key); + } +} -/* - The value in "Key:" isn't allways set right after a few bibkey insets have - been added/removed. Perhaps the wrong object is deleted/used somewhere - upwards? - (Joacim 1998-03-04) -*/ -void InsetBibKey::Edit(BufferView * bv, int, int, unsigned int) +string const InsetBibKey::getBibLabel() const { - if(bv->buffer()->isReadonly()) - WarnReadonly(bv->buffer()->fileName()); - - if (!bibitem_form) { - bibitem_form = create_form_bibitem_form(); - fl_set_form_atclose(bibitem_form->bibitem_form, - CancelCloseBoxCB, 0); - } + if (! getOptions().empty()) + return getOptions(); + return tostr(counter); +} - holder.inset = this; - holder.view = bv; - - bibitem_form->bibitem_form->u_vdata = &holder; - // InsetBibtex uses the same form, with different labels - fl_set_object_label(bibitem_form->key, idex(_("Key:|#K"))); - fl_set_button_shortcut(bibitem_form->key, scex(_("Key:|#K")), 1); - fl_set_object_label(bibitem_form->label, idex(_("Label:|#L"))); - fl_set_button_shortcut(bibitem_form->label, scex(_("Label:|#L")), 1); - fl_set_input(bibitem_form->key, getContents().c_str()); - fl_set_input(bibitem_form->label, getOptions().c_str()); - if (bibitem_form->bibitem_form->visible) { - fl_raise_form(bibitem_form->bibitem_form); - } else { - fl_show_form(bibitem_form->bibitem_form, FL_PLACE_MOUSE, - FL_FULLBORDER, - _("Bibliography item")); - } +string const InsetBibKey::getScreenLabel(Buffer const *) const +{ + return getContents() + " [" + getBibLabel() + "]"; } +void InsetBibKey::edit(BufferView * bv, int, int, unsigned int) +{ + bv->owner()->getDialogs()->showBibitem(this); +} -InsetBibtex::InsetBibtex(string const & dbase, string const & style, - Buffer * o) - : InsetCommand("BibTeX", dbase, style), owner(o) + +void InsetBibKey::edit(BufferView * bv, bool) { + edit(bv, 0, 0, 0); } + +InsetBibtex::InsetBibtex(InsetCommandParams const & p, bool) + : InsetCommand(p) +{} + + InsetBibtex::~InsetBibtex() { - if(bibitem_form && bibitem_form->bibitem_form - && bibitem_form->bibitem_form->visible - && bibitem_form->bibitem_form->u_vdata == &holder) - fl_hide_form(bibitem_form->bibitem_form); } -string InsetBibtex::getScreenLabel() const +string const InsetBibtex::getScreenLabel(Buffer const *) const { return _("BibTeX Generated References"); } -int InsetBibtex::Latex(ostream & os, +int InsetBibtex::latex(Buffer const * buffer, ostream & os, bool /*fragile*/, bool/*fs*/) const { - // this looks like an horrible hack and it is :) The problem - // is that owner is not initialized correctly when the bib - // inset is cut and pasted. Such hacks will not be needed - // later (JMarc) - if (!owner) { - owner = current_view->buffer(); + // changing the sequence of the commands + // 1. \bibliographystyle{style} + // 2. \addcontentsline{...} - if option bibtotoc set + // 3. \bibliography{database} + string adb; + string db_in = getContents(); + db_in = split(db_in, adb, ','); + + // Style-Options + string style = getOptions(); // maybe empty! and with bibtotoc + string bibtotoc; + if (prefixIs(style,"bibtotoc")) { + bibtotoc = "bibtotoc"; + if (contains(style,',')) { + style = split(style,bibtotoc,','); + } + } + + if (!buffer->niceFile + && IsFileReadable(MakeAbsPath(style, buffer->filePath()) + ".bst")) { + style = MakeAbsPath(style, buffer->filePath()); + } + + if (!style.empty()) { // we want no \biblio...{} + os << "\\bibliographystyle{" << style << "}\n"; } + + // bibtotoc-Option + if (!bibtotoc.empty()) { + // maybe a problem when a textclass has no "art" as + // part of its name, because it's than book. + // For the "official" lyx-layouts it's no problem to support + // all well + if (!contains(textclasslist[buffer->params.textclass].name(), + "art")) { + if (buffer->params.sides == LyXTextClass::OneSide) { + // oneside + os << "\\clearpage"; + } else { + // twoside + os << "\\cleardoublepage"; + } + + // bookclass + os << "\\addcontentsline{toc}{chapter}{\\bibname}"; + + } else { + // article class + os << "\\addcontentsline{toc}{section}{\\refname}"; + } + } + + // database // If we generate in a temp dir, we might need to give an // absolute path there. This is a bit complicated since we can // have a comma-separated list of bibliographies - string adb, db_out; - string db_in = getContents(); - db_in = split(db_in, adb, ','); - while(!adb.empty()) { - if (!owner->niceFile && - IsFileReadable(MakeAbsPath(adb, owner->filepath)+".bib")) - adb = MakeAbsPath(adb, owner->filepath); + string db_out; + while (!adb.empty()) { + if (!buffer->niceFile && + IsFileReadable(MakeAbsPath(adb, buffer->filePath())+".bib")) + adb = os::external_path(MakeAbsPath(adb, buffer->filePath())); db_out += adb; db_out += ','; db_in= split(db_in, adb,','); } db_out = strip(db_out, ','); - // Idem, but simpler - string style; - if (!owner->niceFile - && IsFileReadable(MakeAbsPath(getOptions(), owner->filepath) - + ".bst")) - style = MakeAbsPath(getOptions(), owner->filepath); - else - style = getOptions(); - - os << "\\bibliographystyle{" << style << "}\n" - << "\\bibliography{" << db_out << "}\n"; + os << "\\bibliography{" << db_out << "}\n"; return 2; } -// This method returns a comma separated list of Bibtex entries -string InsetBibtex::getKeys(char delim) +vector const InsetBibtex::getFiles(Buffer const & buffer) const { - // This hack is copied from InsetBibtex::Latex. - // Is it still needed? Probably yes. - // Why is this needed here when it already is in Latex? - // Anyway we need a different way to get to the - // buffer the inset is in. (Lgb) - - //if (!owner) { - // owner = current_view->buffer(); - //} - - string tmp, keys; + // Doesn't appear to be used (Angus, 31 July 2001) + Path p(buffer.filePath()); + + vector vec; + + string tmp; string bibfiles = getContents(); bibfiles = split(bibfiles, tmp, ','); - while(!tmp.empty()) { - string fil = findtexfile(ChangeExtension(tmp, "bib", false), - "bib"); - lyxerr[Debug::LATEX] << "Bibfile: " << fil << endl; + while (!tmp.empty()) { + string file = findtexfile(ChangeExtension(tmp, "bib"), "bib"); + lyxerr[Debug::LATEX] << "Bibfile: " << file << endl; + // If we didn't find a matching file name just fail silently - if (!fil.empty()) { - // This is a _very_ simple parser for Bibtex database - // files. All it does is to look for lines starting - // in @ and not being @preamble and @string entries. - // It does NOT do any syntax checking! - ifstream ifs(fil.c_str()); - string linebuf; - while (getline(ifs, linebuf)) { - linebuf = frontStrip(linebuf); - if (prefixIs(linebuf, "@")) { - linebuf = subst(linebuf, '{', '('); - linebuf = split(linebuf, tmp, '('); - tmp = lowercase(tmp); - if (!prefixIs(tmp, "@string") - && !prefixIs(tmp, "@preamble")) { - linebuf = split(linebuf, - tmp, ','); - tmp = frontStrip(strip(tmp)); - if (!tmp.empty()) { - keys += tmp; - keys += delim; - } + if (!file.empty()) + vec.push_back(file); + + // Get next file name + bibfiles = split(bibfiles, tmp, ','); + } + + return vec; +} + +// This method returns a comma separated list of Bibtex entries +vector > const InsetBibtex::getKeys(Buffer const * buffer) const +{ + vector > keys; + + lyx::Assert(buffer); + vector const files = getFiles(*buffer); + for (vector::const_iterator it = files.begin(); + it != files.end(); ++ it) { + // This is a _very_ simple parser for Bibtex database + // files. All it does is to look for lines starting + // in @ and not being @preamble and @string entries. + // It does NOT do any syntax checking! + ifstream ifs(it->c_str()); + string linebuf0; + while (getline(ifs, linebuf0)) { + string linebuf = frontStrip(strip(linebuf0)); + if (linebuf.empty()) continue; + if (prefixIs(linebuf, "@")) { + linebuf = subst(linebuf, '{', '('); + string tmp; + linebuf = split(linebuf, tmp, '('); + tmp = lowercase(tmp); + if (!prefixIs(tmp, "@string") + && !prefixIs(tmp, "@preamble")) { + linebuf = split(linebuf, tmp, ','); + tmp = frontStrip(tmp); + if (!tmp.empty()) { + keys.push_back(pair(tmp,string())); } } + } else if (!keys.empty()) { + keys.back().second += linebuf + "\n"; } } - // Get next file name - bibfiles = split(bibfiles, tmp, ','); } return keys; } -// BibTeX should have its own dialog. This is provisional. -void InsetBibtex::Edit(BufferView * bv, int, int, unsigned int) +void InsetBibtex::edit(BufferView * bv, int, int, unsigned int) { - if (!bibitem_form) { - bibitem_form = create_form_bibitem_form(); - fl_set_form_atclose(bibitem_form->bibitem_form, - CancelCloseBoxCB, 0); - } + bv->owner()->getDialogs()->showBibtex(this); +} - holder.inset = this; - holder.view = bv; - bibitem_form->bibitem_form->u_vdata = &holder; - fl_set_object_label(bibitem_form->key, _("Database:")); - fl_set_object_label(bibitem_form->label, _("Style: ")); - fl_set_input(bibitem_form->key, getContents().c_str()); - fl_set_input(bibitem_form->label, getOptions().c_str()); - if (bibitem_form->bibitem_form->visible) { - fl_raise_form(bibitem_form->bibitem_form); - } else { - fl_show_form(bibitem_form->bibitem_form, - FL_PLACE_MOUSE, FL_FULLBORDER, - _("BibTeX")); - } +void InsetBibtex::edit(BufferView * bv, bool) +{ + edit(bv, 0, 0, 0); } bool InsetBibtex::addDatabase(string const & db) { - if (!contains(contents, db.c_str())) { + string contents(getContents()); + if (!contains(contents, db)) { if (!contents.empty()) - contents += ','; - contents += db; + contents += ","; + setContents(contents + db); return true; } return false; @@ -457,16 +304,16 @@ bool InsetBibtex::addDatabase(string const & db) bool InsetBibtex::delDatabase(string const & db) { - if (contains(contents, db.c_str())) { + if (contains(getContents(), db)) { string bd = db; - int n = tokenPos(contents, ',', bd); + int const n = tokenPos(getContents(), ',', bd); if (n > 0) { // Weird code, would someone care to explain this?(Lgb) string tmp(", "); tmp += bd; - contents = subst(contents, tmp.c_str(), ", "); + setContents(subst(getContents(), tmp, ", ")); } else if (n == 0) - contents = split(contents, bd, ','); + setContents(split(getContents(), bd, ',')); else return false; } @@ -474,63 +321,49 @@ bool InsetBibtex::delDatabase(string const & db) } -// This function should be in LyXView when multiframe works ale970302 -void BibitemUpdate(Combox * combox) -{ - combox->clear(); - - if (!current_view->available()) return; - - string tmp, bibkeys = current_view->buffer()->getBibkeyList(','); - bibkeys = split(bibkeys, tmp,','); - while (!tmp.empty()) { - combox->addto(tmp.c_str()); - bibkeys = split(bibkeys, tmp,','); - } -} - - - // ale070405 This function maybe shouldn't be here. We'll fix this at 0.13. -int bibitemMaxWidth(Painter & pain, LyXFont const & font) +int bibitemMaxWidth(BufferView * bv, LyXFont const & font) { int w = 0; + // Ha, now we are mainly at 1.2.0 and it is still here (Jug) // Does look like a hack? It is! (but will change at 0.13) - LyXParagraph * par = current_view->buffer()->paragraph; + Paragraph * par = bv->buffer()->paragraph; while (par) { if (par->bibkey) { - int wx = par->bibkey->width(pain, font); + int const wx = par->bibkey->width(bv, font); if (wx > w) w = wx; } - par = par->next; + par = par->next(); } return w; } // ale070405 -string bibitemWidthest(Painter & pain) +string const bibitemWidest(Buffer const * buffer) { int w = 0; // Does look like a hack? It is! (but will change at 0.13) - LyXParagraph * par = current_view->buffer()->paragraph; + Paragraph * par = buffer->paragraph; InsetBibKey * bkey = 0; LyXFont font; while (par) { if (par->bibkey) { - int wx = par->bibkey->width(pain, font); + int const wx = + lyxfont::width(par->bibkey->getBibLabel(), + font); if (wx > w) { w = wx; bkey = par->bibkey; } } - par = par->next; + par = par->next(); } - if (bkey && !bkey->getScreenLabel().empty()) - return bkey->getScreenLabel(); + if (bkey && !bkey->getBibLabel().empty()) + return bkey->getBibLabel(); return "99"; }