X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2Finsetert.C;h=37fc79acc64456f9aa8825f7a73db9708581581b;hb=ce1f7f257823c9995035c6cbb75f1ea63d9995b6;hp=acdb6eb5d3ebf9917633297baacadbefe858dd77;hpb=bade84c1f8fe6c9bb4a8835ea0fccc4c1df915e5;p=lyx.git diff --git a/src/insets/insetert.C b/src/insets/insetert.C index acdb6eb5d3..37fc79acc6 100644 --- a/src/insets/insetert.C +++ b/src/insets/insetert.C @@ -1,87 +1,235 @@ -/* This file is part of - * ====================================================== - * - * LyX, The Document Processor - * - * Copyright 1998 The LyX Team. +/** + * \file insetert.C + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. * - *======================================================*/ - + * \author Jürgen Vigna + * \author Lars Gullik Bjønnes + * + * Full author contact details are available in file CREDITS + */ #include -#ifdef __GNUG__ -#pragma implementation -#endif - #include "insetert.h" +#include "insettext.h" + +#include "buffer.h" +#include "BufferView.h" +#include "debug.h" +#include "funcrequest.h" #include "gettext.h" +#include "language.h" #include "lyxfont.h" -#include "buffer.h" -#include "insets/insettext.h" +#include "lyxlex.h" +#include "lyxrow.h" +#include "lyxtext.h" +#include "WordLangTuple.h" + +#include "frontends/Alert.h" +#include "frontends/Dialogs.h" +#include "frontends/LyXView.h" + #include "support/LOstream.h" -#include "lyx_gui_misc.h" +#include "support/LAssert.h" +#include "support/lstrings.h" + using std::ostream; +using std::min; +using std::endl; + +using lyx::pos_type; + -InsetERT::InsetERT() : InsetCollapsable() +void InsetERT::init() { - setLabel(_("666")); - //LyXFont font(LyXFont::ALL_SANE); - //font.setLatex (LyXFont::ON); + setButtonLabel(); labelfont = LyXFont(LyXFont::ALL_SANE); labelfont.decSize(); labelfont.decSize(); labelfont.setColor(LColor::latex); - setAutoCollapse(false); setInsetName("ERT"); } -InsetERT::InsetERT(string const & contents) +InsetERT::InsetERT(BufferParams const & bp, bool collapsed) + : InsetCollapsable(bp, collapsed) +{ + if (collapsed) + status_ = Collapsed; + else + status_ = Open; + init(); +} + + +InsetERT::InsetERT(InsetERT const & in, bool same_id) + : InsetCollapsable(in, same_id), status_(in.status_) +{ + init(); +} + + +Inset * InsetERT::clone(Buffer const &, bool same_id) const { - setLabel(_("666")); - LyXFont font(LyXFont::ALL_SANE); -#ifndef NO_LATEX - font.setLatex(LyXFont::ON); -#else + return new InsetERT(*const_cast(this), same_id); +} + + +InsetERT::InsetERT(BufferParams const & bp, + Language const * l, string const & contents, bool collapsed) + : InsetCollapsable(bp, collapsed) +{ + if (collapsed) + status_ = Collapsed; + else + status_ = Open; + + LyXFont font(LyXFont::ALL_INHERIT, l); +#ifdef SET_HARD_FONT + font.setFamily(LyXFont::TYPEWRITER_FAMILY); font.setColor(LColor::latex); #endif - labelfont = LyXFont(LyXFont::ALL_SANE); - labelfont.decSize(); - labelfont.decSize(); - labelfont.setColor(LColor::latex); - setAutoCollapse(false); - setInsetName("ERT"); string::const_iterator cit = contents.begin(); string::const_iterator end = contents.end(); - Paragraph::size_type pos = 0; + pos_type pos = 0; for (; cit != end; ++cit) { inset.paragraph()->insertChar(pos++, *cit, font); } + // the init has to be after the initialization of the paragraph + // because of the label settings (draw_label for ert insets). + init(); } -void InsetERT::write(Buffer const * buf, ostream & os) const +InsetERT::~InsetERT() { - os << getInsetName() << "\n"; - InsetCollapsable::write(buf, os); + InsetERTMailer mailer(*this); + mailer.hideDialog(); } -Inset * InsetERT::clone(Buffer const &, bool same_id) const +void InsetERT::read(Buffer const * buf, LyXLex & lex) { - InsetERT * result = new InsetERT; - result->inset.init(&inset, same_id); - - result->collapsed = collapsed; - if (same_id) - result->id_ = id_; - return result; + bool token_found = false; + if (lex.isOK()) { + lex.next(); + string const token = lex.getString(); + if (token == "status") { + lex.next(); + string const tmp_token = lex.getString(); + + if (tmp_token == "Inlined") { + status(0, Inlined); + } else if (tmp_token == "Collapsed") { + status(0, Collapsed); + } else { + // leave this as default! + status(0, Open); + } + + token_found = true; + } else { + lyxerr << "InsetERT::Read: Missing 'status'-tag!" + << endl; + // take countermeasures + lex.pushToken(token); + } + } +#if 0 +#warning this should be really short lived only for compatibility to +#warning files written 07/08/2001 so this has to go before 1.2.0! (Jug) + if (lex.isOK()) { + lex.next(); + string const token = lex.getString(); + if (token == "collapsed") { + lex.next(); + collapsed_ = lex.getBool(); + } else { + // Take countermeasures + lex.pushToken(token); + } + } +#endif + inset.read(buf, lex); + +#ifdef SET_HARD_FONT + LyXFont font(LyXFont::ALL_INHERIT, latex_language); + font.setFamily(LyXFont::TYPEWRITER_FAMILY); + font.setColor(LColor::latex); + Paragraph * par = inset.paragraph(); + while (par) { + pos_type siz = par->size(); + for (pos_type i = 0; i < siz; ++i) { + par->setFont(i, font); + } + par = par->next(); + } +#endif + + if (!token_found) { + if (collapsed_) { + status(0, Collapsed); + } else { + status(0, Open); + } + } + setButtonLabel(); +} + + +void InsetERT::write(Buffer const * buf, ostream & os) const +{ + string st; + + switch (status_) { + case Open: + st = "Open"; + break; + case Collapsed: + st = "Collapsed"; + break; + case Inlined: + st = "Inlined"; + break; + } + + os << getInsetName() << "\n" + << "status "<< st << "\n"; + + //inset.writeParagraphData(buf, os); + string const layout(buf->params.getLyXTextClass().defaultLayoutName()); + Paragraph * par = inset.paragraph(); + while (par) { + os << "\n\\layout " << layout << "\n"; + pos_type siz = par->size(); + for (pos_type i = 0; i < siz; ++i) { + Paragraph::value_type c = par->getChar(i); + switch (c) { + case Paragraph::META_INSET: + if (par->getInset(i)->lyxCode() != Inset::NEWLINE_CODE) { + lyxerr << "Element is not allowed in insertERT" + << endl; + } else { + par->getInset(i)->write(buf, os); + } + break; + + case '\\': + os << "\n\\backslash \n"; + break; + default: + os << c; + break; + } + } + par = par->next(); + } } -string const InsetERT::editMessage() const +string const InsetERT::editMessage() const { return _("Opened ERT Inset"); } @@ -95,58 +243,491 @@ bool InsetERT::insertInset(BufferView *, Inset *) void InsetERT::setFont(BufferView *, LyXFont const &, bool, bool selectall) { +#ifdef WITH_WARNINGS +#warning FIXME. More UI stupidity... +#endif // if selectall is activated then the fontchange was an outside general // fontchange and this messages is not needed if (!selectall) - WriteAlert(_("Impossible Operation!"), - _("Not permitted to change font-types inside ERT-insets!"), - _("Sorry.")); + Alert::error(_("Cannot change font"), + _("You cannot change font settings inside TeX code.")); } -void InsetERT::edit(BufferView * bv, int x, int y, unsigned int button) +void InsetERT::updateStatus(BufferView * bv, bool swap) const { - InsetCollapsable::edit(bv, x, y, button); -#ifndef NO_LATEX - LyXFont font(LyXFont::ALL_SANE); - font.setLatex (LyXFont::ON); -#endif + if (status_ != Inlined) { + if (collapsed_) { + status(bv, swap ? Open : Collapsed); + } else { + status(bv, swap ? Collapsed : Open); + } + } +} + +void InsetERT::edit(BufferView * bv, int x, int y, mouse_button::state button) +{ + if (button == mouse_button::button3) + return; + + if (status_ == Inlined) { + if (!bv->lockInset(this)) + return; + inset.edit(bv, x, y, button); + } else { + InsetCollapsable::edit(bv, x, y, button); + } + set_latex_font(bv); + updateStatus(bv); +} + + +Inset::EDITABLE InsetERT::editable() const +{ + if (status_ == Collapsed) + return IS_EDITABLE; + return HIGHLY_EDITABLE; +} + + +void InsetERT::edit(BufferView * bv, bool front) +{ + InsetCollapsable::edit(bv, front); + updateStatus(0); + set_latex_font(bv); +} + + +void InsetERT::lfunMousePress(FuncRequest const & cmd) +{ + if (status_ == Inlined) + inset.localDispatch(cmd); + else + InsetCollapsable::localDispatch(cmd); +} + + +bool InsetERT::lfunMouseRelease(FuncRequest const & cmd) +{ + BufferView * bv = cmd.view(); + + if (cmd.button() == mouse_button::button3) { + showInsetDialog(bv); + return true; + } + + if (status_ != Inlined && (cmd.x >= 0) && (cmd.x < button_length) && + (cmd.y >= button_top_y) && (cmd.y <= button_bottom_y)) { + updateStatus(bv, true); + } else { + LyXFont font(LyXFont::ALL_SANE); + FuncRequest cmd1 = cmd; + cmd1.y = ascent(bv, font) + cmd.y - inset.ascent(bv, font); + + // inlined is special - the text appears above + // button_bottom_y + if (status_ == Inlined) + inset.localDispatch(cmd1); + else if (!collapsed_ && (cmd.y > button_bottom_y)) { + cmd1.y -= ascent_collapsed() + descent_collapsed(); + inset.localDispatch(cmd1); + } + } + return false; +} + + +void InsetERT::lfunMouseMotion(FuncRequest const & cmd) +{ + if (status_ == Inlined) + inset.localDispatch(cmd); + else + InsetCollapsable::localDispatch(cmd); } -int InsetERT::latex(Buffer const *, std::ostream & os, bool /*fragile*/, +int InsetERT::latex(Buffer const *, ostream & os, bool /*fragile*/, bool /*free_spc*/) const { - Paragraph::size_type siz = inset.paragraph()->size(); - for (Paragraph::size_type i = 0; i != siz; ++i) { - char c = inset.paragraph()->getChar(i); - switch (c) { - case Paragraph::META_NEWLINE: - os << '\n'; + Paragraph * par = inset.paragraph(); + int lines = 0; + while (par) { + pos_type siz = par->size(); + for (pos_type i = 0; i < siz; ++i) { + // ignore all struck out text + if (isDeletedText(*par, i)) + continue; + + if (par->isNewline(i)) { + os << '\n'; + ++lines; + } else { + os << par->getChar(i); + } + } + par = par->next(); + if (par) { + os << "\n\n"; + lines += 2; + } + } + + return lines; +} + + +int InsetERT::ascii(Buffer const *, ostream &, int /*linelen*/) const +{ + return 0; +} + + +int InsetERT::linuxdoc(Buffer const *, ostream & os) const +{ + Paragraph * par = inset.paragraph(); + int lines = 0; + while (par) { + pos_type siz = par->size(); + for (pos_type i = 0; i < siz; ++i) { + if (par->isNewline(i)) { + os << '\n'; + ++lines; + } else { + os << par->getChar(i); + } + } + par = par->next(); + if (par) { + os << "\n"; + lines ++; + } + } + + return lines; +} + + +int InsetERT::docbook(Buffer const *, ostream & os, bool) const +{ + Paragraph * par = inset.paragraph(); + int lines = 0; + while (par) { + pos_type siz = par->size(); + for (pos_type i = 0; i < siz; ++i) { + if (par->isNewline(i)) { + os << '\n'; + ++lines; + } else { + os << par->getChar(i); + } + } + par = par->next(); + if (par) { + os << "\n"; + lines ++; + } + } + + return lines; +} + + +Inset::RESULT InsetERT::localDispatch(FuncRequest const & cmd) +{ + Inset::RESULT result = UNDISPATCHED; + BufferView * bv = cmd.view(); + + if (inset.paragraph()->empty()) { + set_latex_font(bv); + } + + switch (cmd.action) { + case LFUN_INSET_MODIFY: { + InsetERT::ERTStatus status_; + InsetERTMailer::string2params(cmd.argument, status_); + + status(bv, status_); + + /* FIXME: I refuse to believe we have to live + * with ugliness like this ! Note that this + * rebreak *is* needed. Consider a change from + * Open (needfullrow) to Inlined (only the space + * taken by the text). + */ + LyXText * t = inset.getLyXText(cmd.view()); + t->need_break_row = t->rows().begin(); + t->fullRebreak(); + t->setCursorIntern(t->cursor.par(), t->cursor.pos()); + inset.update(cmd.view(), true); + bv->updateInset(this); + result = DISPATCHED; + } + break; + + case LFUN_MOUSE_PRESS: + lfunMousePress(cmd); + result = DISPATCHED; + break; + + case LFUN_MOUSE_MOTION: + lfunMouseMotion(cmd); + result = DISPATCHED; + break; + + case LFUN_MOUSE_RELEASE: + lfunMouseRelease(cmd); + result = DISPATCHED; + break; + + case LFUN_LAYOUT: + bv->owner()->setLayout(inset.paragraph()->layout()->name()); + result = DISPATCHED_NOUPDATE; + break; + + default: + result = InsetCollapsable::localDispatch(cmd); + } + + switch (cmd.action) { + case LFUN_BREAKPARAGRAPH: + case LFUN_BREAKPARAGRAPHKEEPLAYOUT: + case LFUN_BACKSPACE: + case LFUN_BACKSPACE_SKIP: + case LFUN_DELETE: + case LFUN_DELETE_SKIP: + case LFUN_DELETE_LINE_FORWARD: + case LFUN_CUT: + set_latex_font(bv); + break; + + default: + break; + } + return result; +} + + +string const InsetERT::get_new_label() const +{ + string la; + pos_type const max_length = 15; + pos_type const p_siz = inset.paragraph()->size(); + pos_type const n = min(max_length, p_siz); + pos_type i = 0; + pos_type j = 0; + for(; i < n && j < p_siz; ++j) { + if (inset.paragraph()->isInset(j)) + continue; + la += inset.paragraph()->getChar(j); + ++i; + } + if (inset.paragraph()->next() || (i > 0 && j < p_siz)) { + la += "..."; + } + if (la.empty()) { + la = _("ERT"); + } + return la; +} + + +void InsetERT::setButtonLabel() const +{ + if (status_ == Collapsed) { + setLabel(get_new_label()); + } else { + setLabel(_("ERT")); + } +} + + +bool InsetERT::checkInsertChar(LyXFont & /* font */) +{ +#ifdef SET_HARD_FONT + LyXFont f(LyXFont::ALL_INHERIT, latex_language); + font = f; + font.setFamily(LyXFont::TYPEWRITER_FAMILY); + font.setColor(LColor::latex); +#endif + return true; +} + + +int InsetERT::ascent(BufferView * bv, LyXFont const & font) const +{ + if (!inlined()) + return InsetCollapsable::ascent(bv, font); + + return inset.ascent(bv, font); +} + + +int InsetERT::descent(BufferView * bv, LyXFont const & font) const +{ + if (!inlined()) + return InsetCollapsable::descent(bv, font); + + return inset.descent(bv, font); +} + + +int InsetERT::width(BufferView * bv, LyXFont const & font) const +{ + if (!inlined()) + return InsetCollapsable::width(bv, font); + + return inset.width(bv, font); +} + + +void InsetERT::draw(BufferView * bv, LyXFont const & f, + int baseline, float & x) const +{ + InsetCollapsable::draw(bv, f, baseline, x, inlined()); +} + + +void InsetERT::set_latex_font(BufferView * /* bv */) +{ +#ifdef SET_HARD_FONT + LyXFont font(LyXFont::ALL_INHERIT, latex_language); + + font.setFamily(LyXFont::TYPEWRITER_FAMILY); + font.setColor(LColor::latex); + + inset.getLyXText(bv)->setFont(bv, font, false); +#endif +} + + +// attention this function can be called with bv == 0 +void InsetERT::status(BufferView * bv, ERTStatus const st) const +{ + if (st != status_) { + status_ = st; + switch (st) { + case Inlined: + if (bv) + inset.setUpdateStatus(bv, InsetText::INIT); break; - default: - os << c; + case Open: + collapsed_ = false; + setButtonLabel(); break; + case Collapsed: + collapsed_ = true; + setButtonLabel(); + if (bv) + bv->unlockInset(const_cast(this)); + break; + } + if (bv) { + bv->updateInset(const_cast(this)); + bv->buffer()->markDirty(); } } - return 1; } -int InsetERT::ascii(Buffer const *, - std::ostream &, int /*linelen*/) const +bool InsetERT::showInsetDialog(BufferView * bv) const { - return 0; + InsetERTMailer mailer(const_cast(*this)); + mailer.showDialog(bv); + return true; } -int InsetERT::linuxdoc(Buffer const *, std::ostream &) const +void InsetERT::open(BufferView * bv) { - return 0; + if (!collapsed_) + return; + status(bv, Open); } -int InsetERT::docBook(Buffer const *, std::ostream &) const +void InsetERT::close(BufferView * bv) const { - return 0; + if (status_ == Collapsed || status_ == Inlined) + return; + + status(bv, Collapsed); +} + + +WordLangTuple const +InsetERT::selectNextWordToSpellcheck(BufferView * bv, float &) const +{ + bv->unlockInset(const_cast(this)); + return WordLangTuple(); +} + + +void InsetERT::getDrawFont(LyXFont & font) const +{ + LyXFont f(LyXFont::ALL_INHERIT, latex_language); + font = f; + font.setFamily(LyXFont::TYPEWRITER_FAMILY); + font.setColor(LColor::latex); +} + + +int InsetERT::getMaxWidth(BufferView * bv, UpdatableInset const * in) const +{ + int w = InsetCollapsable::getMaxWidth(bv, in); + if (status_ != Inlined || w < 0) + return w; + LyXText * text = inset.getLyXText(bv); + int rw = text->rows().begin()->width(); + if (!rw) + rw = w; + rw += 40; + if (text->rows().size() == 1 && rw < w) + return -1; + return w; +} + + +void InsetERT::update(BufferView * bv, bool reinit) +{ + if (inset.need_update & InsetText::INIT || + inset.need_update & InsetText::FULL) { + setButtonLabel(); + } + + InsetCollapsable::update(bv, reinit); +} + + +string const InsetERTMailer::name_("ert"); + +InsetERTMailer::InsetERTMailer(InsetERT & inset) + : inset_(inset) +{} + + +string const InsetERTMailer::inset2string() const +{ + return params2string(inset_.status()); +} + + +void InsetERTMailer::string2params(string const & in, + InsetERT::ERTStatus & status) +{ + status = InsetERT::Collapsed; + + string name; + string body = split(in, name, ' '); + + if (body.empty()) + return; + + status = static_cast(strToInt(body)); +} + + +string const +InsetERTMailer::params2string(InsetERT::ERTStatus status) +{ + return name_ + ' ' + tostr(status); }