Allow paragraph and line breaks in multirow (#12083)

This commit is contained in:
Juergen Spitzmueller 2021-01-23 14:24:54 +01:00
parent 526d2841df
commit 5979a01b1d
7 changed files with 118 additions and 100 deletions

View File

@ -4154,11 +4154,11 @@ def revert_vcolumns2(document):
endcell = find_token(document.body, "</cell>", begcell)
vcand = False
if find_token(document.body, "\\begin_inset Newline", begcell, endcell) != -1:
vcand = not fixedwidth and not multirow
vcand = not fixedwidth
elif count_pars_in_inset(document.body, begcell + 2) > 1:
vcand = not fixedwidth and not multirow
vcand = not fixedwidth
elif get_value(document.body, "\\begin_layout", begcell) != "Plain Layout":
vcand = not fixedwidth and not multirow
vcand = not fixedwidth
colalignment = col_info[col][2]
colvalignment = col_info[col][3]
if vcand:
@ -4174,13 +4174,12 @@ def revert_vcolumns2(document):
document.body[col_line] = document.body[col_line][:-1] + " special=\"" + vval + "\">"
else:
alarg = ""
if multicolumn:
if multicolumn or multirow:
if cellvalign == "middle":
alarg = "[m]"
elif cellvalign == "bottom":
alarg = "[b]"
else:
document.warning("col: %i, alignment: %s" % (col, colvalignment))
if colvalignment == "middle":
alarg = "[m]"
elif colvalignment == "bottom":
@ -4209,6 +4208,20 @@ def revert_vcolumns2(document):
document.body[nl:nl+1] = put_cmd_in_ert("\\linebreak{}")
else:
document.body[nl:nl+1] = put_cmd_in_ert("\\\\")
# Replace parbreaks in multirow with \\endgraf
if multirow == True:
flt = find_token(document.body, "\\begin_layout", begcell, endcell)
if flt != -1:
while True:
elt = find_end_of_layout(document.body, flt)
if elt == -1:
document.warning("Malformed LyX document! Missing layout end.")
break
endcell = find_token(document.body, "</cell>", begcell)
flt = find_token(document.body, "\\begin_layout", elt, endcell)
if flt == -1:
break
document.body[elt : flt + 1] = put_cmd_in_ert("\\endgraf{}")
m += 1
i = j

View File

@ -245,6 +245,11 @@ public:
*/
mutable docstring post_macro;
/** Whether we in a command that is not \\long (i.e. cannot have multiple
* paragraphs)
*/
mutable bool isNonLong = false;
/** Whether we are entering a display math inset.
* Needed to correctly strike out deleted math in change tracking.
*/

View File

@ -1321,24 +1321,7 @@ void toggleFixedWidth(Cursor & cur, InsetTableCell * inset,
if (!multirow)
return;
// merge all paragraphs to one
BufferParams const & bp = cur.bv().buffer().params();
while (inset->paragraphs().size() > 1)
mergeParagraph(bp, inset->paragraphs(), 0);
// This is relevant for multirows
if (fixedWidth)
return;
// remove newlines
ParagraphList::iterator pit = inset->paragraphs().begin();
for (; pit != inset->paragraphs().end(); ++pit) {
for (pos_type j = 0; j != pit->size(); ++j) {
if (pit->isNewline(j))
pit->eraseChar(j, bp.track_changes);
}
}
// reset layout
cur.push(*inset);
// undo information has already been recorded
@ -3165,6 +3148,8 @@ void Tabular::TeXRow(otexstream & os, row_type row,
} else if (!isPartOfMultiRow(row, c)) {
if (!runparams.nice)
os.texrow().start(par.id(), 0);
if (isMultiRow(cell))
newrp.isNonLong = true;
inset->latex(os, newrp);
}
@ -5723,8 +5708,7 @@ bool InsetTabular::getFeatureStatus(Cursor & cur, string const & s,
// fall through
case Tabular::VALIGN_TOP:
status.setEnabled((!tabular.getPWidth(cur.idx()).zero()
|| tabular.getUsebox(cur.idx()) == Tabular::BOX_VARWIDTH)
&& !tabular.isMultiRow(cur.idx()));
|| tabular.getUsebox(cur.idx()) == Tabular::BOX_VARWIDTH));
status.setOnOff(
tabular.getVAlignment(cur.idx(), flag) == Tabular::LYX_VALIGN_TOP);
break;
@ -5734,8 +5718,7 @@ bool InsetTabular::getFeatureStatus(Cursor & cur, string const & s,
// fall through
case Tabular::VALIGN_BOTTOM:
status.setEnabled((!tabular.getPWidth(cur.idx()).zero()
|| tabular.getUsebox(cur.idx()) == Tabular::BOX_VARWIDTH)
&& !tabular.isMultiRow(cur.idx()));
|| tabular.getUsebox(cur.idx()) == Tabular::BOX_VARWIDTH));
status.setOnOff(
tabular.getVAlignment(cur.idx(), flag) == Tabular::LYX_VALIGN_BOTTOM);
break;
@ -5745,8 +5728,7 @@ bool InsetTabular::getFeatureStatus(Cursor & cur, string const & s,
// fall through
case Tabular::VALIGN_MIDDLE:
status.setEnabled((!tabular.getPWidth(cur.idx()).zero()
|| tabular.getUsebox(cur.idx()) == Tabular::BOX_VARWIDTH)
&& !tabular.isMultiRow(cur.idx()));
|| tabular.getUsebox(cur.idx()) == Tabular::BOX_VARWIDTH));
status.setOnOff(
tabular.getVAlignment(cur.idx(), flag) == Tabular::LYX_VALIGN_MIDDLE);
break;
@ -6047,20 +6029,8 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
return cell(cur.idx())->getStatus(cur, cmd, status);
}
// disable in non-fixed-width cells
case LFUN_PARAGRAPH_BREAK:
// multirow does not allow paragraph breaks
if (tabular.isMultiRow(cur.idx())) {
status.setEnabled(false);
return true;
}
// fall through
case LFUN_NEWLINE_INSERT:
if (tabular.isMultiRow(cur.idx())
&& tabular.getPWidth(cur.idx()).zero()) {
status.setEnabled(false);
return true;
}
return cell(cur.idx())->getStatus(cur, cmd, status);
case LFUN_NEWPAGE_INSERT:

View File

@ -1455,12 +1455,17 @@ void TeXOnePar(Buffer const & buf,
// Note from JMarc: we will re-add a \n explicitly in
// TeXEnvironment, because it is needed in this case
if (nextpar && !os.afterParbreak() && !last_was_separator) {
Layout const & next_layout = nextpar->layout();
if (!text.inset().getLayout().parbreakIgnored() && !merged_par)
if (runparams.isNonLong)
// This is to allow parbreak in multirow
// It could also be used for other non-long
// contexts
os << "\\endgraf";
else if (!text.inset().getLayout().parbreakIgnored() && !merged_par)
// Make sure to start a new line
os << breakln;
// A newline '\n' is always output before a command,
// so avoid doubling it.
Layout const & next_layout = nextpar->layout();
if (!next_layout.isCommand()) {
// Here we now try to avoid spurious empty lines by
// outputting a paragraph break only if: (case 1) the

View File

@ -59,7 +59,7 @@ enum {
FLAG_END = 1 << 3, // next \\end ends the parsing process
FLAG_BRACK_LAST = 1 << 4, // next closing bracket ends the parsing
FLAG_TEXTMODE = 1 << 5, // we are in a box
FLAG_ITEM = 1 << 6, // read a (possibly braced token)
FLAG_ITEM = 1 << 6, // read a (possibly braced) token
FLAG_LEAVE = 1 << 7, // leave the loop at the end
FLAG_SIMPLE = 1 << 8, // next $ leaves the loop
FLAG_EQUATION = 1 << 9, // next \] leaves the loop

View File

@ -934,6 +934,67 @@ void handle_hline_below(RowInfo & ri, vector<CellInfo> & ci)
}
void parse_cell_content(ostringstream & os2, Parser & parse, Context & newcontext,
vector< vector<CellInfo> > cellinfo, vector<ColInfo> colinfo,
size_t const row, size_t const col)
{
bool turn = false;
int rotate = 0;
bool varwidth = false;
if (parse.next_token().cs() == "begin") {
parse.pushPosition();
parse.get_token();
string const env = parse.getArg('{', '}');
if (env == "sideways" || env == "turn") {
string angle = "90";
if (env == "turn") {
turn = true;
angle = parse.getArg('{', '}');
}
active_environments.push_back(env);
parse.ertEnvironment(env);
active_environments.pop_back();
parse.skip_spaces();
if (!parse.good() && support::isStrInt(angle))
rotate = convert<int>(angle);
} else if (env == "cellvarwidth") {
active_environments.push_back(env);
parse.ertEnvironment(env);
active_environments.pop_back();
parse.skip_spaces();
varwidth = true;
}
parse.popPosition();
}
if (rotate != 0) {
cellinfo[row][col].rotate = rotate;
parse.get_token();
active_environments.push_back(parse.getArg('{', '}'));
if (turn)
parse.getArg('{', '}');
parse_text_in_inset(parse, os2, FLAG_END, false, newcontext);
active_environments.pop_back();
preamble.registerAutomaticallyLoadedPackage("rotating");
} else if (varwidth) {
parse.get_token();
active_environments.push_back(parse.getArg('{', '}'));
// valign arg
if (parse.hasOpt())
cellinfo[row][col].valign = parse.getArg('[', ']')[1];
newcontext.in_table_cell = true;
parse_text_in_inset(parse, os2, FLAG_END, false, newcontext);
if (cellinfo[row][col].multi == CELL_NORMAL)
colinfo[col].align = newcontext.cell_align;
else
cellinfo[row][col].align = newcontext.cell_align;
active_environments.pop_back();
preamble.registerAutomaticallyLoadedPackage("varwidth");
} else {
parse_text_in_inset(parse, os2, FLAG_CELL, false, newcontext);
}
}
} // anonymous namespace
@ -1284,7 +1345,11 @@ void handle_tabular(Parser & p, ostream & os, string const & name,
cellinfo[row][col].mrxnum = ncells - 1;
ostringstream os2;
parse_text_in_inset(parse, os2, FLAG_ITEM, false, newcontext);
parse.get_token();// skip {
parse_cell_content(os2, parse, newcontext,
cellinfo, colinfo,
row, col);
parse.get_token();// skip }
if (!cellinfo[row][col].content.empty()) {
// This may or may not work in LaTeX,
// but it does not work in LyX.
@ -1321,7 +1386,11 @@ void handle_tabular(Parser & p, ostream & os, string const & name,
cellinfo[row][col].leftlines = ci.leftlines;
cellinfo[row][col].rightlines = ci.rightlines;
ostringstream os2;
parse_text_in_inset(parse, os2, FLAG_ITEM, false, newcontext);
parse.get_token();// skip {
parse_cell_content(os2, parse, newcontext,
cellinfo, colinfo,
row, col);
parse.get_token();// skip }
if (!cellinfo[row][col].content.empty()) {
// This may or may not work in LaTeX,
// but it does not work in LyX.
@ -1416,64 +1485,13 @@ void handle_tabular(Parser & p, ostream & os, string const & name,
for (size_t c = 1; c < colinfo.size(); ++c)
cellinfo[row][c].multi = CELL_PART_OF_MULTICOLUMN;
} else {
bool turn = false;
int rotate = 0;
bool varwidth = false;
if (parse.next_token().cs() == "begin") {
parse.pushPosition();
parse.get_token();
string const env = parse.getArg('{', '}');
if (env == "sideways" || env == "turn") {
string angle = "90";
if (env == "turn") {
turn = true;
angle = parse.getArg('{', '}');
}
active_environments.push_back(env);
parse.ertEnvironment(env);
active_environments.pop_back();
parse.skip_spaces();
if (!parse.good() && support::isStrInt(angle))
rotate = convert<int>(angle);
} else if (env == "cellvarwidth") {
active_environments.push_back(env);
parse.ertEnvironment(env);
active_environments.pop_back();
parse.skip_spaces();
varwidth = true;
}
parse.popPosition();
}
ostringstream os2;
parse_cell_content(os2, parse, newcontext,
cellinfo, colinfo,
row, col);
cellinfo[row][col].leftlines = colinfo[col].leftlines;
cellinfo[row][col].rightlines = colinfo[col].rightlines;
cellinfo[row][col].align = colinfo[col].align;
ostringstream os2;
if (rotate != 0) {
cellinfo[row][col].rotate = rotate;
parse.get_token();
active_environments.push_back(parse.getArg('{', '}'));
if (turn)
parse.getArg('{', '}');
parse_text_in_inset(parse, os2, FLAG_END, false, newcontext);
active_environments.pop_back();
preamble.registerAutomaticallyLoadedPackage("rotating");
} else if (varwidth) {
parse.get_token();
active_environments.push_back(parse.getArg('{', '}'));
// valign arg
if (parse.hasOpt())
cellinfo[row][col].valign = parse.getArg('[', ']')[1];
newcontext.in_table_cell = true;
parse_text_in_inset(parse, os2, FLAG_END, false, newcontext);
if (cellinfo[row][col].multi == CELL_NORMAL)
colinfo[col].align = newcontext.cell_align;
else
cellinfo[row][col].align = newcontext.cell_align;
active_environments.pop_back();
preamble.registerAutomaticallyLoadedPackage("varwidth");
} else {
parse_text_in_inset(parse, os2, FLAG_CELL, false, newcontext);
}
cellinfo[row][col].content += os2.str();
}
}

View File

@ -5105,6 +5105,13 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
continue;
}
if (t.cs() == "endgraf" && context.in_table_cell) {
context.new_paragraph(os);
context.check_layout(os);
skip_spaces_braces(p);
continue;
}
if (t.cs() == "input" || t.cs() == "include"
|| t.cs() == "verbatiminput"
|| t.cs() == "lstinputlisting"