X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2Finsetbib.C;h=d314ad7013c235f5c9cf0a11f710e4496a4bbb11;hb=4a5b7a5952ad2381fcdf4830511293e184c7c5a1;hp=f86e7b37d432dc43d3878b528d00e13ba93b29df;hpb=07febc9941598e6d34ff0e763011ba1d938545fa;p=lyx.git diff --git a/src/insets/insetbib.C b/src/insets/insetbib.C index f86e7b37d4..d314ad7013 100644 --- a/src/insets/insetbib.C +++ b/src/insets/insetbib.C @@ -1,429 +1,299 @@ - #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" +#include "lyxrc.h" +#include "font.h" +#include "LyXView.h" +#include "lyxtextclasslist.h" -extern BufferView * current_view; +#include "frontends/Dialogs.h" -FD_citation_form * citation_form = 0; -FD_bibitem_form * bibitem_form = 0; -static Combox * bibcombox = 0; +#include "support/filetools.h" +#include "support/path.h" +#include "support/os.h" +#include "support/lstrings.h" +#include "support/LAssert.h" -extern void UpdateInset(Inset* inset, bool mark_dirty = true); -void BibitemUpdate(Combox *); -FD_citation_form * create_form_citation_form(void); -FD_bibitem_form * create_form_bibitem_form(void); +#include +#include +using std::ostream; +using std::ifstream; +using std::getline; +using std::endl; +using std::vector; +using std::pair; +using std::max; -extern "C" void bibitem_cb(FL_OBJECT *, long data) -{ - switch (data) { - case 1: // OK, citation - { - if(!current_view->buffer()->isReadonly()) { - InsetCommand * inset = static_cast(citation_form->citation_form->u_vdata); - 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 - UpdateInset(inset); - break; - } - // fall through to Cancel on RO-mode - } - case 0: fl_hide_form(citation_form->citation_form); - break; - case 3: // OK, bibitem - { - if(!current_view->buffer()->isReadonly()) { - InsetCommand *inset = static_cast(bibitem_form->bibitem_form->u_vdata); - 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) - current_view->buffer()->text->RedoParagraph(); - current_view->buffer()->update(1); - break; - } // fall through to Cancel on RO-mode - } - case 2: // Cancel, bibitem - fl_hide_form(bibitem_form->bibitem_form); // Cancel, bibitem - break; - } -} +int InsetBibKey::key_counter = 0; +const string key_prefix = "key-"; -FD_citation_form *create_form_citation_form(void) +InsetBibKey::InsetBibKey(InsetCommandParams const & p) + : InsetCommand(p), counter(1) { - 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, 120); - - 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; + if (getContents().empty()) + setContents(key_prefix + tostr(++key_counter)); } -/*---------------------------------------*/ -FD_bibitem_form *create_form_bibitem_form(void) + +InsetBibKey::~InsetBibKey() { - 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) +Inset * InsetBibKey::clone(Buffer const &, bool) const { - + InsetBibKey * b = new InsetBibKey(params()); + b->setCounter(counter); + return b; } -InsetCitation::~InsetCitation() -{ - if(citation_form && citation_form->citation_form - && citation_form->citation_form->visible - && citation_form->citation_form->u_vdata == this) - fl_hide_form(citation_form->citation_form); + + +void InsetBibKey::setCounter(int c) +{ + counter = c; } -void InsetCitation::Edit(int, int) +// I'm sorry but this is still necessary because \bibitem is used also +// 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(Buffer const *, ostream & os) const { - if(current_view->buffer()->isReadonly()) - WarnReadonly(); - - if (!citation_form) { - citation_form = create_form_citation_form(); - fl_set_form_atclose(citation_form->citation_form, - CancelCloseBoxCB, 0); + os << "\\bibitem "; + if (! getOptions().empty()) { + os << '[' + << getOptions() << ']'; } - citation_form->citation_form->u_vdata = this; - - 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")); - } + os << '{' + << getContents() << "}\n"; } -string InsetCitation::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) { - string temp("["); - - temp += contents; - - if (!options.empty()) { - temp += ", " + options; + if (lex.eatLine()) { + string const token = lex.getString(); + scanCommand(token); + } else { + lex.printError("InsetCommand: Parse error: `$$Token'"); } - return temp + ']'; + if (prefixIs(getContents(), key_prefix)) { + int key = strToInt(getContents().substr(key_prefix.length())); + key_counter = max(key_counter, key); + } } - -InsetBibKey::InsetBibKey(string const & key, string const & label): - InsetCommand("bibitem", key, label) +string const InsetBibKey::getBibLabel() const { - counter = 1; - if (key.empty()) - contents = ' '; + if (! getOptions().empty()) + return getOptions(); + return tostr(counter); } - -InsetBibKey::InsetBibKey(InsetBibKey const *b): - InsetCommand("bibitem", b->contents, b->options) +string const InsetBibKey::getScreenLabel(Buffer const *) const { - counter = b->counter; + return getContents() + " [" + getBibLabel() + "]"; } -InsetBibKey::~InsetBibKey() -{ - if(bibitem_form && bibitem_form->bibitem_form - && bibitem_form->bibitem_form->visible) - fl_hide_form(bibitem_form->bibitem_form); -} - -void InsetBibKey::setCounter(int c) +void InsetBibKey::edit(BufferView * bv, int, int, unsigned int) { - counter = c; - - if (contents.empty()) - contents += tostr(counter); + bv->owner()->getDialogs()->showBibitem(this); } -// I'm sorry but this is still necessary because \bibitem is used also -// 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(FILE * file) +void InsetBibKey::edit(BufferView * bv, bool) { - string s; - if (!options.empty()) { - s += '['; - s += options + ']'; - } - s += '{'; - s += contents + '}'; - fprintf(file, "\\bibitem %s\n", s.c_str()); + edit(bv, 0, 0, 0); } -string InsetBibKey::getScreenLabel() const -{ - if (!options.empty()) - return options; - - return tostr(counter); -} +InsetBibtex::InsetBibtex(InsetCommandParams const & p, bool) + : InsetCommand(p) +{} -/* - 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(int, int) +InsetBibtex::~InsetBibtex() { - if(current_view->buffer()->isReadonly()) - WarnReadonly(); - - if (!bibitem_form) { - bibitem_form = create_form_bibitem_form(); - fl_set_form_atclose(bibitem_form->bibitem_form, - CancelCloseBoxCB, 0); - } - bibitem_form->bibitem_form->u_vdata = this; - // 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")); - } } - -InsetBibtex::InsetBibtex(string const & dbase, string const & style, - Buffer *o) - :InsetCommand("BibTeX", dbase, style), owner(o) +string const InsetBibtex::getScreenLabel(Buffer const *) const { + return _("BibTeX Generated References"); } -string InsetBibtex::getScreenLabel() const +int InsetBibtex::latex(Buffer const * buffer, ostream & os, + bool /*fragile*/, bool/*fs*/) const { - return _("BibTeX Generated References"); -} + // changing the sequence of the commands + // 1. \bibliographystyle{style} + // 2. \addcontentsline{...} - if option bibtotoc set + // 3. \bibliography{database} + string adb, db_out; + 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()); + } -int InsetBibtex::Latex(FILE *file, signed char /*fragile*/) -{ - string bib; - signed char dummy = 0; - int result = Latex(bib, dummy); - fprintf(file, "%s", bib.c_str()); - return result; -} + 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.NameOfClass(buffer->params.textclass),"art")) { + if (buffer->params.sides == LyXTextClass::OneSide) { + // oneside + os << "\\clearpage"; + } else { + // twoside + os << "\\cleardoublepage"; + } -int InsetBibtex::Latex(string &file, signed char /*fragile*/) -{ - // 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(); + // 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 db_in, adb, db_out; - 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); + 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(); - - file += "\\bibliographystyle{"; - file += style; - file += "}\n"; - file += "\\bibliography{"; - file += db_out; - file += "}\n"; + os << "\\bibliography{" << db_out << "}\n"; return 2; } -// This method returns a comma separated list of Bibtex entries -string InsetBibtex::getKeys() +vector const InsetBibtex::getFiles(Buffer const & buffer) const { - // This hack is copied from InsetBibtex::Latex. - // Is it still needed? Probably yes. - 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 << "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)) { - if (prefixIs(linebuf, "@")) { - linebuf = subst(linebuf, '{', '('); - linebuf = split(linebuf, tmp, '('); - tmp = lowercase(tmp); - if (!prefixIs(tmp, "@string") - && !prefixIs(tmp, "@preamble")) { - linebuf = split(linebuf, - tmp, ','); - if (!tmp.empty()) { - keys += strip(tmp); - keys += ", "; - } + 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(int, 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); +} - bibitem_form->bibitem_form->u_vdata = this; - 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; @@ -432,16 +302,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; } @@ -449,64 +319,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(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(font); - if (wx>w) w = wx; + int const wx = par->bibkey->width(bv, font); + if (wx > w) w = wx; } - par = par->next; + par = par->next(); } return w; } -// ale070405 -string bibitemWidthest() +// ale070405 +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(font); - if (wx>w) { + 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"; }