namespace {
int const WIDTH_OF_LINE = 5;
+int const default_line_space = 10;
+
template <class T>
string const write_attribute(string const & name, T const & t)
}
+bool getTokenValue(string const & str, char const * token, LyXLength & len, bool & flag)
+{
+ len = LyXLength();
+ flag = false;
+ string tmp;
+ if (!getTokenValue(str, token, tmp))
+ return false;
+ if (tmp == "default") {
+ flag = true;
+ return true;
+ }
+ return isValidLength(tmp, &len);
+}
+
+
void l_getline(istream & is, string & str)
{
str.erase();
descent_of_row(0),
top_line(true),
bottom_line(false),
+ top_space_default(false),
+ bottom_space_default(false),
+ interline_space_default(false),
endhead(false),
endfirsthead(false),
endfoot(false),
LyXTabular::LyXTabular(BufferParams const & bp, row_type rows_arg,
- col_type columns_arg)
+ col_type columns_arg)
{
init(bp, rows_arg, columns_arg);
}
// activates all lines and sets all widths to 0
void LyXTabular::init(BufferParams const & bp, row_type rows_arg,
- col_type columns_arg)
+ col_type columns_arg)
{
rows_ = rows_arg;
columns_ = columns_arg;
column_info.back().right_line = true;
is_long_tabular = false;
rotate = false;
+ use_booktabs = false;
}
}
-// returns 1 if there is a topline, returns 0 if not
bool LyXTabular::topLine(idx_type const cell, bool const onlycolumn) const
{
- if (!onlycolumn && isMultiColumn(cell))
+ if (!onlycolumn && isMultiColumn(cell) &&
+ !(use_booktabs && row_of_cell(cell) == 0))
return cellinfo_of_cell(cell).top_line;
return row_info[row_of_cell(cell)].top_line;
}
bool LyXTabular::bottomLine(idx_type const cell, bool onlycolumn) const
{
- if (!onlycolumn && isMultiColumn(cell))
+ if (!onlycolumn && isMultiColumn(cell) &&
+ !(use_booktabs && isLastRow(cell)))
return cellinfo_of_cell(cell).bottom_line;
return row_info[row_of_cell(cell)].bottom_line;
}
bool LyXTabular::leftLine(idx_type cell, bool onlycolumn) const
{
+ if (use_booktabs)
+ return false;
if (!onlycolumn && isMultiColumn(cell) &&
(isFirstCellInRow(cell) || isMultiColumn(cell-1)))
{
bool LyXTabular::rightLine(idx_type cell, bool onlycolumn) const
{
+ if (use_booktabs)
+ return false;
if (!onlycolumn && isMultiColumn(cell) &&
(isLastCellInRow(cell) || isMultiColumn(cell + 1)))
{
top = row_info[row].top_line;
}
}
+ int const interline_space = row_info[row - 1].interline_space_default ?
+ default_line_space :
+ row_info[row - 1].interline_space.inPixels(width_of_tabular);
if (top && bottom)
- return WIDTH_OF_LINE;
- return 0;
+ return interline_space + WIDTH_OF_LINE;
+ return interline_space;
}
void LyXTabular::setAlignment(idx_type cell, LyXAlignment align,
- bool onlycolumn)
+ bool onlycolumn)
{
if (!isMultiColumn(cell) || onlycolumn)
column_info[column_of_cell(cell)].alignment = align;
void LyXTabular::setVAlignment(idx_type cell, VAlignment align,
- bool onlycolumn)
+ bool onlycolumn)
{
if (!isMultiColumn(cell) || onlycolumn)
column_info[column_of_cell(cell)].valignment = align;
idx_type const cell = getCellNumber(i, j);
// because of multicolumns
toggleFixedWidth(cur, getCellInset(cell).get(),
- !getPWidth(cell).zero());
+ !getPWidth(cell).zero());
}
// cur paragraph can become invalid after paragraphs were merged
if (cur.pit() > cur.lastpit())
// global longtable options
os << "<features"
<< write_attribute("rotate", rotate)
+ << write_attribute("booktabs", use_booktabs)
<< write_attribute("islongtable", is_long_tabular)
<< write_attribute("firstHeadTopDL", endfirsthead.topDL)
<< write_attribute("firstHeadBottomDL", endfirsthead.bottomDL)
for (row_type i = 0; i < rows_; ++i) {
os << "<row"
<< write_attribute("topline", row_info[i].top_line)
- << write_attribute("bottomline", row_info[i].bottom_line)
- << write_attribute("endhead", row_info[i].endhead)
+ << write_attribute("bottomline", row_info[i].bottom_line);
+ static const string def("default");
+ if (row_info[i].top_space_default)
+ os << write_attribute("topspace", def);
+ else
+ os << write_attribute("topspace", row_info[i].top_space);
+ if (row_info[i].bottom_space_default)
+ os << write_attribute("bottomspace", def);
+ else
+ os << write_attribute("bottomspace", row_info[i].bottom_space);
+ if (row_info[i].interline_space_default)
+ os << write_attribute("interlinespace", def);
+ else
+ os << write_attribute("interlinespace", row_info[i].interline_space);
+ os << write_attribute("endhead", row_info[i].endhead)
<< write_attribute("endfirsthead", row_info[i].endfirsthead)
<< write_attribute("endfoot", row_info[i].endfoot)
<< write_attribute("endlastfoot", row_info[i].endlastfoot)
return;
}
getTokenValue(line, "rotate", rotate);
+ getTokenValue(line, "booktabs", use_booktabs);
getTokenValue(line, "islongtable", is_long_tabular);
getTokenValue(line, "firstHeadTopDL", endfirsthead.topDL);
getTokenValue(line, "firstHeadBottomDL", endfirsthead.bottomDL);
}
getTokenValue(line, "topline", row_info[i].top_line);
getTokenValue(line, "bottomline", row_info[i].bottom_line);
+ getTokenValue(line, "topspace", row_info[i].top_space,
+ row_info[i].top_space_default);
+ getTokenValue(line, "bottomspace", row_info[i].bottom_space,
+ row_info[i].bottom_space_default);
+ getTokenValue(line, "interlinespace", row_info[i].interline_space,
+ row_info[i].interline_space_default);
getTokenValue(line, "endfirsthead", row_info[i].endfirsthead);
getTokenValue(line, "endhead", row_info[i].endhead);
getTokenValue(line, "endfoot", row_info[i].endfoot);
void LyXTabular::setMultiColumn(Buffer * buffer, idx_type cell,
- idx_type number)
+ idx_type number)
{
cellstruct & cs = cellinfo_of_cell(cell);
cs.multicolumn = CELL_BEGIN_OF_MULTICOLUMN;
}
+void LyXTabular::setBookTabs(bool what)
+{
+ use_booktabs = what;
+}
+
+
+bool LyXTabular::useBookTabs() const
+{
+ return use_booktabs;
+}
+
+
void LyXTabular::setLongTabular(bool what)
{
is_long_tabular = what;
LyXTabular::idx_type LyXTabular::getCellNumber(row_type row,
- col_type column) const
+ col_type column) const
{
BOOST_ASSERT(column != npos && column < columns_ &&
- row != npos && row < rows_);
+ row != npos && row < rows_);
return cell_info[row][column].cellno;
}
// This are functions used for the longtable support
///
void LyXTabular::setLTHead(row_type row, bool flag, ltType const & hd,
- bool first)
+ bool first)
{
if (first) {
endfirsthead = hd;
void LyXTabular::setLTFoot(row_type row, bool flag, ltType const & fd,
- bool last)
+ bool last)
{
if (last) {
endlastfoot = fd;
if (topLine(i))
++tmp;
}
- if (tmp == n - fcell) {
- os << "\\hline ";
+ if (use_booktabs && row == 0) {
+ os << "\\toprule ";
+ } else if (tmp == n - fcell) {
+ os << (use_booktabs ? "\\midrule " : "\\hline ");
} else if (tmp) {
for (idx_type i = fcell; i < n; ++i) {
if (topLine(i)) {
- os << "\\cline{"
+ os << (use_booktabs ? "\\cmidrule{" : "\\cline{")
<< column_of_cell(i) + 1
<< '-'
<< right_column_of_cell(i) + 1
if (bottomLine(i))
++tmp;
}
- if (tmp == n - fcell) {
- os << "\\hline";
+ if (use_booktabs && row == rows_ - 1) {
+ os << "\\bottomrule";
+ } else if (tmp == n - fcell) {
+ os << (use_booktabs ? "\\midrule" : "\\hline");
} else if (tmp) {
for (idx_type i = fcell; i < n; ++i) {
if (bottomLine(i)) {
- os << "\\cline{"
+ os << (use_booktabs ? "\\cmidrule{" : "\\cline{")
<< column_of_cell(i) + 1
<< '-'
<< right_column_of_cell(i) + 1
OutputParams const & runparams) const
{
idx_type cell = getCellNumber(i, 0);
-
int ret = TeXTopHLine(os, i);
+ if (row_info[i].top_space_default) {
+ if (use_booktabs)
+ os << "\\addlinespace\n";
+ else
+ os << "\\noalign{\\vskip\\doublerulesep}\n";
+ } else if(!row_info[i].top_space.zero()) {
+ if (use_booktabs)
+ os << "\\addlinespace["
+ << row_info[i].top_space.asLatexString() << "]\n";
+ else {
+ os << "\\noalign{\\vskip"
+ << row_info[i].top_space.asLatexString() << "}\n";
+ }
+ ++ret;
+ }
+
for (col_type j = 0; j < columns_; ++j) {
if (isPartOfMultiColumn(i, j))
continue;
}
++cell;
}
- os << "\\tabularnewline\n";
+ os << "\\tabularnewline";
+ if (row_info[i].bottom_space_default) {
+ if (use_booktabs)
+ os << "\\addlinespace";
+ else
+ os << "[\\doublerulesep]";
+ } else if (!row_info[i].bottom_space.zero()) {
+ if (use_booktabs)
+ os << "\\addlinespace";
+ os << '[' << row_info[i].bottom_space.asLatexString() << ']';
+ }
+ os << '\n';
++ret;
ret += TeXBottomHLine(os, i);
+ if (row_info[i].interline_space_default) {
+ if (use_booktabs)
+ os << "\\addlinespace\n";
+ else
+ os << "\\noalign{\\vskip\\doublerulesep}\n";
+ } else if (!row_info[i].interline_space.zero()) {
+ if (use_booktabs)
+ os << "\\addlinespace["
+ << row_info[i].interline_space.asLatexString()
+ << "]\n";
+ else
+ os << "\\noalign{\\vskip"
+ << row_info[i].interline_space.asLatexString()
+ << "}\n";
+ ++ret;
+ }
return ret;
}
if (!column_info[i].align_special.empty()) {
os << column_info[i].align_special;
} else {
- if (column_info[i].left_line)
+ if (!use_booktabs && column_info[i].left_line)
os << '|';
if (!column_info[i].p_width.zero()) {
switch (column_info[i].alignment) {
break;
}
}
- if (column_info[i].right_line)
+ if (!use_booktabs && column_info[i].right_line)
os << '|';
}
}
shared_ptr<InsetText> LyXTabular::getCellInset(row_type row,
- col_type column) const
+ col_type column) const
{
return cell_info[row][column].inset;
}
void LyXTabular::validate(LaTeXFeatures & features) const
{
features.require("NeedTabularnewline");
+ if (useBookTabs())
+ features.require("booktabs");
if (isLongTabular())
features.require("longtable");
if (needRotating())