X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2Finsetbib.C;h=d314ad7013c235f5c9cf0a11f710e4496a4bbb11;hb=4a5b7a5952ad2381fcdf4830511293e184c7c5a1;hp=99bb4989ef4cfd545783704a01b90255b6e93f28;hpb=d6665cba427b04ae37f42c846398cad518d2be0f;p=lyx.git diff --git a/src/insets/insetbib.C b/src/insets/insetbib.C index 99bb4989ef..d314ad7013 100644 --- a/src/insets/insetbib.C +++ b/src/insets/insetbib.C @@ -1,23 +1,30 @@ #include -#include -#include - #ifdef __GNUG__ #pragma implementation #endif -#include FORMS_H_LOCATION #include "insetbib.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 "lyxrc.h" +#include "font.h" +#include "LyXView.h" +#include "lyxtextclasslist.h" + +#include "frontends/Dialogs.h" + #include "support/filetools.h" #include "support/path.h" +#include "support/os.h" +#include "support/lstrings.h" +#include "support/LAssert.h" + +#include +#include using std::ostream; using std::ifstream; @@ -25,70 +32,25 @@ using std::getline; using std::endl; using std::vector; using std::pair; +using std::max; -extern BufferView * current_view; - -FD_bibitem_form * bibitem_form = 0; - -FD_bibitem_form * create_form_bibitem_form(void); - - -extern "C" -void bibitem_cb(FL_OBJECT *, long data) -{ - InsetBibKey::Holder * holder = - static_cast - (bibitem_form->bibitem_form->u_vdata); - - holder->inset->callback( bibitem_form, data ); -} - - -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, 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(_("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; -} - +int InsetBibKey::key_counter = 0; +const string key_prefix = "key-"; InsetBibKey::InsetBibKey(InsetCommandParams const & p) - : InsetCommand(p) + : InsetCommand(p), counter(1) { - counter = 1; + if (getContents().empty()) + setContents(key_prefix + tostr(++key_counter)); } 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); } -Inset * InsetBibKey::Clone() const +Inset * InsetBibKey::clone(Buffer const &, bool) const { InsetBibKey * b = new InsetBibKey(params()); b->setCounter(counter); @@ -96,30 +58,9 @@ Inset * InsetBibKey::Clone() const } -void InsetBibKey::callback( FD_bibitem_form * form, long data ) -{ - switch (data) { - case 1: - if(!holder.view->buffer()->isReadonly()) { - setContents(fl_get_input(form->key)); - setOptions(fl_get_input(form->label)); - // shouldn't mark the buffer dirty unless - // something was actually altered - holder.view->updateInset( this, true ); - } // fall through to Cancel - case 0: - fl_hide_form(form->bibitem_form); - break; - } -} - - void InsetBibKey::setCounter(int c) { counter = c; - - if (getCmdName().empty()) - setCmdName( tostr(counter) ); } @@ -127,7 +68,7 @@ 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(Buffer const *, ostream & os) const +void InsetBibKey::write(Buffer const *, ostream & os) const { os << "\\bibitem "; if (! getOptions().empty()) { @@ -141,208 +82,208 @@ void InsetBibKey::Write(Buffer const *, ostream & os) 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 token; - - if (lex.EatLine()) { - token = lex.GetString(); +void InsetBibKey::read(Buffer const *, LyXLex & lex) +{ + if (lex.eatLine()) { + string const token = lex.getString(); scanCommand(token); - } else + } 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); + } +} -string const InsetBibKey::getScreenLabel() const +string const InsetBibKey::getBibLabel() const { if (! getOptions().empty()) return getOptions(); - return tostr(counter); } - -/** - 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::getScreenLabel(Buffer const *) 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); - } + return getContents() + " [" + getBibLabel() + "]"; +} - 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")); - } + +void InsetBibKey::edit(BufferView * bv, int, int, unsigned int) +{ + bv->owner()->getDialogs()->showBibitem(this); +} + + +void InsetBibKey::edit(BufferView * bv, bool) +{ + edit(bv, 0, 0, 0); } -InsetBibtex::InsetBibtex(InsetCommandParams const & p, Buffer * o) - : InsetCommand(p), owner(o) +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 const InsetBibtex::getScreenLabel() const +string const InsetBibtex::getScreenLabel(Buffer const *) const { return _("BibTeX Generated References"); } -int InsetBibtex::Latex(Buffer const *, 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(); - } - // 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 + // 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, ','); - while(!adb.empty()) { - if (!owner->niceFile && - IsFileReadable(MakeAbsPath(adb, owner->filepath)+".bib")) - adb = MakeAbsPath(adb, owner->filepath); + // 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.NameOfClass(buffer->params.textclass),"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 + 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 -vector > const InsetBibtex::getKeys() const +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(); - //} - - Path p(owner->filepath); + // Doesn't appear to be used (Angus, 31 July 2001) + Path p(buffer.filePath()); + + vector vec; - vector > keys; string tmp; string bibfiles = getContents(); bibfiles = split(bibfiles, tmp, ','); - while(!tmp.empty()) { - string fil = findtexfile(ChangeExtension(tmp, "bib"), - "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 linebuf0; - while (getline(ifs, linebuf0)) { - string linebuf = frontStrip(strip(linebuf0)); - if( linebuf.empty() ) continue; - 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(tmp); - if (!tmp.empty()) { - keys.push_back(pair(tmp,string())); - } + 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"; } + } 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); } @@ -363,7 +304,7 @@ bool InsetBibtex::delDatabase(string const & db) { if (contains(getContents(), db)) { string bd = db; - int n = tokenPos(getContents(), ',', bd); + int const n = tokenPos(getContents(), ',', bd); if (n > 0) { // Weird code, would someone care to explain this?(Lgb) string tmp(", "); @@ -382,42 +323,45 @@ bool InsetBibtex::delDatabase(string const & db) 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(bv, font); + int const wx = par->bibkey->width(bv, font); if (wx > w) w = wx; } - par = par->next; + par = par->next(); } return w; } // ale070405 -string const bibitemWidest(BufferView * bv) +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(bv, 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"; }