]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetListings.cpp
try to pass a Buffer & to inset construction if some buffer(param)
[lyx.git] / src / insets / InsetListings.cpp
index 30ba1a2a4ef6e2d05b8ce089a699e315f3f0d9e9..0b63ec28e6783c45f3bd06a9da710068096c7d42 100644 (file)
@@ -4,6 +4,7 @@
  * Licence details can be found in the file COPYING.
  *
  * \author Bo Peng
+ * \author Jürgen Spitzmüller
  *
  * Full author contact details are available in file CREDITS.
  */
 #include <config.h>
 
 #include "InsetListings.h"
+#include "InsetCaption.h"
 
-#include "Language.h"
-#include "gettext.h"
+#include "Buffer.h"
+#include "BufferParams.h"
+#include "Counters.h"
+#include "Cursor.h"
 #include "DispatchResult.h"
 #include "FuncRequest.h"
 #include "FuncStatus.h"
-#include "Cursor.h"
+#include "support/gettext.h"
+#include "InsetList.h"
+#include "Language.h"
+#include "MetricsInfo.h"
+#include "TextClass.h"
+
+#include "support/docstream.h"
 #include "support/lstrings.h"
 
 #include <sstream>
 
+using namespace std;
+using namespace lyx::support;
+
 namespace lyx {
 
-using support::token;
 
-using std::auto_ptr;
-using std::istringstream;
-using std::ostream;
-using std::ostringstream;
-using std::string;
+char const lstinline_delimiters[] =
+       "!*()-=+|;:'\"`,<.>/?QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm";
 
+InsetListings::InsetListings(Buffer const & buf, InsetListingsParams const & par)
+       : InsetCollapsable(buf, par.status())
+{}
 
-void InsetListings::init()
-{
-       setButtonLabel();
-       // FIXME: define Color::listing?
-       Font font(Font::ALL_SANE);
-       font.decSize();
-       font.decSize();
-       font.setColor(Color::foreground);
-       setLabelFont(font);
-       // FIXME: english_language?
-       text_.current_font.setLanguage(english_language);
-       text_.real_current_font.setLanguage(english_language);
-       // FIXME: why I can not make text of source code black with the following two lines?
-       text_.current_font.setColor(Color::foreground);
-       text_.real_current_font.setColor(Color::foreground);
-}
+
+InsetListings::InsetListings(InsetListings const & in)
+       : InsetCollapsable(in), params_(in.params_)
+{}
 
 
-InsetListings::InsetListings(BufferParams const & bp, InsetListingsParams const & par)
-       : InsetERT(bp, par.status())
+Inset * InsetListings::clone() const
 {
-       init();
+       return new InsetListings(*this);
 }
 
 
-InsetListings::InsetListings(InsetListings const & in)
-       : InsetERT(in)
+InsetListings::~InsetListings()
 {
-       init();
+       InsetListingsMailer(*this).hideDialog();
 }
 
 
-auto_ptr<Inset> InsetListings::doClone() const
+Inset::DisplayType InsetListings::display() const
 {
-       return auto_ptr<Inset>(new InsetListings(*this));
+       return params().isInline() || params().isFloat() ? Inline : AlignLeft;
 }
 
 
-InsetListings::~InsetListings()
+void InsetListings::updateLabels(ParIterator const & it)
 {
-       InsetListingsMailer(*this).hideDialog();
-}
+       Counters & cnts = buffer().params().documentClass().counters();
+       string const saveflt = cnts.current_float();
 
+       // Tell to captions what the current float is
+       cnts.current_float("listing");
 
-bool InsetListings::display() const
-{
-       return !params().isInline();
+       InsetCollapsable::updateLabels(it);
+
+       //reset afterwards
+       cnts.current_float(saveflt);
 }
 
 
-void InsetListings::write(Buffer const & buf, ostream & os) const
+void InsetListings::write(ostream & os) const
 {
        os << "listings" << "\n";
        InsetListingsParams const & par = params();
@@ -95,11 +96,11 @@ void InsetListings::write(Buffer const & buf, ostream & os) const
                os << "inline true\n";
        else
                os << "inline false\n";
-       InsetCollapsable::write(buf, os);
+       InsetCollapsable::write(os);
 }
 
 
-void InsetListings::read(Buffer const & buf, Lexer & lex)
+void InsetListings::read(Lexer & lex)
 {
        while (lex.isOK()) {
                lex.next();
@@ -117,59 +118,86 @@ void InsetListings::read(Buffer const & buf, Lexer & lex)
                        break;
                }
        }
-       InsetCollapsable::read(buf, lex);
+       InsetCollapsable::read(lex);
 }
 
 
-docstring const InsetListings::editMessage() const
+docstring InsetListings::editMessage() const
 {
-       return _("Opened Listings Inset");
+       return _("Opened Listing Inset");
 }
 
 
-int InsetListings::latex(Buffer const &, odocstream & os,
-                   OutputParams const &) const
+int InsetListings::latex(odocstream & os, OutputParams const & runparams) const
 {
-       string param_string = params().encodedString();
+       string param_string = params().params();
        // NOTE: I use {} to quote text, which is an experimental feature
        // of the listings package (see page 25 of the manual)
        int lines = 0;
-       bool lstinline = params().isInline();
-       if (lstinline) {
-               if (param_string.empty())
-                       os << "\\lstinline{";
-               else
-                       os << "\\lstinline[" << from_ascii(param_string) << "]{";
-       } else {
-               if (param_string.empty())
-                       os << "\n\\begingroup\n\\inputencoding{latin1}\n\\begin{lstlisting}\n";
-               else
-                       os << "\n\\begingroup\n\\inputencoding{latin1}\n\\begin{lstlisting}[" << from_ascii(param_string) << "]\n";
-               lines += 4;
-       }
+       bool isInline = params().isInline();
+       // get the paragraphs. We can not output them directly to given odocstream
+       // because we can not yet determine the delimiter character of \lstinline
+       docstring code;
        ParagraphList::const_iterator par = paragraphs().begin();
        ParagraphList::const_iterator end = paragraphs().end();
 
        while (par != end) {
                pos_type siz = par->size();
+               bool captionline = false;
                for (pos_type i = 0; i < siz; ++i) {
-                       // ignore all struck out text
-                       if (par->isDeleted(i))
+                       if (i == 0 && par->isInset(i) && i + 1 == siz)
+                               captionline = true;
+                       // ignore all struck out text and (caption) insets
+                       if (par->isDeleted(i) || par->isInset(i))
                                continue;
-                       os.put(par->getChar(i));
+                       code += par->getChar(i);
                }
                ++par;
                // for the inline case, if there are multiple paragraphs
-               // they are simply joined. Otherwise, expect latex errors. 
-               if (par != end && !lstinline) {
-                       os << "\n";
+               // they are simply joined. Otherwise, expect latex errors.
+               if (par != end && !isInline && !captionline) {
+                       code += "\n";
                        ++lines;
                }
        }
-       if (lstinline)
-               os << "}";              
-       else {
-               os << "\n\\end{lstlisting}\n\\endgroup\n";
+       if (isInline) {
+                char const * delimiter = lstinline_delimiters;
+               for (; delimiter != '\0'; ++delimiter)
+                       if (!contains(code, *delimiter))
+                               break;
+               // This code piece contains all possible special character? !!!
+               // Replace ! with a warning message and use ! as delimiter.
+               if (*delimiter == '\0') {
+                       code = subst(code, from_ascii("!"), from_ascii(" WARNING: no lstline delimiter can be used "));
+                       delimiter = lstinline_delimiters;
+               }
+               if (param_string.empty())
+                       os << "\\lstinline" << *delimiter;
+               else
+                       os << "\\lstinline[" << from_ascii(param_string) << "]" << *delimiter;
+                os << code
+                   << *delimiter;
+       } else {
+               OutputParams rp = runparams;
+               // FIXME: the line below would fix bug 4182,
+               // but real_current_font moved to cursor.
+               //rp.local_font = &text_.real_current_font;
+               rp.moving_arg = true;
+               docstring const caption = getCaption(rp);
+               runparams.encoding = rp.encoding;
+               if (param_string.empty() && caption.empty())
+                       os << "\n\\begingroup\n\\inputencoding{latin1}\n\\begin{lstlisting}\n";
+               else {
+                       os << "\n\\begingroup\n\\inputencoding{latin1}\n\\begin{lstlisting}[";
+                       if (!caption.empty()) {
+                               os << "caption={" << caption << '}';
+                               if (!param_string.empty())
+                                       os << ',';
+                       }
+                       os << from_utf8(param_string) << "]\n";
+               }
+               lines += 4;
+               os << code << "\n\\end{lstlisting}\n\\endgroup\n";
                lines += 3;
        }
 
@@ -187,17 +215,17 @@ void InsetListings::doDispatch(Cursor & cur, FuncRequest & cmd)
        }
        case LFUN_INSET_DIALOG_UPDATE:
                InsetListingsMailer(*this).updateDialog(&cur.bv());
-               break;  
+               break;
        case LFUN_MOUSE_RELEASE: {
                if (cmd.button() == mouse_button::button3 && hitButton(cmd)) {
                        InsetListingsMailer(*this).showDialog(&cur.bv());
                        break;
                }
-               InsetERT::doDispatch(cur, cmd);
+               InsetCollapsable::doDispatch(cur, cmd);
                break;
        }
        default:
-               InsetERT::doDispatch(cur, cmd);
+               InsetCollapsable::doDispatch(cur, cmd);
                break;
        }
 }
@@ -210,8 +238,11 @@ bool InsetListings::getStatus(Cursor & cur, FuncRequest const & cmd,
                case LFUN_INSET_DIALOG_UPDATE:
                        status.enabled(true);
                        return true;
+               case LFUN_CAPTION_INSERT:
+                       status.enabled(!params().isInline());
+                       return true;
                default:
-                       return InsetERT::getStatus(cur, cmd, status);
+                       return InsetCollapsable::getStatus(cur, cmd, status);
        }
 }
 
@@ -219,14 +250,17 @@ bool InsetListings::getStatus(Cursor & cur, FuncRequest const & cmd,
 void InsetListings::setButtonLabel()
 {
        // FIXME UNICODE
-       setLabel(isOpen() ?  _("Listings") : getNewLabel(_("Listings")));
+       if (decoration() == InsetLayout::Classic)
+               setLabel(isOpen() ?  _("Listing") : getNewLabel(_("Listing")));
+       else
+               setLabel(getNewLabel(_("Listing")));
 }
 
 
 void InsetListings::validate(LaTeXFeatures & features) const
 {
        features.require("listings");
-       InsetERT::validate(features);
+       InsetCollapsable::validate(features);
 }
 
 
@@ -237,11 +271,27 @@ bool InsetListings::showInsetDialog(BufferView * bv) const
 }
 
 
-void InsetListings::getDrawFont(Font & font) const
+docstring InsetListings::getCaption(OutputParams const & runparams) const
 {
-       font = Font(Font::ALL_INHERIT, english_language);
-       font.setFamily(Font::TYPEWRITER_FAMILY);
-       font.setColor(Color::foreground);
+       if (paragraphs().empty())
+               return docstring();
+
+       ParagraphList::const_iterator pit = paragraphs().begin();
+       for (; pit != paragraphs().end(); ++pit) {
+               InsetList::const_iterator it = pit->insetList().begin();
+               for (; it != pit->insetList().end(); ++it) {
+                       Inset & inset = *it->inset;
+                       if (inset.lyxCode() == CAPTION_CODE) {
+                               odocstringstream ods;
+                               InsetCaption * ins =
+                                       static_cast<InsetCaption *>(it->inset);
+                               ins->getOptArg(ods, runparams);
+                               ins->getArgument(ods, runparams);
+                               return ods.str();
+                       }
+               }
+       }
+       return docstring();
 }