("1_2", [220], generate_minor_versions("1.2" , 4)),
("1_3", [221], generate_minor_versions("1.3" , 7)),
("1_4", range(222,246), generate_minor_versions("1.4" , 3)),
- ("1_5", range(246,257), generate_minor_versions("1.5" , 0))]
+ ("1_5", range(246,258), generate_minor_versions("1.5" , 0))]
def formats_list():
""" Convert files to the file format generated by lyx 1.5"""
import re
-from parser_tools import find_token, find_token_exact, find_tokens, find_end_of, get_value
+from parser_tools import find_token, find_token_backwards, find_token_exact, find_tokens, find_end_of, get_value
from LyX import get_encoding
# Private helper functions
def find_end_of_inset(lines, i):
- " Find beginning of inset, where lines[i] is included."
+ " Find end of inset, where lines[i] is included."
return find_end_of(lines, i, "\\begin_inset", "\\end_inset")
+def find_end_of_layout(lines, i):
+ " Find end of layout, where lines[i] is included."
+ return find_end_of(lines, i, "\\begin_layout", "\\end_layout")
+
# End of helper functions
####################################################################
document.inputencoding = get_value(document.header, "\\inputencoding", 0)
+def convert_caption(document):
+ " Convert caption layouts to caption insets. "
+ i = 0
+ while 1:
+ i = find_token(document.body, "\\begin_layout Caption", i)
+ if i == -1:
+ return
+ j = find_end_of_layout(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Missing `\\end_layout'.")
+ return
+
+ document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
+ document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
+ "\\begin_inset Caption", "",
+ "\\begin_layout %s" % document.default_layout]
+ i = i + 1
+
+
+def revert_caption(document):
+ " Convert caption insets to caption layouts. "
+ " This assumes that the text class has a caption style. "
+ i = 0
+ while 1:
+ i = find_token(document.body, "\\begin_inset Caption", i)
+ if i == -1:
+ return
+
+ # We either need to delete the previous \begin_layout line, or we
+ # need to end the previous layout if this inset is not in the first
+ # position of the paragraph.
+ layout_before = find_token_backwards(document.body, "\\begin_layout", i)
+ if layout_before == -1:
+ document.warning("Malformed LyX document: Missing `\\begin_layout'.")
+ return
+ layout_line = document.body[layout_before]
+ del_layout_before = True
+ l = layout_before + 1
+ while l < i:
+ if document.body[l] != "":
+ del_layout_before = False
+ break
+ l = l + 1
+ if del_layout_before:
+ del document.body[layout_before:i]
+ i = layout_before
+ else:
+ document.body[i:i] = ["\\end_layout", ""]
+ i = i + 2
+
+ # Find start of layout in the inset and end of inset
+ j = find_token(document.body, "\\begin_layout", i)
+ if j == -1:
+ document.warning("Malformed LyX document: Missing `\\begin_layout'.")
+ return
+ k = find_end_of_inset(document.body, i)
+ if k == -1:
+ document.warning("Malformed LyX document: Missing `\\end_inset'.")
+ return
+
+ # We either need to delete the following \end_layout line, or we need
+ # to restart the old layout if this inset is not at the paragraph end.
+ layout_after = find_token(document.body, "\\end_layout", k)
+ if layout_after == -1:
+ document.warning("Malformed LyX document: Missing `\\end_layout'.")
+ return
+ del_layout_after = True
+ l = k + 1
+ while l < layout_after:
+ if document.body[l] != "":
+ del_layout_after = False
+ break
+ l = l + 1
+ if del_layout_after:
+ del document.body[k+1:layout_after+1]
+ else:
+ document.body[k+1:k+1] = [layout_line, ""]
+
+ # delete \begin_layout and \end_inset and replace \begin_inset with
+ # "\begin_layout Caption". This works because we can only have one
+ # paragraph in the caption inset: The old \end_layout will be recycled.
+ del document.body[k]
+ if document.body[k] == "":
+ del document.body[k]
+ del document.body[j]
+ if document.body[j] == "":
+ del document.body[j]
+ document.body[i] = "\\begin_layout Caption"
+ if document.body[i+1] == "":
+ del document.body[i+1]
+ i = i + 1
+
+
##
# Conversion hub
#
[253, []],
[254, [convert_esint]],
[255, []],
- [256, []]]
+ [256, []],
+ [257, [convert_caption]]]
-revert = [[255, [revert_encodings]],
+revert = [[256, [revert_caption]],
+ [255, [revert_encodings]],
[254, [revert_clearpage, revert_cleardoublepage]],
[253, [revert_esint]],
[252, [revert_nomenclature, revert_printnomenclature]],
if __name__ == "__main__":
pass
+
# Full author contact details are available in file CREDITS
-# This script will update a .layout file to format 2
+# This script will update a .layout file to format 3
import os, re, string, sys
re_LabelStringAppendix = re.compile(r'^(\s*)(LabelStringAppendix)(\s+)(("[^"]+")|(\S+))', re.IGNORECASE)
re_LatexType = re.compile(r'^(\s*)(LatexType)(\s+)(\S+)', re.IGNORECASE)
re_Style = re.compile(r'^(\s*)(Style)(\s+)(\S+)', re.IGNORECASE)
+ re_CopyStyle = re.compile(r'^(\s*)(CopyStyle)(\s+)(\S+)', re.IGNORECASE)
+ re_NoStyle = re.compile(r'^(\s*)(NoStyle)(\s+)(\S+)', re.IGNORECASE)
re_End = re.compile(r'^(\s*)(End)(\s*)$', re.IGNORECASE)
# counters for sectioning styles (hardcoded in 1.3)
latextype_line = -1
style = ""
maxcounter = 0
+ format = 1
while i < len(lines):
# Skip comments and empty lines
if (only_comment):
match = re_Format.match(lines[i])
if match:
- format = match.group(4)
- if format == '2':
+ format = int(match.group(4))
+ if format == 2:
+ lines[i] = "Format 3"
+ only_comment = 0
+ elif format == 3:
# nothing to do
return
- error('Cannot convert file format %s' % format)
+ else:
+ error('Cannot convert file format %s' % format)
else:
- lines.insert(i, "Format 2")
+ lines.insert(i, "Format 3")
only_comment = 0
continue
i = i + 1
continue
+ if format == 2:
+ caption = []
+
+ # delete caption styles
+ match = re_Style.match(lines[i])
+ if match:
+ style = string.lower(match.group(4))
+ if style == "caption":
+ del lines[i]
+ while i < len(lines) and not re_End.match(lines[i]):
+ caption.append(lines[i])
+ del lines[i]
+ if i == len(lines):
+ error('Incomplete caption style.')
+ else:
+ del lines[i]
+ continue
+
+ # delete undefinition of caption styles
+ match = re_NoStyle.match(lines[i])
+ if match:
+ style = string.lower(match.group(4))
+ if style == "caption":
+ del lines[i]
+ continue
+
+ # replace the CopyStyle statement with the definition of the real
+ # style. This may result in duplicate statements, but that is OK
+ # since the second one will overwrite the first one.
+ match = re_CopyStyle.match(lines[i])
+ if match:
+ style = string.lower(match.group(4))
+ if style == "caption":
+ if len(caption) > 0:
+ lines[i:i+1] = caption
+ else:
+ # FIXME: This style comes from an include file, we
+ # should replace the real style and not this default.
+ lines[i:i+1] = [' Margin First_Dynamic',
+ ' LatexType Command',
+ ' LatexName caption',
+ ' NeedProtect 1',
+ ' LabelSep xx',
+ ' ParSkip 0.4',
+ ' TopSep 0.5',
+ ' Align Center',
+ ' AlignPossible Center',
+ ' LabelType Sensitive',
+ ' LabelString "Senseless!"',
+ ' OptionalArgs 1',
+ ' LabelFont',
+ ' Series Bold',
+ ' EndFont']
+
+ i = i + 1
+ continue
+
# Delete MaxCounter and remember the value of it
match = re_MaxCounter.match(lines[i])
if match:
Item "Citation...|C" "dialog-show-new-inset citation"
Item "Cross-Reference...|R" "dialog-show-new-inset ref"
Item "Label...|L" "label-insert"
+ Item "Caption..." "caption-insert"
Item "Index Entry|d" "index-insert"
Item "Glossary Entry|y" "nomencl-insert"
Separator
namespace {
-int const LYX_FORMAT = 256;
+int const LYX_FORMAT = 257;
} // namespace anon
#include "frontends/Alert.h"
#include "insets/insetbibitem.h"
+#include "insets/insetcaption.h"
#include "insets/insetinclude.h"
#include "support/filetools.h"
}
+void setCaptionLabels(InsetBase & inset, Floating const & fl,
+ Counters & counters)
+{
+ LyXText * text = inset.getText(0);
+ if (!text)
+ return;
+
+ ParagraphList & pars = text->paragraphs();
+ if (pars.empty())
+ return;
+
+ // FIXME UNICODE
+ docstring const counter = from_ascii(fl.type());
+ docstring const label = from_utf8(fl.name());
+
+ ParagraphList::iterator p = pars.begin();
+ for (; p != pars.end(); ++p) {
+ InsetList::iterator it2 = p->insetlist.begin();
+ InsetList::iterator end2 = p->insetlist.end();
+ // Any caption within this float should have the same
+ // label prefix but different numbers.
+ for (; it2 != end2; ++it2) {
+ InsetBase & icap = *it2->inset;
+ // Look deeper just in case.
+ setCaptionLabels(icap, fl, counters);
+ if (icap.lyxCode() == InsetBase::CAPTION_CODE) {
+ // We found a caption!
+ counters.step(counter);
+ int number = counters.value(counter);
+ static_cast<InsetCaption &>(icap).setCount(number);
+ static_cast<InsetCaption &>(icap).setLabel(label);
+ }
+ }
+ }
+}
+
+
+void setCaptions(Paragraph & par, LyXTextClass const & textclass)
+{
+ if (par.insetlist.empty())
+ return;
+
+ Counters & counters = textclass.counters();
+
+ InsetList::iterator it = par.insetlist.begin();
+ InsetList::iterator end = par.insetlist.end();
+ for (; it != end; ++it) {
+ InsetBase & inset = *it->inset;
+ if (inset.lyxCode() != InsetBase::FLOAT_CODE
+ && inset.lyxCode() != InsetBase::WRAP_CODE)
+ continue;
+
+ docstring const & type = inset.getInsetName();
+ if (type.empty())
+ continue;
+
+ Floating const & fl = textclass.floats().getType(to_ascii(type));
+ setCaptionLabels(inset, fl, counters);
+ }
+}
+
// set the label of a paragraph. This includes the counters.
void setLabel(Buffer const & buf, ParIterator & it, LyXTextClass const & textclass)
{
// set the counter for this paragraph
setLabel(buf, it, textclass);
+ // It is better to set the captions after setLabel because
+ // the caption number might need the section number in the
+ // future.
+ setCaptions(*it, textclass);
+
// Now included docs
InsetList::const_iterator iit = it->insetlist.begin();
InsetList::const_iterator end = it->insetlist.end();
#include "BufferView.h"
#include "Floating.h"
#include "FloatList.h"
+#include "funcrequest.h"
+#include "FuncStatus.h"
#include "gettext.h"
#include "LColor.h"
#include "metricsinfo.h"
+#include "output_latex.h"
#include "paragraph.h"
#include "frontends/FontMetrics.h"
}
-void InsetCaption::setLabel(LCursor & cur) const
+void InsetCaption::setLabel(docstring const & label)
{
- // Set caption label _only_ if the cursor is in _this_ float:
- if (cur.top().text() == &text_) {
- string s;
- size_t i = cur.depth();
- while (i > 0) {
- --i;
- InsetBase * const in = &cur[i].inset();
- if (in->lyxCode() == InsetBase::FLOAT_CODE ||
- in->lyxCode() == InsetBase::WRAP_CODE) {
- s = to_utf8(in->getInsetName());
- break;
- }
- }
- Floating const & fl = textclass_.floats().getType(s);
- s = fl.name();
- docstring num;
- if (s.empty())
- s = "Senseless";
- else
- num = convert<docstring>(counter_);
-
- // Generate the label
- label = bformat(from_ascii("%1$s %2$s:"), _(s), num);
- }
+ label_ = _(to_ascii(label));
}
bool InsetCaption::metrics(MetricsInfo & mi, Dimension & dim) const
{
mi.base.textwidth -= 2 * TEXT_TO_INSET_OFFSET;
- LCursor cur = mi.base.bv->cursor();
- setLabel(cur);
- labelwidth_ = theFontMetrics(mi.base.font).width(label);
+ docstring const number = convert<docstring>(counter_);
+ full_label_ = bformat(from_ascii("%1$s %2$s:"), label_, number);
+ labelwidth_ = theFontMetrics(mi.base.font).width(full_label_);
dim.wid = labelwidth_;
Dimension textdim;
InsetText::metrics(mi, textdim);
+ // Correct for button width, and re-fit
+ mi.base.textwidth -= dim.wid;
+ InsetText::metrics(mi, textdim);
dim.des = std::max(dim.des - textdim.asc + dim.asc, textdim.des);
dim.asc = textdim.asc;
dim.wid += textdim.wid;
// the text inset or the paragraph?
// We should also draw the float number (Lgb)
- // See if we can find the name of the float this caption
- // belongs to.
- LCursor cur = pi.base.bv->cursor();
- setLabel(cur);
- labelwidth_ = pi.pain.text(x, y, label, pi.base.font);
+ // Answer: the text inset (in buffer_funcs.C: setCaption).
+
+ labelwidth_ = pi.pain.text(x, y, full_label_, pi.base.font);
InsetText::draw(pi, x + labelwidth_, y);
setPosCache(pi, x, y);
}
}
+bool InsetCaption::getStatus(LCursor & cur, FuncRequest const & cmd,
+ FuncStatus & status) const
+{
+ switch (cmd.action) {
+
+ case LFUN_CAPTION_INSERT:
+ case LFUN_FLOAT_INSERT:
+ case LFUN_FLOAT_WIDE_INSERT:
+ case LFUN_WRAP_INSERT:
+ case LFUN_PARAGRAPH_MOVE_UP:
+ case LFUN_PARAGRAPH_MOVE_DOWN:
+ case LFUN_BREAK_PARAGRAPH:
+ case LFUN_BREAK_PARAGRAPH_KEEP_LAYOUT:
+ case LFUN_BREAK_PARAGRAPH_SKIP:
+ case LFUN_PARAGRAPH_SPACING:
+ case LFUN_PAGEBREAK_INSERT:
+ status.enabled(false);
+ return true;
+
+ default:
+ return InsetText::getStatus(cur, cmd, status);
+ }
+}
+
+
int InsetCaption::latex(Buffer const & buf, odocstream & os,
OutputParams const & runparams) const
{
// This code is currently only able to handle the simple
// \caption{...}, later we will make it take advantage
// of the one of the caption packages. (Lgb)
- odocstringstream ost;
- int const l = InsetText::latex(buf, ost, runparams);
- os << "\\caption{" << ost.str() << "}\n";
+ os << "\\caption";
+ int l = latexOptArgInsets(buf, paragraphs()[0], os, runparams, 1);
+ os << '{';
+ l += InsetText::latex(buf, os, runparams);
+ os << "}\n";
return l + 1;
}
-int InsetCaption::plaintext(Buffer const & /*buf*/, odocstream & /*os*/,
- OutputParams const & /*runparams*/) const
+int InsetCaption::plaintext(Buffer const & buf, odocstream & os,
+ OutputParams const & runparams) const
{
- // FIXME: Implement me!
- return 0;
+ os << full_label_ << ' ';
+ return InsetText::plaintext(buf, os, runparams);
}
#ifndef INSETCAPTION_H
#define INSETCAPTION_H
-
#include "insettext.h"
#include "lyxtextclass.h"
///
InsetCaption(BufferParams const &);
///
+ virtual ~InsetCaption() {}
+ ///
void write(Buffer const & buf, std::ostream & os) const;
///
void read(Buffer const & buf, LyXLex & lex);
///
virtual InsetBase * editXY(LCursor & cur, int x, int y);
///
+ virtual bool getStatus(LCursor & cur, FuncRequest const & cmd, FuncStatus &) const;
+ ///
+ virtual bool wide() const { return false; }
+ ///
virtual int latex(Buffer const & buf, odocstream & os,
OutputParams const &) const;
///
OutputParams const & runparams) const;
///
void setCount(int c) { counter_ = c; }
-private:
///
- void setLabel(LCursor & cur) const;
+ void setLabel(docstring const & label);
+
+private:
///
virtual std::auto_ptr<InsetBase> doClone() const;
///
- mutable docstring label;
+ mutable docstring full_label_;
///
mutable int labelwidth_;
///
- mutable int counter_;
+ docstring label_;
+ ///
+ int counter_;
///
LyXTextClass const & textclass_;
};
explicit InsetText(BufferParams const &);
///
InsetText();
+ ///
+ virtual ~InsetText() {}
+
/// empty inset to empty par
void clear();
///
return (i == 0) ? const_cast<LyXText*>(&text_) : 0;
}
///
- bool getStatus(LCursor & cur, FuncRequest const & cmd, FuncStatus &) const;
+ virtual bool getStatus(LCursor & cur, FuncRequest const & cmd, FuncStatus &) const;
/// set the change for the entire inset
void setChange(Change const & change);
///
InsetText(InsetText const &);
///
- bool wide() const { return wide_inset_; }
+ virtual bool wide() const { return wide_inset_; }
///
void setWide(bool wide_inset) { wide_inset_ = wide_inset; }
};
-int const FORMAT = 2;
+int const FORMAT = 3;
bool layout2layout(FileName const & filename, FileName const & tempfile)
}
-int latexOptArgInsets(Buffer const & buf, Paragraph const & par,
- odocstream & os, OutputParams const & runparams, int number);
-
-
ParagraphList::const_iterator
TeXEnvironment(Buffer const & buf,
ParagraphList const & paragraphs,
return par;
}
+}
+
int latexOptArgInsets(Buffer const & buf, Paragraph const & par,
odocstream & os, OutputParams const & runparams, int number)
}
+namespace {
+
ParagraphList::const_iterator
TeXOnePar(Buffer const & buf,
ParagraphList const & paragraphs,
class OutputParams;
class TexRow;
+/// Export up to \p number optarg insets
+int latexOptArgInsets(Buffer const & buf, Paragraph const & par,
+ odocstream & os, OutputParams const & runparams,
+ int number);
+
/** Export \p paragraphs of buffer \p buf to LaTeX.
Don't use a temporary stringstream for \p os if the final output is
supposed to go to a file.
#if 0
case LFUN_LIST_INSERT:
case LFUN_THEOREM_INSERT:
- case LFUN_CAPTION_INSERT:
#endif
+ case LFUN_CAPTION_INSERT:
case LFUN_NOTE_INSERT:
case LFUN_CHARSTYLE_INSERT:
case LFUN_BOX_INSERT:
case LFUN_WRAP_INSERT:
doInsertInset(cur, this, cmd, true, true);
cur.posRight();
- // FIXME: the "Caption" name should not be hardcoded,
- // but given by the float definition.
- cur.dispatch(FuncRequest(LFUN_LAYOUT, "Caption"));
+ cur.dispatch(FuncRequest(LFUN_CAPTION_INSERT));
+ updateLabels(cur.buffer());
break;
case LFUN_INDEX_INSERT: