The caption inset patch by Georg, Martin and myself.

* buffer.C: increase LyX format to 257.

* lyxtextclass.C: increase FORMAT format to 3.

* buffer_funcs.C: 
  - setCaptionLabels(): new recursive function
  - setCaptions(): new function
  - updateLabels(): call setCaptions() for each paragraph.

* InsetCaption:
  - add a virtual destructor
  - overload InsetText' getStatus() and wide().
  - setLabel(): only set the new private member label_.
  - metrics(): don't set label here and correct for title metrics.
  - draw(): don't set label here
  - latex(): fix optional argument.
  - plaintext(): implement!

* InsetText:
  - add a virtual destructor
  - add virtual to getStatus() and wide().

*  output_latex.[Ch]: move latexOptArgInsets() out of anon namespace.

* text3.C: enable LFUN_CAPTION_INSERT


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@16948 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Abdelrazak Younes 2007-01-30 13:23:21 +00:00
parent 951e4e0a78
commit 500a5f959f
13 changed files with 322 additions and 67 deletions

View File

@ -73,7 +73,7 @@ format_relation = [("0_06", [200], generate_minor_versions("0.6" , 4)),
("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():

View File

@ -20,7 +20,7 @@
""" 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
@ -28,9 +28,13 @@ 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
####################################################################
@ -720,6 +724,99 @@ def revert_encodings(document):
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
#
@ -735,9 +832,11 @@ convert = [[246, []],
[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]],
@ -753,3 +852,4 @@ revert = [[255, [revert_encodings]],
if __name__ == "__main__":
pass

View File

@ -9,7 +9,7 @@
# 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
@ -76,6 +76,8 @@ def convert(lines):
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)
@ -118,6 +120,7 @@ def convert(lines):
latextype_line = -1
style = ""
maxcounter = 0
format = 1
while i < len(lines):
# Skip comments and empty lines
@ -129,13 +132,17 @@ def convert(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
@ -146,6 +153,63 @@ def convert(lines):
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:

View File

@ -298,6 +298,7 @@ Menuset
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

View File

@ -141,7 +141,7 @@ using std::string;
namespace {
int const LYX_FORMAT = 256;
int const LYX_FORMAT = 257;
} // namespace anon

View File

@ -38,6 +38,7 @@
#include "frontends/Alert.h"
#include "insets/insetbibitem.h"
#include "insets/insetcaption.h"
#include "insets/insetinclude.h"
#include "support/filetools.h"
@ -351,6 +352,67 @@ bool needEnumCounterReset(ParIterator const & it)
}
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)
{
@ -602,6 +664,11 @@ void updateLabels(Buffer const & buf, bool childonly)
// 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();

View File

@ -21,9 +21,12 @@
#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"
@ -90,44 +93,24 @@ void InsetCaption::cursorPos(BufferView const & bv,
}
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;
@ -149,11 +132,9 @@ void InsetCaption::draw(PainterInfo & pi, int x, int y) const
// 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);
}
@ -173,6 +154,31 @@ InsetBase * InsetCaption::editXY(LCursor & cur, int x, int 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
{
@ -181,18 +187,20 @@ int InsetCaption::latex(Buffer const & buf, odocstream & os,
// 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);
}

View File

@ -12,7 +12,6 @@
#ifndef INSETCAPTION_H
#define INSETCAPTION_H
#include "insettext.h"
#include "lyxtextclass.h"
@ -26,6 +25,8 @@ public:
///
InsetCaption(BufferParams const &);
///
virtual ~InsetCaption() {}
///
void write(Buffer const & buf, std::ostream & os) const;
///
void read(Buffer const & buf, LyXLex & lex);
@ -51,6 +52,10 @@ public:
///
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;
///
@ -61,17 +66,20 @@ public:
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_;
};

View File

@ -43,6 +43,9 @@ public:
explicit InsetText(BufferParams const &);
///
InsetText();
///
virtual ~InsetText() {}
/// empty inset to empty par
void clear();
///
@ -98,7 +101,7 @@ public:
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);
@ -133,7 +136,7 @@ public:
///
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; }

View File

@ -65,7 +65,7 @@ private:
};
int const FORMAT = 2;
int const FORMAT = 3;
bool layout2layout(FileName const & filename, FileName const & tempfile)

View File

@ -83,10 +83,6 @@ TeXDeeper(Buffer const & buf,
}
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,
@ -212,6 +208,8 @@ TeXEnvironment(Buffer const & buf,
return par;
}
}
int latexOptArgInsets(Buffer const & buf, Paragraph const & par,
odocstream & os, OutputParams const & runparams, int number)
@ -232,6 +230,8 @@ int latexOptArgInsets(Buffer const & buf, Paragraph const & par,
}
namespace {
ParagraphList::const_iterator
TeXOnePar(Buffer const & buf,
ParagraphList const & paragraphs,

View File

@ -25,6 +25,11 @@ class Encoding;
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.

View File

@ -1127,8 +1127,8 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
#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:
@ -1159,9 +1159,8 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
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: