mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-28 20:45:47 +00:00
The algorithm used for breaking a paragraph in LaTeX export is changed for avoiding spurious blank lines causing too much vertical space. This change is tied to the introduction of a new inset (with two different specializations) helping in either outputing LaTeX paragraph breaks or separating environments in LyX. Both of the above goals were previously achieved by the ---Separator--- layout and can now be accomplished by the new inset in a more natural way. As an example, after leaving an environment by hitting the Return key for two times, a third return automatically inserts a parbreak inset, which is equivalent to the old separator layout, i.e., it also introduces a blank line in the output. If this blank line is not wanted, the parbreak separator can be changed to a plain separator by a right click of the mouse. Of course, an environment can still be separated by the following one by using the Alt+P+Return shortcut (or the corresponding menu key), but now the plain separator inset is used instead of the old separator layout, such that no blank line occurs in the LaTeX output. Old documents are converted such that the LaTeX output remains unchanged. As a result of this conversion, the old separator layout is replaced by the new parbreak inset, which may also appear in places where the old algorithm was introducing blank lines while the new one is not. Note that not all blank lines were actually affecting the LaTeX output, because a blank line is simply ignored by the TeX engine when it occurs in the so called "vertical mode" (e.g., after an alignment environment). The old ---Separator--- layout is now gone and old layout files using it are also automatically converted. Round trip conversions between old and new format should leave a document unchanged. This means that the new behavior about paragraph breaking is not "carried back" to the old format. Indeed, this would need introducing special LaTeX commands in ERT that would accumulate in roundtrip conversions, horribly cluttering the document. So, when converting a modified document to old formats, the LaTeX output may slightly differ in vertical spacing if the document is processed by an old version of LyX. In other words, forward compatibility is guaranteed, but not backwards.
This commit is contained in:
parent
2ebcf38493
commit
c668ebf611
@ -11,6 +11,14 @@ adjustments are made to tex2lyx and bugs are fixed in lyx2lyx.
|
||||
|
||||
-----------------------
|
||||
|
||||
2014-05-05 Enrico Forestieri <forenr@lyx.org>
|
||||
* Format incremented to 475
|
||||
New Separator insets. The parbreak separator introduces a LaTeX
|
||||
paragraph break in the output. The plain separator does nothing
|
||||
and its purpose is replacing the Separator layout for separating
|
||||
environments. The new parbreak separator is roughly equivalent
|
||||
to the old Separator layout.
|
||||
|
||||
2013-05-30 Richard Heck <rgheck@lyx.org>
|
||||
* Format increments to 474: dummy format for conversion of Chunk layouts
|
||||
to insets
|
||||
|
@ -84,7 +84,7 @@ format_relation = [("0_06", [200], minor_versions("0.6" , 4)),
|
||||
("1_6", range(277,346), minor_versions("1.6" , 10)),
|
||||
("2_0", range(346,414), minor_versions("2.0", 8)),
|
||||
("2_1", range(414,475), minor_versions("2.1", 0)),
|
||||
("2_2", [], minor_versions("2.2", 0))
|
||||
("2_2", range(475,476), minor_versions("2.2", 0))
|
||||
]
|
||||
|
||||
####################################################################
|
||||
|
@ -34,6 +34,9 @@ import sys, os
|
||||
# put_cmd_in_ert, lyx2latex, latex_length, revert_flex_inset, \
|
||||
# revert_font_attrs, hex2ratio, str2bool
|
||||
|
||||
from parser_tools import find_token, find_token_backwards, find_re, \
|
||||
find_end_of_inset, find_end_of_layout, find_nonempty_line, \
|
||||
get_containing_layout, get_value, check_token
|
||||
|
||||
###############################################################################
|
||||
###
|
||||
@ -41,16 +44,208 @@ import sys, os
|
||||
###
|
||||
###############################################################################
|
||||
|
||||
def convert_separator(document):
|
||||
"""
|
||||
Convert layout separators to separator insets and add (LaTeX) paragraph
|
||||
breaks in order to mimic previous LaTeX export.
|
||||
"""
|
||||
|
||||
parins = ["\\begin_inset Separator parbreak", "\\end_inset", ""]
|
||||
parlay = ["\\begin_layout Standard", "\\begin_inset Separator parbreak",
|
||||
"\\end_inset", "", "\\end_layout", ""]
|
||||
sty_dict = {
|
||||
"family" : "default",
|
||||
"series" : "default",
|
||||
"shape" : "default",
|
||||
"size" : "default",
|
||||
"bar" : "default",
|
||||
"color" : "inherit"
|
||||
}
|
||||
|
||||
i = 0
|
||||
while 1:
|
||||
i = find_token(document.body, "\\begin_deeper", i)
|
||||
if i == -1:
|
||||
break
|
||||
|
||||
j = find_token_backwards(document.body, "\\end_layout", i-1)
|
||||
if j != -1:
|
||||
# reset any text style before inserting the inset
|
||||
lay = get_containing_layout(document.body, j-1)
|
||||
if lay != False:
|
||||
content = "\n".join(document.body[lay[1]:lay[2]])
|
||||
for val in sty_dict.keys():
|
||||
if content.find("\\%s" % val) != -1:
|
||||
document.body[j:j] = ["\\%s %s" % (val, sty_dict[val])]
|
||||
i = i + 1
|
||||
j = j + 1
|
||||
document.body[j:j] = parins
|
||||
i = i + len(parins) + 1
|
||||
else:
|
||||
i = i + 1
|
||||
|
||||
i = 0
|
||||
while 1:
|
||||
i = find_token(document.body, "\\align", i)
|
||||
if i == -1:
|
||||
break
|
||||
|
||||
lay = get_containing_layout(document.body, i)
|
||||
if lay != False and lay[0] == "Plain Layout":
|
||||
i = i + 1
|
||||
continue
|
||||
|
||||
j = find_token_backwards(document.body, "\\end_layout", i-1)
|
||||
if j != -1:
|
||||
lay = get_containing_layout(document.body, j-1)
|
||||
if lay != False and lay[0] == "Standard" \
|
||||
and find_token(document.body, "\\align", lay[1], lay[2]) == -1 \
|
||||
and find_token(document.body, "\\begin_inset VSpace", lay[1], lay[2]) == -1:
|
||||
# reset any text style before inserting the inset
|
||||
content = "\n".join(document.body[lay[1]:lay[2]])
|
||||
for val in sty_dict.keys():
|
||||
if content.find("\\%s" % val) != -1:
|
||||
document.body[j:j] = ["\\%s %s" % (val, sty_dict[val])]
|
||||
i = i + 1
|
||||
j = j + 1
|
||||
document.body[j:j] = parins
|
||||
i = i + len(parins) + 1
|
||||
else:
|
||||
i = i + 1
|
||||
else:
|
||||
i = i + 1
|
||||
|
||||
regexp = re.compile(r'^\\begin_layout (?:(-*)|(\s*))(Separator|EndOfSlide)(?:(-*)|(\s*))$', re.IGNORECASE)
|
||||
|
||||
i = 0
|
||||
while 1:
|
||||
i = find_re(document.body, regexp, 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
|
||||
|
||||
lay = get_containing_layout(document.body, j-1)
|
||||
if lay != False:
|
||||
lines = document.body[lay[3]:lay[2]]
|
||||
else:
|
||||
lines = []
|
||||
|
||||
document.body[i:j+1] = parlay
|
||||
if len(lines) > 0:
|
||||
document.body[i+1:i+1] = lines
|
||||
|
||||
i = i + len(parlay) + len(lines) + 1
|
||||
|
||||
|
||||
def revert_separator(document):
|
||||
" Revert separator insets to layout separators "
|
||||
|
||||
parsep = ["\\begin_layout --Separator--", "", "\\end_layout", ""]
|
||||
comert = ["\\begin_inset ERT", "status collapsed", "",
|
||||
"\\begin_layout Plain Layout", "%", "\\end_layout",
|
||||
"", "\\end_inset", ""]
|
||||
empert = ["\\begin_inset ERT", "status collapsed", "",
|
||||
"\\begin_layout Plain Layout", " ", "\\end_layout",
|
||||
"", "\\end_inset", ""]
|
||||
|
||||
i = 0
|
||||
while 1:
|
||||
i = find_token(document.body, "\\begin_inset Separator", i)
|
||||
if i == -1:
|
||||
return
|
||||
|
||||
lay = get_containing_layout(document.body, i)
|
||||
if lay == False:
|
||||
document.warning("Malformed LyX document: Can't convert separator inset at line " + str(i))
|
||||
i = i + 1
|
||||
continue
|
||||
|
||||
layoutname = lay[0]
|
||||
beg = lay[1]
|
||||
end = lay[2]
|
||||
kind = get_value(document.body, "\\begin_inset Separator", i, i+1, "plain").split()[1]
|
||||
before = document.body[beg+1:i]
|
||||
something_before = len(before) > 0 and len("".join(before)) > 0
|
||||
j = find_end_of_inset(document.body, i)
|
||||
after = document.body[j+1:end]
|
||||
something_after = len(after) > 0 and len("".join(after)) > 0
|
||||
if kind == "plain":
|
||||
beg = beg + len(before) + 1
|
||||
elif something_before:
|
||||
document.body[i:i] = ["\\end_layout", ""]
|
||||
i = i + 2
|
||||
j = j + 2
|
||||
beg = i
|
||||
end = end + 2
|
||||
|
||||
if kind == "plain":
|
||||
if something_after:
|
||||
document.body[beg:j+1] = empert
|
||||
i = i + len(empert)
|
||||
else:
|
||||
document.body[beg:j+1] = comert
|
||||
i = i + len(comert)
|
||||
else:
|
||||
if something_after:
|
||||
if layoutname == "Standard":
|
||||
if not something_before:
|
||||
document.body[beg:j+1] = parsep
|
||||
i = i + len(parsep)
|
||||
document.body[i:i] = ["", "\\begin_layout Standard"]
|
||||
i = i + 2
|
||||
else:
|
||||
document.body[beg:j+1] = ["\\begin_layout Standard"]
|
||||
i = i + 1
|
||||
else:
|
||||
document.body[beg:j+1] = ["\\begin_deeper"]
|
||||
i = i + 1
|
||||
end = end + 1 - (j + 1 - beg)
|
||||
if not something_before:
|
||||
document.body[i:i] = parsep
|
||||
i = i + len(parsep)
|
||||
end = end + len(parsep)
|
||||
document.body[i:i] = ["\\begin_layout Standard"]
|
||||
document.body[end+2:end+2] = ["", "\\end_deeper", ""]
|
||||
i = i + 4
|
||||
else:
|
||||
next_par_is_aligned = False
|
||||
k = find_nonempty_line(document.body, end+1)
|
||||
if k != -1 and check_token(document.body[k], "\\begin_layout"):
|
||||
lay = get_containing_layout(document.body, k)
|
||||
next_par_is_aligned = lay != False and \
|
||||
find_token(document.body, "\\align", lay[1], lay[2]) != -1
|
||||
if k != -1 and not next_par_is_aligned \
|
||||
and not check_token(document.body[k], "\\end_deeper") \
|
||||
and not check_token(document.body[k], "\\begin_deeper"):
|
||||
if layoutname == "Standard":
|
||||
document.body[beg:j+1] = ["\\begin_layout --Separator--"]
|
||||
i = i + 1
|
||||
else:
|
||||
document.body[beg:j+1] = ["\\begin_deeper", "\\begin_layout --Separator--"]
|
||||
end = end + 2 - (j + 1 - beg)
|
||||
document.body[end+1:end+1] = ["", "\\end_deeper", ""]
|
||||
i = i + 3
|
||||
else:
|
||||
del document.body[i:end+1]
|
||||
|
||||
i = i + 1
|
||||
|
||||
|
||||
##
|
||||
# Conversion hub
|
||||
#
|
||||
|
||||
supported_versions = ["2.2.0","2.2"]
|
||||
convert = [#[475, []]
|
||||
convert = [
|
||||
[475, [convert_separator]],
|
||||
]
|
||||
|
||||
revert = [#[474, []]
|
||||
revert = [
|
||||
[474, [revert_separator]]
|
||||
]
|
||||
|
||||
|
||||
|
@ -165,6 +165,9 @@ import os, re, string, sys
|
||||
# Incremented to format 49, 10 Feb 2014 by gb
|
||||
# Change default of "ResetsFont" tag to false
|
||||
|
||||
# Incremented to format 50, 9 May 2014 by forenr
|
||||
# Removal of "Separator" layouts
|
||||
|
||||
# Do not forget to document format change in Customization
|
||||
# Manual (section "Declaring a new text class").
|
||||
|
||||
@ -172,7 +175,7 @@ import os, re, string, sys
|
||||
# development/tools/updatelayouts.sh script to update all
|
||||
# layout files to the new format.
|
||||
|
||||
currentFormat = 49
|
||||
currentFormat = 50
|
||||
|
||||
|
||||
def usage(prog_name):
|
||||
@ -270,6 +273,7 @@ def convert(lines):
|
||||
re_QInsetLayout2 = re.compile(r'^\s*InsetLayout\s+"([^"]+)"\s*$', re.IGNORECASE)
|
||||
re_IsFlex = re.compile(r'\s*LyXType.*$', re.IGNORECASE)
|
||||
re_CopyStyle2 = re.compile(r'(\s*CopyStyle\s+)"?([^"]+)"?\s*$')
|
||||
re_Separator = re.compile(r'^(?:(-*)|(\s*))(Separator|EndOfSlide)(?:(-*)|(\s*))$', re.IGNORECASE)
|
||||
# for categories
|
||||
re_Declaration = re.compile(r'^#\s*\\Declare\w+Class.*$')
|
||||
re_ExtractCategory = re.compile(r'^(#\s*\\Declare\w+Class(?:\[[^]]*?\])?){([^(]+?)\s+\(([^)]+?)\)\s*}\s*$')
|
||||
@ -395,6 +399,63 @@ def convert(lines):
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if format == 49:
|
||||
separator = []
|
||||
|
||||
# delete separator styles
|
||||
match = re_Style.match(lines[i])
|
||||
if match:
|
||||
style = string.lower(match.group(4))
|
||||
if re_Separator.match(style):
|
||||
del lines[i]
|
||||
while i < len(lines) and not re_End.match(lines[i]):
|
||||
separator.append(lines[i])
|
||||
del lines[i]
|
||||
if i == len(lines):
|
||||
error('Incomplete separator style.')
|
||||
else:
|
||||
del lines[i]
|
||||
continue
|
||||
|
||||
# delete undefinition of separator styles
|
||||
match = re_NoStyle.match(lines[i])
|
||||
if match:
|
||||
style = string.lower(match.group(4))
|
||||
if re_Separator.match(style):
|
||||
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 re_Separator.match(style):
|
||||
if len(separator) > 0:
|
||||
lines[i:i+1] = separator
|
||||
else:
|
||||
# FIXME: If this style was redefined in an include file,
|
||||
# we should replace the real style and not this default.
|
||||
lines[i:i+1] = [' Category MainText',
|
||||
' KeepEmpty 1',
|
||||
' Margin Dynamic',
|
||||
' LatexType Paragraph',
|
||||
' LatexName dummy',
|
||||
' ParIndent MM',
|
||||
' Align Block',
|
||||
' LabelType Static',
|
||||
' LabelString "--- Separate Environment ---"',
|
||||
' LabelFont',
|
||||
' Family Roman',
|
||||
' Series Medium',
|
||||
' Size Normal',
|
||||
' Color Blue',
|
||||
' EndFont',
|
||||
' HTMLLabel NONE']
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if format == 48:
|
||||
# The default of ResetsFont in LyX changed from true to false,
|
||||
# because it is now used for all InsetLayouts, not only flex ones.
|
||||
|
@ -301,6 +301,14 @@ Menuset
|
||||
Item "Justified Line Break|J" "inset-modify newline linebreak"
|
||||
End
|
||||
|
||||
#
|
||||
# InsetNewline context menu
|
||||
#
|
||||
Menu "context-separator"
|
||||
Item "Plain Separator|P" "inset-modify separator plain"
|
||||
Item "Paragraph Break|B" "inset-modify separator parbreak"
|
||||
End
|
||||
|
||||
#
|
||||
# Edit context menu
|
||||
#
|
||||
|
@ -108,6 +108,7 @@ void Bidi::computeTables(Paragraph const & par,
|
||||
pos_type const pos =
|
||||
(is_space && lpos + 1 <= end_ &&
|
||||
!par.isLineSeparator(lpos + 1) &&
|
||||
!par.isEnvSeparator(lpos + 1) &&
|
||||
!par.isNewline(lpos + 1))
|
||||
? lpos + 1 : lpos;
|
||||
|
||||
|
@ -457,6 +457,7 @@ enum FuncCode
|
||||
LFUN_VC_COPY, // gb 20130205
|
||||
// 355
|
||||
LFUN_SPELLING_CONTINUOUSLY, // vfr, 20130324
|
||||
LFUN_SEPARATOR_INSERT, // ef 20140502
|
||||
LFUN_LASTACTION // end of the table
|
||||
};
|
||||
|
||||
|
@ -625,6 +625,15 @@ void LyXAction::init()
|
||||
* \endvar
|
||||
*/
|
||||
{ LFUN_NEWLINE_INSERT, "newline-insert", Noop, Edit },
|
||||
/*!
|
||||
* \var lyx::FuncCode lyx::LFUN_SEPARATOR_INSERT
|
||||
* \li Action: Inserts an environment separator or paragraph break.
|
||||
* \li Syntax: separator-insert [<ARG>]
|
||||
* \li Params: <ARG>: <plain|parbreak> default: plain
|
||||
* \li Origin: ef, 2 May 2014
|
||||
* \endvar
|
||||
*/
|
||||
{ LFUN_SEPARATOR_INSERT, "separator-insert", Noop, Edit },
|
||||
/*!
|
||||
* \var lyx::FuncCode lyx::LFUN_ESCAPE
|
||||
* \li Action: Clears the selection. If no text is selected call #LFUN_FINISHED_FORWARD.
|
||||
|
@ -575,6 +575,7 @@ SOURCEFILESINSETS = \
|
||||
insets/InsetQuotes.cpp \
|
||||
insets/InsetRef.cpp \
|
||||
insets/InsetScript.cpp \
|
||||
insets/InsetSeparator.cpp \
|
||||
insets/InsetSpace.cpp \
|
||||
insets/InsetSpecialChar.cpp \
|
||||
insets/InsetTabular.cpp \
|
||||
@ -633,6 +634,7 @@ HEADERFILESINSETS = \
|
||||
insets/InsetQuotes.h \
|
||||
insets/InsetRef.h \
|
||||
insets/InsetScript.h \
|
||||
insets/InsetSeparator.h \
|
||||
insets/InsetSpace.h \
|
||||
insets/InsetSpecialChar.h \
|
||||
insets/InsetTabular.h \
|
||||
|
@ -1054,7 +1054,7 @@ void Paragraph::Private::latexInset(BufferParams const & bparams,
|
||||
}
|
||||
|
||||
// FIXME: move this to InsetNewline::latex
|
||||
if (inset->lyxCode() == NEWLINE_CODE) {
|
||||
if (inset->lyxCode() == NEWLINE_CODE || inset->lyxCode() == SEPARATOR_CODE) {
|
||||
// newlines are handled differently here than
|
||||
// the default in simpleTeXSpecialChars().
|
||||
if (!style.newline_allowed) {
|
||||
@ -2132,17 +2132,17 @@ void Paragraph::setBeginOfBody()
|
||||
// remove unnecessary getChar() calls
|
||||
pos_type i = 0;
|
||||
pos_type end = size();
|
||||
if (i < end && !isNewline(i)) {
|
||||
if (i < end && !(isNewline(i) || isEnvSeparator(i))) {
|
||||
++i;
|
||||
char_type previous_char = 0;
|
||||
char_type temp = 0;
|
||||
if (i < end) {
|
||||
previous_char = d->text_[i];
|
||||
if (!isNewline(i)) {
|
||||
if (!(isNewline(i) || isEnvSeparator(i))) {
|
||||
++i;
|
||||
while (i < end && previous_char != ' ') {
|
||||
temp = d->text_[i];
|
||||
if (isNewline(i))
|
||||
if (isNewline(i) || isEnvSeparator(i))
|
||||
break;
|
||||
++i;
|
||||
previous_char = temp;
|
||||
@ -3205,6 +3205,13 @@ bool Paragraph::isNewline(pos_type pos) const
|
||||
}
|
||||
|
||||
|
||||
bool Paragraph::isEnvSeparator(pos_type pos) const
|
||||
{
|
||||
Inset const * inset = getInset(pos);
|
||||
return inset && inset->lyxCode() == SEPARATOR_CODE;
|
||||
}
|
||||
|
||||
|
||||
bool Paragraph::isLineSeparator(pos_type pos) const
|
||||
{
|
||||
char_type const c = d->text_[pos];
|
||||
|
@ -404,6 +404,8 @@ public:
|
||||
bool isInset(pos_type pos) const;
|
||||
///
|
||||
bool isNewline(pos_type pos) const;
|
||||
///
|
||||
bool isEnvSeparator(pos_type pos) const;
|
||||
/// return true if the char is a word separator
|
||||
bool isSeparator(pos_type pos) const;
|
||||
///
|
||||
|
@ -269,7 +269,7 @@ bool ParagraphMetrics::hfillExpansion(Row const & row, pos_type pos) const
|
||||
// the specified position that is neither a newline nor an hfill,
|
||||
// the hfill will be expanded, otherwise it won't
|
||||
for (pos_type i = row.pos(); i < pos; i++) {
|
||||
if (!par_->isNewline(i) && !par_->isHfill(i))
|
||||
if (!par_->isNewline(i) && !par_->isEnvSeparator(i) && !par_->isHfill(i))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -921,6 +921,7 @@ void Text::insertChar(Cursor & cur, char_type c)
|
||||
if (contains(number_unary_operators, c) &&
|
||||
(cur.pos() == 1
|
||||
|| par.isSeparator(cur.pos() - 2)
|
||||
|| par.isEnvSeparator(cur.pos() - 2)
|
||||
|| par.isNewline(cur.pos() - 2))
|
||||
) {
|
||||
setCharFont(pit, cur.pos() - 1, cur.current_font,
|
||||
|
@ -656,6 +656,7 @@ bool Text::cursorBackward(Cursor & cur)
|
||||
cur.textRow().pos() == cur.pos() &&
|
||||
!cur.paragraph().isLineSeparator(cur.pos() - 1) &&
|
||||
!cur.paragraph().isNewline(cur.pos() - 1) &&
|
||||
!cur.paragraph().isEnvSeparator(cur.pos() - 1) &&
|
||||
!cur.paragraph().isSeparator(cur.pos() - 1)) {
|
||||
return setCursor(cur, cur.pit(), cur.pos(), true, true);
|
||||
}
|
||||
@ -669,8 +670,14 @@ bool Text::cursorBackward(Cursor & cur)
|
||||
}
|
||||
|
||||
// move to the previous paragraph or do nothing
|
||||
if (cur.pit() > 0)
|
||||
return setCursor(cur, cur.pit() - 1, getPar(cur.pit() - 1).size(), true, false);
|
||||
if (cur.pit() > 0) {
|
||||
Paragraph & par = getPar(cur.pit() - 1);
|
||||
pos_type lastpos = par.size();
|
||||
if (lastpos > 0 && par.isEnvSeparator(lastpos - 1))
|
||||
return setCursor(cur, cur.pit() - 1, lastpos - 1, true, false);
|
||||
else
|
||||
return setCursor(cur, cur.pit() - 1, lastpos, true, false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -734,12 +741,19 @@ bool Text::cursorForward(Cursor & cur)
|
||||
bool sep2 = cur.paragraph().isSeparator(cur.pos()+1);
|
||||
}
|
||||
#endif
|
||||
if (cur.textRow().endpos() == cur.pos() + 1 &&
|
||||
cur.textRow().endpos() != cur.lastpos() &&
|
||||
!cur.paragraph().isNewline(cur.pos()) &&
|
||||
!cur.paragraph().isLineSeparator(cur.pos()) &&
|
||||
!cur.paragraph().isSeparator(cur.pos())) {
|
||||
return setCursor(cur, cur.pit(), cur.pos() + 1, true, true);
|
||||
if (cur.textRow().endpos() == cur.pos() + 1) {
|
||||
if (cur.paragraph().isEnvSeparator(cur.pos()) &&
|
||||
cur.pos() + 1 == cur.lastpos() &&
|
||||
cur.pit() != cur.lastpit()) {
|
||||
// move to next paragraph
|
||||
return setCursor(cur, cur.pit() + 1, 0, true, false);
|
||||
} else if (cur.textRow().endpos() != cur.lastpos() &&
|
||||
!cur.paragraph().isNewline(cur.pos()) &&
|
||||
!cur.paragraph().isEnvSeparator(cur.pos()) &&
|
||||
!cur.paragraph().isLineSeparator(cur.pos()) &&
|
||||
!cur.paragraph().isSeparator(cur.pos())) {
|
||||
return setCursor(cur, cur.pit(), cur.pos() + 1, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
// in front of RTL boundary? Stay on this side of the boundary because:
|
||||
|
@ -1021,11 +1021,20 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
|
||||
|
||||
case LFUN_CHAR_DELETE_FORWARD:
|
||||
if (!cur.selection()) {
|
||||
bool was_separator = cur.paragraph().isEnvSeparator(cur.pos());
|
||||
if (cur.pos() == cur.paragraph().size())
|
||||
// Par boundary, force full-screen update
|
||||
singleParUpdate = false;
|
||||
needsUpdate |= erase(cur);
|
||||
cur.resetAnchor();
|
||||
if (was_separator && cur.pos() == cur.paragraph().size()
|
||||
&& (!cur.paragraph().layout().isEnvironment()
|
||||
|| cur.paragraph().size() > 0)) {
|
||||
// Force full-screen update
|
||||
singleParUpdate = false;
|
||||
needsUpdate |= erase(cur);
|
||||
cur.resetAnchor();
|
||||
}
|
||||
// It is possible to make it a lot faster still
|
||||
// just comment out the line below...
|
||||
} else {
|
||||
@ -1038,11 +1047,17 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
|
||||
case LFUN_CHAR_DELETE_BACKWARD:
|
||||
if (!cur.selection()) {
|
||||
if (bv->getIntl().getTransManager().backspace()) {
|
||||
bool par_boundary = cur.pos() == 0;
|
||||
// Par boundary, full-screen update
|
||||
if (cur.pos() == 0)
|
||||
if (par_boundary)
|
||||
singleParUpdate = false;
|
||||
needsUpdate |= backspace(cur);
|
||||
cur.resetAnchor();
|
||||
if (par_boundary && cur.pos() > 0
|
||||
&& cur.paragraph().isEnvSeparator(cur.pos() - 1)) {
|
||||
needsUpdate |= backspace(cur);
|
||||
cur.resetAnchor();
|
||||
}
|
||||
// It is possible to make it a lot faster still
|
||||
// just comment out the line below...
|
||||
}
|
||||
@ -1052,11 +1067,33 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
|
||||
}
|
||||
break;
|
||||
|
||||
case LFUN_PARAGRAPH_BREAK:
|
||||
case LFUN_PARAGRAPH_BREAK: {
|
||||
cap::replaceSelection(cur);
|
||||
breakParagraph(cur, cmd.argument() == "inverse");
|
||||
pit_type pit = cur.pit();
|
||||
Paragraph const & par = pars_[pit];
|
||||
Paragraph const & prevpar = pit > 0 ? pars_[pit - 1] : par;
|
||||
if (pit > 0 && cur.pos() == par.beginOfBody()
|
||||
&& ((prevpar.getDepth() > par.getDepth()
|
||||
&& !par.layout().isEnvironment())
|
||||
|| (prevpar.layout() != par.layout()
|
||||
&& prevpar.layout().isEnvironment()))) {
|
||||
if (par.layout().isEnvironment()) {
|
||||
docstring const layout = par.layout().name();
|
||||
DocumentClass const & tc = bv->buffer().params().documentClass();
|
||||
lyx::dispatch(FuncRequest(LFUN_LAYOUT, tc.plainLayout().name()));
|
||||
lyx::dispatch(FuncRequest(LFUN_SEPARATOR_INSERT, "parbreak"));
|
||||
breakParagraph(cur, true);
|
||||
lyx::dispatch(FuncRequest(LFUN_LAYOUT, layout));
|
||||
} else {
|
||||
lyx::dispatch(FuncRequest(LFUN_SEPARATOR_INSERT, "parbreak"));
|
||||
breakParagraph(cur);
|
||||
}
|
||||
} else {
|
||||
breakParagraph(cur, cmd.argument() == "inverse");
|
||||
}
|
||||
cur.resetAnchor();
|
||||
break;
|
||||
}
|
||||
|
||||
case LFUN_INSET_INSERT: {
|
||||
cur.recordUndo();
|
||||
@ -1404,15 +1441,10 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
|
||||
while (cur.paragraph().params().depth() > split_depth)
|
||||
lyx::dispatch(FuncRequest(LFUN_DEPTH_DECREMENT));
|
||||
}
|
||||
bool const morecont = cur.lastpos() > cur.pos();
|
||||
// FIXME This hardcoding is bad
|
||||
docstring const sep =
|
||||
cur.buffer()->params().documentClass().hasLayout(from_ascii("Separator"))
|
||||
? from_ascii("Separator") : from_ascii("--Separator--");
|
||||
lyx::dispatch(FuncRequest(LFUN_LAYOUT, sep));
|
||||
DocumentClass const & tc = bv->buffer().params().documentClass();
|
||||
lyx::dispatch(FuncRequest(LFUN_LAYOUT, tc.plainLayout().name()));
|
||||
lyx::dispatch(FuncRequest(LFUN_SEPARATOR_INSERT, "plain"));
|
||||
lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_BREAK, "inverse"));
|
||||
if (morecont)
|
||||
lyx::dispatch(FuncRequest(LFUN_DOWN));
|
||||
lyx::dispatch(FuncRequest(LFUN_LAYOUT, layout));
|
||||
|
||||
break;
|
||||
@ -1903,6 +1935,16 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
|
||||
cur.posForward();
|
||||
break;
|
||||
|
||||
case LFUN_SEPARATOR_INSERT: {
|
||||
doInsertInset(cur, this, cmd, false, false);
|
||||
cur.posForward();
|
||||
// remove a following space
|
||||
Paragraph & par = cur.paragraph();
|
||||
if (cur.pos() != cur.lastpos() && par.isLineSeparator(cur.pos()))
|
||||
par.eraseChar(cur.pos(), cur.buffer()->params().track_changes);
|
||||
break;
|
||||
}
|
||||
|
||||
case LFUN_DEPTH_DECREMENT:
|
||||
changeDepth(cur, DEC_DEPTH);
|
||||
break;
|
||||
@ -2906,6 +2948,11 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
|
||||
&& cur.pos() > cur.paragraph().beginOfBody();
|
||||
break;
|
||||
|
||||
case LFUN_SEPARATOR_INSERT:
|
||||
// Always enabled for now
|
||||
enable = true;
|
||||
break;
|
||||
|
||||
case LFUN_TAB_INSERT:
|
||||
case LFUN_TAB_DELETE:
|
||||
enable = cur.paragraph().isPassThru();
|
||||
@ -2953,12 +3000,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
|
||||
break;
|
||||
|
||||
case LFUN_ENVIRONMENT_SPLIT: {
|
||||
// FIXME This hardcoding is bad
|
||||
if (!cur.buffer()->params().documentClass().hasLayout(from_ascii("Separator"))
|
||||
&& !cur.buffer()->params().documentClass().hasLayout(from_ascii("--Separator--"))) {
|
||||
enable = false;
|
||||
break;
|
||||
}
|
||||
if (cmd.argument() == "outer") {
|
||||
// check if we have an environment in our nesting hierarchy
|
||||
bool res = false;
|
||||
|
@ -61,7 +61,7 @@ namespace lyx {
|
||||
// development/tools/updatelayouts.sh script, to update the format of
|
||||
// all of our layout files.
|
||||
//
|
||||
int const LAYOUT_FORMAT = 49; //gb: change default of ResetsFont
|
||||
int const LAYOUT_FORMAT = 50; //ef: removal of separator layout
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -348,6 +348,7 @@ bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos,
|
||||
// FED FED| FED )
|
||||
if (startpos == pos && endpos == pos && endpos != par.size()
|
||||
&& (par.isNewline(pos - 1)
|
||||
|| par.isEnvSeparator(pos - 1)
|
||||
|| par.isLineSeparator(pos - 1)
|
||||
|| par.isSeparator(pos - 1)))
|
||||
return false;
|
||||
@ -628,6 +629,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
|
||||
if (ns
|
||||
&& row.endpos() < par.size()
|
||||
&& !par.isNewline(row.endpos() - 1)
|
||||
&& !par.isEnvSeparator(row.endpos() - 1)
|
||||
&& !disp_inset
|
||||
) {
|
||||
row.separator = w / ns;
|
||||
@ -897,7 +899,7 @@ pos_type TextMetrics::rowBreakPoint(int width, pit_type const pit,
|
||||
break;
|
||||
}
|
||||
|
||||
if (par.isNewline(i)) {
|
||||
if (par.isNewline(i) || par.isEnvSeparator(i)) {
|
||||
point = i + 1;
|
||||
break;
|
||||
}
|
||||
@ -1269,7 +1271,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
|
||||
if (lastrow &&
|
||||
((rtl_on_lastrow && left_side && vc == row.pos() && x < tmpx - 5) ||
|
||||
(!rtl_on_lastrow && !left_side && vc == end && x > tmpx + 5))) {
|
||||
if (!par.isNewline(end - 1))
|
||||
if (!(par.isNewline(end - 1) || par.isEnvSeparator(end - 1)))
|
||||
c = end;
|
||||
} else if (vc == row.pos()) {
|
||||
c = bidi.vis2log(vc);
|
||||
@ -1318,7 +1320,9 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
|
||||
if (!c || end == par.size())
|
||||
return col;
|
||||
|
||||
if (c==end && !par.isLineSeparator(c-1) && !par.isNewline(c-1)) {
|
||||
if (c==end && !par.isLineSeparator(c-1)
|
||||
&& !par.isNewline(c-1)
|
||||
&& !par.isEnvSeparator(c-1)) {
|
||||
boundary = true;
|
||||
return col;
|
||||
}
|
||||
@ -1810,7 +1814,8 @@ bool TextMetrics::cursorEnd(Cursor & cur)
|
||||
bool boundary = false;
|
||||
if (end != cur.lastpos()) {
|
||||
if (!cur.paragraph().isLineSeparator(end-1)
|
||||
&& !cur.paragraph().isNewline(end-1))
|
||||
&& !cur.paragraph().isNewline(end-1)
|
||||
&& !cur.paragraph().isEnvSeparator(end-1))
|
||||
boundary = true;
|
||||
else
|
||||
--end;
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "insets/InsetPreview.h"
|
||||
#include "insets/InsetRef.h"
|
||||
#include "insets/InsetScript.h"
|
||||
#include "insets/InsetSeparator.h"
|
||||
#include "insets/InsetSpace.h"
|
||||
#include "insets/InsetTabular.h"
|
||||
#include "insets/InsetTOC.h"
|
||||
@ -99,6 +100,20 @@ Inset * createInsetHelper(Buffer * buf, FuncRequest const & cmd)
|
||||
return new InsetNewpage(inp);
|
||||
}
|
||||
|
||||
case LFUN_SEPARATOR_INSERT: {
|
||||
string const name = cmd.getArg(0);
|
||||
InsetSeparatorParams inp;
|
||||
if (name.empty() || name == "plain")
|
||||
inp.kind = InsetSeparatorParams::PLAIN;
|
||||
else if (name == "parbreak")
|
||||
inp.kind = InsetSeparatorParams::PARBREAK;
|
||||
else {
|
||||
lyxerr << "Wrong argument for LyX function 'separator-insert'." << endl;
|
||||
break;
|
||||
}
|
||||
return new InsetSeparator(inp);
|
||||
}
|
||||
|
||||
case LFUN_FLEX_INSERT: {
|
||||
string s = cmd.getArg(0);
|
||||
return new InsetFlex(buf, s);
|
||||
@ -627,6 +642,8 @@ Inset * readInset(Lexer & lex, Buffer * buf)
|
||||
inset.reset(new InsetNewpage);
|
||||
} else if (tmptok == "Newline") {
|
||||
inset.reset(new InsetNewline);
|
||||
} else if (tmptok == "Separator") {
|
||||
inset.reset(new InsetSeparator);
|
||||
} else if (tmptok == "Argument") {
|
||||
inset.reset(new InsetArgument(buf, tmptok));
|
||||
} else if (tmptok == "Float") {
|
||||
|
274
src/insets/InsetSeparator.cpp
Normal file
274
src/insets/InsetSeparator.cpp
Normal file
@ -0,0 +1,274 @@
|
||||
/**
|
||||
* \file InsetSeparator.cpp
|
||||
* This file is part of LyX, the document processor.
|
||||
* Licence details can be found in the file COPYING.
|
||||
*
|
||||
* \author Enrico Forestieri
|
||||
*
|
||||
* Full author contact details are available in file CREDITS.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "InsetSeparator.h"
|
||||
|
||||
#include "Cursor.h"
|
||||
#include "Dimension.h"
|
||||
#include "FuncRequest.h"
|
||||
#include "FuncStatus.h"
|
||||
#include "Lexer.h"
|
||||
#include "MetricsInfo.h"
|
||||
#include "OutputParams.h"
|
||||
#include "output_xhtml.h"
|
||||
|
||||
#include "frontends/Application.h"
|
||||
#include "frontends/FontMetrics.h"
|
||||
#include "frontends/Painter.h"
|
||||
|
||||
#include "support/debug.h"
|
||||
#include "support/docstream.h"
|
||||
#include "support/docstring.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace lyx {
|
||||
|
||||
InsetSeparator::InsetSeparator() : Inset(0)
|
||||
{}
|
||||
|
||||
|
||||
InsetSeparator::InsetSeparator(InsetSeparatorParams const & params)
|
||||
: Inset(0), params_(params)
|
||||
{}
|
||||
|
||||
|
||||
void InsetSeparatorParams::write(ostream & os) const
|
||||
{
|
||||
string command;
|
||||
switch (kind) {
|
||||
case InsetSeparatorParams::PLAIN:
|
||||
os << "plain";
|
||||
break;
|
||||
case InsetSeparatorParams::PARBREAK:
|
||||
os << "parbreak";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InsetSeparatorParams::read(Lexer & lex)
|
||||
{
|
||||
string token;
|
||||
lex.setContext("InsetSeparatorParams::read");
|
||||
lex >> token;
|
||||
if (token == "plain")
|
||||
kind = InsetSeparatorParams::PLAIN;
|
||||
else if (token == "parbreak")
|
||||
kind = InsetSeparatorParams::PARBREAK;
|
||||
else
|
||||
lex.printError("Unknown kind: `$$Token'");
|
||||
}
|
||||
|
||||
|
||||
void InsetSeparator::write(ostream & os) const
|
||||
{
|
||||
os << "Separator ";
|
||||
params_.write(os);
|
||||
}
|
||||
|
||||
|
||||
void InsetSeparator::read(Lexer & lex)
|
||||
{
|
||||
params_.read(lex);
|
||||
lex >> "\\end_inset";
|
||||
}
|
||||
|
||||
|
||||
void InsetSeparator::doDispatch(Cursor & cur, FuncRequest & cmd)
|
||||
{
|
||||
switch (cmd.action()) {
|
||||
|
||||
case LFUN_INSET_MODIFY: {
|
||||
InsetSeparatorParams params;
|
||||
cur.recordUndo();
|
||||
string2params(to_utf8(cmd.argument()), params);
|
||||
params_.kind = params.kind;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Inset::doDispatch(cur, cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool InsetSeparator::getStatus(Cursor & cur, FuncRequest const & cmd,
|
||||
FuncStatus & status) const
|
||||
{
|
||||
switch (cmd.action()) {
|
||||
// we handle these
|
||||
case LFUN_INSET_MODIFY:
|
||||
if (cmd.getArg(0) == "plain") {
|
||||
InsetSeparatorParams params;
|
||||
string2params(to_utf8(cmd.argument()), params);
|
||||
status.setOnOff(params_.kind == params.kind);
|
||||
}
|
||||
status.setEnabled(true);
|
||||
return true;
|
||||
default:
|
||||
return Inset::getStatus(cur, cmd, status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ColorCode InsetSeparator::ColorName() const
|
||||
{
|
||||
switch (params_.kind) {
|
||||
case InsetSeparatorParams::PLAIN:
|
||||
return Color_latex;
|
||||
break;
|
||||
case InsetSeparatorParams::PARBREAK:
|
||||
return Color_pagebreak;
|
||||
break;
|
||||
}
|
||||
// not really useful, but to avoids gcc complaints
|
||||
return Color_latex;
|
||||
}
|
||||
|
||||
|
||||
void InsetSeparator::latex(otexstream & os, OutputParams const & rp) const
|
||||
{
|
||||
switch (params_.kind) {
|
||||
case InsetSeparatorParams::PLAIN:
|
||||
os << breakln << "%\n";
|
||||
break;
|
||||
case InsetSeparatorParams::PARBREAK:
|
||||
os << breakln << "\n";
|
||||
break;
|
||||
default:
|
||||
os << breakln << "%\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int InsetSeparator::plaintext(odocstringstream & os,
|
||||
OutputParams const &, size_t) const
|
||||
{
|
||||
os << '\n';
|
||||
return PLAINTEXT_NEWLINE;
|
||||
}
|
||||
|
||||
|
||||
int InsetSeparator::docbook(odocstream & os, OutputParams const &) const
|
||||
{
|
||||
os << '\n';
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
docstring InsetSeparator::xhtml(XHTMLStream & xs, OutputParams const &) const
|
||||
{
|
||||
xs << html::CR() << html::CompTag("br") << html::CR();
|
||||
return docstring();
|
||||
}
|
||||
|
||||
|
||||
void InsetSeparator::metrics(MetricsInfo & mi, Dimension & dim) const
|
||||
{
|
||||
frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
|
||||
dim.asc = fm.maxAscent();
|
||||
dim.des = fm.maxDescent();
|
||||
dim.wid = fm.width('m');
|
||||
if (params_.kind == InsetSeparatorParams::PLAIN)
|
||||
dim.wid *= 5;
|
||||
}
|
||||
|
||||
|
||||
void InsetSeparator::draw(PainterInfo & pi, int x, int y) const
|
||||
{
|
||||
FontInfo font;
|
||||
font.setColor(ColorName());
|
||||
|
||||
frontend::FontMetrics const & fm = theFontMetrics(pi.base.font);
|
||||
int const wid = fm.width('m');
|
||||
int const asc = fm.maxAscent();
|
||||
|
||||
int xp[3];
|
||||
int yp[3];
|
||||
|
||||
if (params_.kind == InsetSeparatorParams::PLAIN) {
|
||||
yp[0] = int(y - 0.500 * asc * 0.75);
|
||||
yp[1] = int(y - 0.500 * asc * 0.75);
|
||||
|
||||
xp[0] = int(x);
|
||||
xp[1] = int(x + wid * 5);
|
||||
|
||||
pi.pain.lines(xp, yp, 2, ColorName());
|
||||
} else {
|
||||
yp[0] = int(y - 0.875 * asc * 0.75);
|
||||
yp[1] = int(y - 0.500 * asc * 0.75);
|
||||
yp[2] = int(y - 0.125 * asc * 0.75);
|
||||
|
||||
if (pi.ltr_pos) {
|
||||
xp[0] = int(x + wid * 0.375);
|
||||
xp[1] = int(x);
|
||||
xp[2] = int(x + wid * 0.375);
|
||||
} else {
|
||||
xp[0] = int(x + wid * 0.625);
|
||||
xp[1] = int(x + wid);
|
||||
xp[2] = int(x + wid * 0.625);
|
||||
}
|
||||
|
||||
pi.pain.lines(xp, yp, 3, ColorName());
|
||||
|
||||
yp[0] = int(y - 0.500 * asc * 0.75);
|
||||
yp[1] = int(y - 0.500 * asc * 0.75);
|
||||
yp[2] = int(y - asc * 0.75);
|
||||
|
||||
if (pi.ltr_pos) {
|
||||
xp[0] = int(x);
|
||||
xp[1] = int(x + wid);
|
||||
xp[2] = int(x + wid);
|
||||
} else {
|
||||
xp[0] = int(x + wid);
|
||||
xp[1] = int(x);
|
||||
xp[2] = int(x);
|
||||
}
|
||||
|
||||
pi.pain.lines(xp, yp, 3, ColorName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
string InsetSeparator::contextMenuName() const
|
||||
{
|
||||
return "context-separator";
|
||||
}
|
||||
|
||||
|
||||
void InsetSeparator::string2params(string const & in, InsetSeparatorParams & params)
|
||||
{
|
||||
params = InsetSeparatorParams();
|
||||
if (in.empty())
|
||||
return;
|
||||
istringstream data(in);
|
||||
Lexer lex;
|
||||
lex.setStream(data);
|
||||
lex.setContext("InsetSeparator::string2params");
|
||||
lex >> "separator";
|
||||
params.read(lex);
|
||||
}
|
||||
|
||||
|
||||
string InsetSeparator::params2string(InsetSeparatorParams const & params)
|
||||
{
|
||||
ostringstream data;
|
||||
data << "separator" << ' ';
|
||||
params.write(data);
|
||||
return data.str();
|
||||
}
|
||||
|
||||
|
||||
} // namespace lyx
|
95
src/insets/InsetSeparator.h
Normal file
95
src/insets/InsetSeparator.h
Normal file
@ -0,0 +1,95 @@
|
||||
// -*- C++ -*-
|
||||
/**
|
||||
* \file InsetSeparator.h
|
||||
* This file is part of LyX, the document processor.
|
||||
* Licence details can be found in the file COPYING.
|
||||
*
|
||||
* \author Enrico Forestieri
|
||||
*
|
||||
* Full author contact details are available in file CREDITS.
|
||||
*/
|
||||
|
||||
#ifndef INSET_SEPARATOR_H
|
||||
#define INSET_SEPARATOR_H
|
||||
|
||||
#include "Inset.h"
|
||||
|
||||
|
||||
namespace lyx {
|
||||
|
||||
class InsetSeparatorParams
|
||||
{
|
||||
public:
|
||||
/// The different kinds of separators we support
|
||||
enum Kind {
|
||||
///
|
||||
PLAIN,
|
||||
///
|
||||
PARBREAK
|
||||
};
|
||||
///
|
||||
InsetSeparatorParams() : kind(PLAIN) {}
|
||||
///
|
||||
void write(std::ostream & os) const;
|
||||
///
|
||||
void read(Lexer & lex);
|
||||
///
|
||||
Kind kind;
|
||||
};
|
||||
|
||||
|
||||
class InsetSeparator : public Inset
|
||||
{
|
||||
public:
|
||||
///
|
||||
InsetSeparator();
|
||||
///
|
||||
explicit InsetSeparator(InsetSeparatorParams const & par);
|
||||
///
|
||||
static void string2params(std::string const &, InsetSeparatorParams &);
|
||||
///
|
||||
static std::string params2string(InsetSeparatorParams const &);
|
||||
private:
|
||||
///
|
||||
InsetSeparatorParams params() const { return params_; }
|
||||
///
|
||||
InsetCode lyxCode() const { return SEPARATOR_CODE; }
|
||||
///
|
||||
void metrics(MetricsInfo &, Dimension &) const;
|
||||
///
|
||||
void draw(PainterInfo & pi, int x, int y) const;
|
||||
///
|
||||
void latex(otexstream &, OutputParams const &) const;
|
||||
///
|
||||
int plaintext(odocstringstream & ods, OutputParams const & op,
|
||||
size_t max_length = INT_MAX) const;
|
||||
///
|
||||
int docbook(odocstream &, OutputParams const &) const;
|
||||
///
|
||||
docstring xhtml(XHTMLStream &, OutputParams const &) const;
|
||||
///
|
||||
void read(Lexer & lex);
|
||||
///
|
||||
void write(std::ostream & os) const;
|
||||
/// is this equivalent to a space (which is BTW different from
|
||||
/// a line separator)?
|
||||
bool isSpace() const { return true; }
|
||||
///
|
||||
ColorCode ColorName() const;
|
||||
///
|
||||
std::string contextMenuName() const;
|
||||
///
|
||||
Inset * clone() const { return new InsetSeparator(*this); }
|
||||
///
|
||||
void doDispatch(Cursor & cur, FuncRequest & cmd);
|
||||
///
|
||||
bool getStatus(Cursor & cur, FuncRequest const & cmd, FuncStatus &) const;
|
||||
|
||||
///
|
||||
InsetSeparatorParams params_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace lyx
|
||||
|
||||
#endif // INSET_SEPARATOR_H
|
@ -213,7 +213,8 @@ static void finishEnvironment(otexstream & os, OutputParams const & runparams,
|
||||
}
|
||||
|
||||
if (data.style->isEnvironment()) {
|
||||
os << "\\end{" << from_ascii(data.style->latexname()) << "}\n";
|
||||
os << breakln
|
||||
<< "\\end{" << from_ascii(data.style->latexname()) << "}\n";
|
||||
prev_env_language_ = data.par_language;
|
||||
if (runparams.encoding != data.prev_encoding) {
|
||||
runparams.encoding = data.prev_encoding;
|
||||
@ -223,7 +224,7 @@ static void finishEnvironment(otexstream & os, OutputParams const & runparams,
|
||||
}
|
||||
|
||||
if (data.leftindent_open) {
|
||||
os << "\\end{LyXParagraphLeftIndent}\n";
|
||||
os << breakln << "\\end{LyXParagraphLeftIndent}\n";
|
||||
prev_env_language_ = data.par_language;
|
||||
if (runparams.encoding != data.prev_encoding) {
|
||||
runparams.encoding = data.prev_encoding;
|
||||
@ -277,21 +278,6 @@ void TeXEnvironment(Buffer const & buf, Text const & text,
|
||||
// Or par->params().depth() > current_depth
|
||||
// Or par->params().leftIndent() != current_left_indent)
|
||||
|
||||
if (par->layout().isParagraph()) {
|
||||
// FIXME (Lgb): How to handle this?
|
||||
//&& !suffixIs(os, "\n\n")
|
||||
|
||||
// (ARRae) There should be at least one '\n' already but we need there to
|
||||
// be two for Standard paragraphs that are depth-increment'ed to be
|
||||
// output correctly. However, tables can also be paragraphs so
|
||||
// don't adjust them.
|
||||
|
||||
// FIXME (Lgb): Will it ever harm to have one '\n' too
|
||||
// many? i.e. that we sometimes will have
|
||||
// three in a row.
|
||||
os << '\n';
|
||||
}
|
||||
|
||||
// FIXME This test should not be necessary.
|
||||
// We should perhaps issue an error if it is.
|
||||
bool const force_plain_layout = text.inset().forcePlainLayout();
|
||||
@ -302,6 +288,21 @@ void TeXEnvironment(Buffer const & buf, Text const & text,
|
||||
if (!style.isEnvironment()) {
|
||||
// This is a standard paragraph, no need to call TeXEnvironment.
|
||||
TeXOnePar(buf, text, pit, os, runparams);
|
||||
// Unless the current or following paragraph are inside
|
||||
// \begin..\end tags and the nesting layout is not of
|
||||
// an itemize kind, we have to output a paragraph break
|
||||
// (we already are at the beginning of a new line)
|
||||
if (pit + 1 < runparams.par_end) {
|
||||
ParagraphList::const_iterator nextpar =
|
||||
paragraphs.constIterator(pit + 1);
|
||||
if (nextpar->layout() == current_layout
|
||||
&& nextpar->getDepth() == current_depth
|
||||
&& current_layout.latextype != LATEX_ITEM_ENVIRONMENT
|
||||
&& current_layout.latextype != LATEX_LIST_ENVIRONMENT
|
||||
&& par->getAlign() == style.align
|
||||
&& nextpar->getAlign() == nextpar->layout().align)
|
||||
os << '\n';
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -858,7 +859,9 @@ void TeXOnePar(Buffer const & buf,
|
||||
switch (style.latextype) {
|
||||
case LATEX_ITEM_ENVIRONMENT:
|
||||
case LATEX_LIST_ENVIRONMENT:
|
||||
if (nextpar && (par.params().depth() < nextpar->params().depth()))
|
||||
if (nextpar
|
||||
&& (par.params().depth() < nextpar->params().depth())
|
||||
&& !par.isEnvSeparator(par.size() - 1))
|
||||
pending_newline = true;
|
||||
break;
|
||||
case LATEX_ENVIRONMENT: {
|
||||
@ -873,7 +876,8 @@ void TeXOnePar(Buffer const & buf,
|
||||
// fall through possible
|
||||
default:
|
||||
// we don't need it for the last paragraph!!!
|
||||
if (nextpar)
|
||||
// or if the last thing is an environment separator
|
||||
if (nextpar && !par.isEnvSeparator(par.size() - 1))
|
||||
pending_newline = true;
|
||||
}
|
||||
|
||||
@ -882,7 +886,13 @@ void TeXOnePar(Buffer const & buf,
|
||||
&& (runparams.isLastPar || !nextpar->hasSameLayout(par))) {
|
||||
if (pending_newline)
|
||||
os << '\n';
|
||||
os << from_ascii(par.params().spacing().writeEnvirEnd(useSetSpace));
|
||||
|
||||
string const endtag =
|
||||
par.params().spacing().writeEnvirEnd(useSetSpace);
|
||||
if (prefixIs(endtag, "\\end{"))
|
||||
os << breakln;
|
||||
|
||||
os << from_ascii(endtag);
|
||||
pending_newline = true;
|
||||
}
|
||||
}
|
||||
@ -1013,19 +1023,29 @@ void TeXOnePar(Buffer const & buf,
|
||||
// we don't need a newline for the last paragraph!!!
|
||||
// Note from JMarc: we will re-add a \n explicitly in
|
||||
// TeXEnvironment, because it is needed in this case
|
||||
if (nextpar) {
|
||||
if (nextpar && !par.isEnvSeparator(par.size() - 1)) {
|
||||
// Make sure to start a new line
|
||||
os << breakln;
|
||||
// Here we now try to avoid spurious empty lines by outputting
|
||||
// a paragraph break only if: (case 1) the paragraph style
|
||||
// allows parbreaks and no \begin, \end or \item tags are
|
||||
// going to follow (i.e., if the next isn't the first
|
||||
// or the current isn't the last paragraph of an environment
|
||||
// or itemize) and the depth and alignment of the following
|
||||
// paragraph is unchanged, or (case 2) the following is a
|
||||
// non-environment paragraph whose depth is increased but
|
||||
// whose alignment is unchanged.
|
||||
Layout const & next_layout = nextpar->layout();
|
||||
if (style == next_layout
|
||||
// no blank lines before environments!
|
||||
|| !next_layout.isEnvironment()
|
||||
// unless there's a depth change
|
||||
// FIXME What we really want to do here is put every \begin and \end
|
||||
// tag on a new line (which was not the case with nested environments).
|
||||
// But in the present state of play, we don't have access to the
|
||||
// information whether the current TeX row is empty or not.
|
||||
// For some ideas about how to fix this, see this thread:
|
||||
// http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg145787.html
|
||||
|| nextpar->params().depth() != par.params().depth()) {
|
||||
if ((style == next_layout
|
||||
&& !style.parbreak_is_newline
|
||||
&& style.latextype != LATEX_ITEM_ENVIRONMENT
|
||||
&& style.latextype != LATEX_LIST_ENVIRONMENT
|
||||
&& style.align == par.getAlign()
|
||||
&& nextpar->getDepth() == par.getDepth()
|
||||
&& nextpar->getAlign() == par.getAlign())
|
||||
|| (!next_layout.isEnvironment()
|
||||
&& nextpar->getDepth() > par.getDepth()
|
||||
&& nextpar->getAlign() == par.getAlign())) {
|
||||
os << '\n';
|
||||
}
|
||||
}
|
||||
|
@ -1599,24 +1599,13 @@ void parse_environment(Parser & p, ostream & os, bool outer,
|
||||
if (last_env == name) {
|
||||
// we need to output a separator since LyX would export
|
||||
// the two environments as one otherwise (bug 5716)
|
||||
docstring const sep = from_ascii("--Separator--");
|
||||
TeX2LyXDocClass const & textclass(parent_context.textclass);
|
||||
if (textclass.hasLayout(sep)) {
|
||||
Context newcontext(parent_context);
|
||||
newcontext.layout = &(textclass[sep]);
|
||||
newcontext.check_layout(os);
|
||||
newcontext.check_end_layout(os);
|
||||
} else {
|
||||
parent_context.check_layout(os);
|
||||
begin_inset(os, "Note Note\n");
|
||||
os << "status closed\n";
|
||||
Context newcontext(true, textclass,
|
||||
&(textclass.defaultLayout()));
|
||||
newcontext.check_layout(os);
|
||||
newcontext.check_end_layout(os);
|
||||
end_inset(os);
|
||||
parent_context.check_end_layout(os);
|
||||
}
|
||||
Context newcontext(true, textclass,
|
||||
&(textclass.defaultLayout()));
|
||||
newcontext.check_layout(os);
|
||||
begin_inset(os, "Separator plain\n");
|
||||
end_inset(os);
|
||||
newcontext.check_end_layout(os);
|
||||
}
|
||||
switch (context.layout->latextype) {
|
||||
case LATEX_LIST_ENVIRONMENT:
|
||||
|
@ -30,8 +30,8 @@ extern char const * const lyx_version_info;
|
||||
|
||||
// Do not remove the comment below, so we get merge conflict in
|
||||
// independent branches. Instead add your own.
|
||||
#define LYX_FORMAT_LYX 474 // rgh: dummy format change for Chunk switch
|
||||
#define LYX_FORMAT_TEX2LYX 474
|
||||
#define LYX_FORMAT_LYX 475 // ef: new separator inset
|
||||
#define LYX_FORMAT_TEX2LYX 475
|
||||
|
||||
#if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
|
||||
#ifndef _MSC_VER
|
||||
|
Loading…
Reference in New Issue
Block a user