- Multicolumn now supports multiple paragraphs in non-fixed-width context.
- Multicolumn now supports valign in non-fixed-width context.
- varwidth columns now properly align horizontally and vertically.
-----------------------
+2021-01-22 Jürgen Spitzmüller <spitz@lyx.org>
+ * Format incremented to 605: Extended variable table cell support.
+ - Multicolumn now supports multiple paragraphs in non-fixed-width context.
+ - Multicolumn now supports valign in non-fixed-width context.
+ - varwidth columns now properly align horizontally and vertically.
+
2021-01-19 Jürgen Spitzmüller <spitz@lyx.org>
* Format incremented to 604: Branch colors now take two values:
\color lightmode darkmode
i += 1
+def revert_vcolumns2(document):
+ """Revert varwidth columns with line breaks etc."""
+ i = 0
+ needvarwidth = False
+ needarray = False
+ needcellvarwidth = False
+ try:
+ while True:
+ i = find_token(document.body, "\\begin_inset Tabular", i+1)
+ if i == -1:
+ return
+ j = find_end_of_inset(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Could not find end of tabular.")
+ continue
+
+ # Collect necessary column information
+ m = i + 1
+ nrows = int(document.body[i+1].split('"')[3])
+ ncols = int(document.body[i+1].split('"')[5])
+ col_info = []
+ for k in range(ncols):
+ m = find_token(document.body, "<column", m)
+ width = get_option_value(document.body[m], 'width')
+ varwidth = get_option_value(document.body[m], 'varwidth')
+ alignment = get_option_value(document.body[m], 'alignment')
+ valignment = get_option_value(document.body[m], 'valignment')
+ special = get_option_value(document.body[m], 'special')
+ col_info.append([width, varwidth, alignment, valignment, special, m])
+ m += 1
+
+ # Now parse cells
+ m = i + 1
+ lines = []
+ for row in range(nrows):
+ for col in range(ncols):
+ m = find_token(document.body, "<cell", m)
+ multicolumn = get_option_value(document.body[m], 'multicolumn') != ""
+ multirow = get_option_value(document.body[m], 'multirow') != ""
+ fixedwidth = get_option_value(document.body[m], 'width') != ""
+ rotate = get_option_value(document.body[m], 'rotate')
+ cellalign = get_option_value(document.body[m], 'alignment')
+ cellvalign = get_option_value(document.body[m], 'valignment')
+ # Check for: linebreaks, multipars, non-standard environments
+ begcell = m
+ 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
+ elif count_pars_in_inset(document.body, begcell + 2) > 1:
+ vcand = not fixedwidth and not multirow
+ elif get_value(document.body, "\\begin_layout", begcell) != "Plain Layout":
+ vcand = not fixedwidth and not multirow
+ colalignment = col_info[col][2]
+ colvalignment = col_info[col][3]
+ if vcand:
+ if rotate == "" and ((colalignment == "left" and colvalignment == "top") or (multicolumn == True and cellalign == "left" and cellvalign == "top")):
+ if col_info[col][0] == "" and col_info[col][1] == "" and col_info[col][4] == "":
+ needvarwidth = True
+ col_line = col_info[col][5]
+ needarray = True
+ vval = "V{\\linewidth}"
+ if multicolumn:
+ document.body[m] = document.body[m][:-1] + " special=\"" + vval + "\">"
+ else:
+ document.body[col_line] = document.body[col_line][:-1] + " special=\"" + vval + "\">"
+ else:
+ alarg = ""
+ if multicolumn:
+ 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":
+ alarg = "[b]"
+ flt = find_token(document.body, "\\begin_layout", begcell, endcell)
+ elt = find_token_backwards(document.body, "\\end_layout", endcell)
+ if flt != -1 and elt != -1:
+ document.body[elt:elt+1] = put_cmd_in_ert("\\end{cellvarwidth}")
+ document.body[flt+1:flt+1] = put_cmd_in_ert("\\begin{cellvarwidth}" + alarg)
+ needcellvarwidth = True
+ needvarwidth = True
+ # ERT newlines and linebreaks (since LyX < 2.4 automatically inserts parboxes
+ # with newlines, and we do not want that)
+ while True:
+ endcell = find_token(document.body, "</cell>", begcell)
+ linebreak = False
+ nl = find_token(document.body, "\\begin_inset Newline newline", begcell, endcell)
+ if nl == -1:
+ nl = find_token(document.body, "\\begin_inset Newline linebreak", begcell, endcell)
+ if nl == -1:
+ break
+ linebreak = True
+ nle = find_end_of_inset(document.body, nl)
+ del(document.body[nle:nle+1])
+ if linebreak:
+ document.body[nl:nl+1] = put_cmd_in_ert("\\linebreak{}")
+ else:
+ document.body[nl:nl+1] = put_cmd_in_ert("\\\\")
+ m += 1
+
+ i = j
+
+ finally:
+ if needarray == True:
+ add_to_preamble(document, ["\\usepackage{array}"])
+ if needcellvarwidth == True:
+ add_to_preamble(document, ["%% Variable width box for table cells",
+ "\\newenvironment{cellvarwidth}[1][t]",
+ " {\\begin{varwidth}[#1]{\\linewidth}}",
+ " {\\@finalstrut\\@arstrutbox\\end{varwidth}}"])
+ if needvarwidth == True:
+ add_to_preamble(document, ["\\usepackage{varwidth}"])
+
+
##
# Conversion hub
#
[601, [convert_math_refs]],
[602, [convert_branch_colors]],
[603, []],
- [604, []]
+ [604, []],
+ [605, []]
]
-revert = [[603, [revert_branch_darkcols]],
+revert = [[604, [revert_vcolumns2]],
+ [603, [revert_branch_darkcols]],
[602, [revert_darkmode_graphics]],
[601, [revert_branch_colors]],
[600, []],
"%% Because html converters don't know tabularnewline\n"
"\\providecommand{\\tabularnewline}{\\\\}\n");
+static docstring const cellvarwidth_def = from_ascii(
+ "%% Variable width box for table cells\n"
+ "\\newenvironment{cellvarwidth}[1][t]\n"
+ " {\\begin{varwidth}[#1]{\\linewidth}}\n"
+ " {\\@finalstrut\\@arstrutbox\\end{varwidth}}\n");
+
// We want to omit the file extension for includegraphics, but this does not
// work when the filename contains other dots.
// Idea from http://www.tex.ac.uk/cgi-bin/texfaq2html?label=unkgrfextn
if (mustProvide("NeedTabularnewline"))
macros << tabularnewline_def;
+ if (mustProvide("cellvarwidth"))
+ macros << cellvarwidth_def;
+
// greyed-out environment (note inset)
// the color is specified in the routine
// getColorOptions() to avoid LaTeX-package clashes
namespace {
/**
- * Allow line and paragraph breaks for fixed width multicol/multirow cells
+ * Allow line and paragraph breaks for fixed width multirow cells
* or disallow them, merge cell paragraphs and reset layout to standard
* for variable width multicol cells.
*/
void toggleFixedWidth(Cursor & cur, InsetTableCell * inset,
- bool const fixedWidth, bool const multicol,
- bool const multirow)
+ bool const fixedWidth, bool const multirow)
{
inset->toggleFixedWidth(fixedWidth);
- if (!multirow && (fixedWidth || !multicol))
+ if (!multirow)
return;
// merge all paragraphs to one
idx_type const cidx = cellIndex(r, c);
// because of multicolumns
toggleFixedWidth(cur, cellInset(cidx).get(),
- !getPWidth(cidx).zero(), isMultiColumn(cidx),
- isMultiRow(cidx));
+ !getPWidth(cidx).zero(), isMultiRow(cidx));
if (isMultiRow(cidx))
setAlignment(cidx, LYX_ALIGN_LEFT, false);
}
cellInfo(cell).p_width = width;
toggleFixedWidth(cur, cellInset(cell).get(), !width.zero(),
- isMultiColumn(cell), isMultiRow(cell));
+ isMultiRow(cell));
// cur can become invalid after paragraphs were merged
cur.fixIfBroken();
return true;
{
for (row_type r = 0; r < nrows(); ++r) {
idx_type idx = cellIndex(r, c);
- if (getRotateCell(idx) == 0 && useBox(idx) == BOX_VARWIDTH)
+ if (getRotateCell(idx) == 0 && useBox(idx) == BOX_VARWIDTH
+ && getAlignment(idx) == LYX_ALIGN_LEFT
+ && getVAlignment(idx) == LYX_VALIGN_TOP)
return true;
}
return false;
// non-fixed width multicolumns cannot have multiple paragraphs
if (getPWidth(cell).zero()) {
toggleFixedWidth(cur, cellInset(cell).get(),
- !getPWidth(cell).zero(), isMultiColumn(cell),
- isMultiRow(cell));
+ !getPWidth(cell).zero(), isMultiRow(cell));
// cur can become invalid after paragraphs were merged
cur.fixIfBroken();
}
if (getPWidth(cell).zero()) {
toggleFixedWidth(cur, cellInset(cell).get(),
!getPWidth(cell).zero(),
- isMultiColumn(cell), isMultiRow(cell));
+ isMultiRow(cell));
// cur can become invalid after paragraphs were merged
cur.fixIfBroken();
}
<< from_ascii(getPWidth(cell).asLatexString())
<< '}';
} else {
- switch (align) {
- case LYX_ALIGN_LEFT:
- os << 'l';
- break;
- case LYX_ALIGN_RIGHT:
- os << 'r';
- break;
- default:
- os << 'c';
- break;
+ if ((getRotateCell(cell) == 0 && useBox(cell) == BOX_VARWIDTH
+ && align == LYX_ALIGN_LEFT))
+ os << "V{\\linewidth}";
+ else {
+ switch (align) {
+ case LYX_ALIGN_LEFT:
+ os << 'l';
+ break;
+ case LYX_ALIGN_RIGHT:
+ os << 'r';
+ break;
+ default:
+ os << 'c';
+ break;
+ }
}
} // end if else !getPWidth
} // end if else !cellinfo_of_cell
}
os << "]{" << from_ascii(getPWidth(cell).asLatexString())
<< "}\n";
- } else if (getRotateCell(cell) != 0 && getUsebox(cell) == BOX_VARWIDTH) {
- os << "\\begin{varwidth}[";
+ } else if (getUsebox(cell) == BOX_VARWIDTH
+ && (getRotateCell(cell) != 0 || align != LYX_ALIGN_LEFT
+ || valign != LYX_VALIGN_TOP)) {
+ os << "\\begin{cellvarwidth}[";
switch (valign) {
case LYX_VALIGN_TOP:
os << 't';
case LYX_VALIGN_BOTTOM:
os << 'b';
break;
+ }
+ os << "]\n";
+ switch (align) {
+ case LYX_ALIGN_RIGHT:
+ os << "\\raggedleft\n";
+ break;
+ case LYX_ALIGN_CENTER:
+ os << "\\centering\n";
+ break;
+ case LYX_ALIGN_LEFT:
+ //os << "\\narrowragged\n";
+ break;
+ case LYX_ALIGN_BLOCK:
+ case LYX_ALIGN_DECIMAL:
+ case LYX_ALIGN_NONE:
+ case LYX_ALIGN_LAYOUT:
+ case LYX_ALIGN_SPECIAL:
+ break;
+ }
}
- os << "]{\\linewidth}\n";
-}
}
os << '}';
else if (getUsebox(cell) == BOX_MINIPAGE)
os << breakln << "\\end{minipage}";
- else if (getRotateCell(cell) != 0 && getUsebox(cell) == BOX_VARWIDTH)
- os << breakln << "\\end{varwidth}";
+ else if (getUsebox(cell) == BOX_VARWIDTH
+ && (getRotateCell(cell) != 0 || getAlignment(cell) != LYX_ALIGN_LEFT
+ || getVAlignment(cell) != LYX_VALIGN_TOP))
+ os << breakln << "\\end{cellvarwidth}";
if (getRotateCell(cell) != 0)
os << breakln << "\\end{turn}";
if (ismultirow)
break;
}
os << 'X';
- } else if (isVTypeColumn(c)) {
- switch (column_info[c].alignment) {
- case LYX_ALIGN_LEFT:
- os << ">{\\raggedright}";
- break;
- case LYX_ALIGN_RIGHT:
- os << ">{\\raggedleft}";
- break;
- case LYX_ALIGN_CENTER:
- os << ">{\\centering}";
- break;
- case LYX_ALIGN_NONE:
- case LYX_ALIGN_BLOCK:
- case LYX_ALIGN_LAYOUT:
- case LYX_ALIGN_SPECIAL:
- case LYX_ALIGN_DECIMAL:
- break;
- }
+ } else if (isVTypeColumn(c))
os << "V{\\linewidth}";
- } else {
+ else {
switch (column_info[c].alignment) {
case LYX_ALIGN_LEFT:
os << 'l';
for (idx_type cell = 0; cell < numberofcells; ++cell) {
if (isMultiRow(cell))
features.require("multirow");
- if (getUsebox(cell) == BOX_VARWIDTH)
+ if (getUsebox(cell) == BOX_VARWIDTH) {
features.require("varwidth");
+ features.require("cellvarwidth");
+ }
if (getVAlignment(cell) != LYX_VALIGN_TOP
|| !getPWidth(cell).zero()
|| isVTypeColumn(cellColumn(cell)))
bool InsetTableCell::forcePlainLayout(idx_type) const
{
- return isMultiRow || (isMultiColumn && !isFixedWidth);
+ return isMultiRow;
}
flag = false;
// fall through
case Tabular::VALIGN_BOTTOM:
- status.setEnabled(!tabular.getPWidth(cur.idx()).zero()
- && !tabular.isMultiRow(cur.idx()));
+ status.setEnabled(!tabular.isMultiRow(cur.idx()));
status.setOnOff(
tabular.getVAlignment(cur.idx(), flag) == Tabular::LYX_VALIGN_BOTTOM);
break;
flag = false;
// fall through
case Tabular::VALIGN_MIDDLE:
- status.setEnabled(!tabular.getPWidth(cur.idx()).zero()
- && !tabular.isMultiRow(cur.idx()));
+ status.setEnabled(!tabular.isMultiRow(cur.idx()));
status.setOnOff(
tabular.getVAlignment(cur.idx(), flag) == Tabular::LYX_VALIGN_MIDDLE);
break;
}
// fall through
case LFUN_NEWLINE_INSERT:
- if ((tabular.isMultiColumn(cur.idx()) || tabular.isMultiRow(cur.idx()))
+ if (tabular.isMultiRow(cur.idx())
&& tabular.getPWidth(cur.idx()).zero()) {
status.setEnabled(false);
return true;
bool InsetTabular::forcePlainLayout(idx_type cell) const
{
- return tabular.isMultiColumn(cell) && !tabular.getPWidth(cell).zero();
+ return tabular.isMultiRow(cell);
}
// Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own.
-#define LYX_FORMAT_LYX 604 // spitz: separate dark branch color
-#define LYX_FORMAT_TEX2LYX 604
+#define LYX_FORMAT_LYX 605 // spitz: improved varwidth cells
+#define LYX_FORMAT_TEX2LYX 605
#if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
#ifndef _MSC_VER