#include "support/convert.h"
#include "support/lstrings.h"
+#include <algorithm>
#include <iostream>
#include <sstream>
#include <vector>
namespace lyx {
-// filled in preamble.cpp
-map<char, int> special_columns;
-
namespace {
public:
CellInfo() : multi(CELL_NORMAL), align('n'), valign('n'),
leftlines(0), rightlines(0), topline(false),
- bottomline(false), rotate(false) {}
+ bottomline(false), rotate(0) {}
/// cell content
string content;
/// multicolumn flag
bool topline;
/// do we have a line below?
bool bottomline;
- /// is the cell rotated?
- bool rotate;
+ /// how is the cell rotated?
+ int rotate;
/// width for multicolumn cells
string width;
/// special formatting for multicolumn cells
class ltType {
public:
// constructor
- ltType() : topDL(false), bottomDL(false), empty(false) {}
+ ltType() : set(false), topDL(false), bottomDL(false), empty(false) {}
// we have this header type (is set in the getLT... functions)
bool set;
// double borders on top
}
+string const write_attribute(string const & name, int const & i)
+{
+ // we write only true attribute values so we remove a bit of the
+ // file format bloat for tabulars.
+ return i ? write_attribute(name, convert<string>(i)) : string();
+}
+
+
/*! rather brutish way to code table structure in a string:
\verbatim
next.special += t.character();
next.special += '{' + p.verbatim_item() + '}';
break;
- default:
+ default: {
// try user defined column types
- if (special_columns.find(t.character()) !=
- special_columns.end()) {
- ci2special(next);
- next.special += t.character();
- int const nargs =
- special_columns[t.character()];
- for (int i = 0; i < nargs; ++i)
- next.special += '{' +
- p.verbatim_item() +
- '}';
- colinfo.push_back(next);
- next = ColInfo();
- } else
- cerr << "Ignoring column specification"
- " '" << t << "'." << endl;
+ // unknown column types (nargs == -1) are
+ // assumed to consume no arguments
+ ci2special(next);
+ next.special += t.character();
+ int const nargs =
+ preamble.getSpecialTableColumnArguments(t.character());
+ for (int i = 0; i < nargs; ++i)
+ next.special += '{' +
+ p.verbatim_item() + '}';
+ colinfo.push_back(next);
+ next = ColInfo();
break;
}
+ }
}
// Maybe we have some column separators that need to be added to the
}
}
- else if (t.cat() == catSpace
+ else if (t.cat() == catSpace
|| t.cat() == catNewline
- || t.cat() == catLetter
- || t.cat() == catSuper
- || t.cat() == catSub
- || t.cat() == catOther
- || t.cat() == catActive
+ || t.cat() == catLetter
+ || t.cat() == catSuper
+ || t.cat() == catSub
+ || t.cat() == catOther
+ || t.cat() == catActive
|| t.cat() == catParameter)
os << t.cs();
// treat the nested environment as a block, don't
// parse &, \\ etc, because they don't belong to our
// table if they appear.
- os << p.verbatimEnvironment(name);
+ os << p.ertEnvironment(name);
os << "\\end{" << name << '}';
active_environments.pop_back();
}
cellinfo[row][col].content += os.str();
// add dummy cells for multicol
- for (size_t i = 0; i < ncells - 1 && col < colinfo.size(); ++i) {
+ for (size_t i = 0; i < ncells - 1; ++i) {
++col;
+ if (col >= colinfo.size()) {
+ cerr << "The cell '"
+ << cells[cell]
+ << "' specifies "
+ << convert<string>(ncells)
+ << " columns while the table has only "
+ << convert<string>(colinfo.size())
+ << " columns!"
+ << " Therefore the surplus columns will be ignored."
+ << endl;
+ break;
+ }
cellinfo[row][col].multi = CELL_PART_OF_MULTICOLUMN;
cellinfo[row][col].align = 'c';
}
// one multicolumn cell. The contents of that
// cell must contain exactly one caption inset
// and nothing else.
- // LyX outputs all caption rows as first head,
- // so we must not set the caption flag for
- // captions not in the first head.
// Fortunately, the caption flag is only needed
// for tables with more than one column.
- bool usecaption = (rowinfo[row].type == LT_NORMAL ||
- rowinfo[row].type == LT_FIRSTHEAD);
- for (size_t r = 0; r < row && usecaption; ++r)
- if (rowinfo[row].type != LT_NORMAL &&
- rowinfo[row].type != LT_FIRSTHEAD)
- usecaption = false;
- if (usecaption) {
- rowinfo[row].caption = true;
- for (size_t c = 1; c < cells.size(); ++c) {
- if (!cells[c].empty()) {
- cerr << "Moving cell content '"
- << cells[c]
- << "' into the caption cell. "
- "This will probably not work."
- << endl;
- cells[0] += cells[c];
- }
+ rowinfo[row].caption = true;
+ for (size_t c = 1; c < cells.size(); ++c) {
+ if (!cells[c].empty()) {
+ cerr << "Moving cell content '"
+ << cells[c]
+ << "' into the caption cell. "
+ "This will probably not work."
+ << endl;
+ cells[0] += cells[c];
}
- cells.resize(1);
- cellinfo[row][col].align = colinfo[col].align;
- cellinfo[row][col].multi = CELL_BEGIN_OF_MULTICOLUMN;
- } else {
- cellinfo[row][col].leftlines = colinfo[col].leftlines;
- cellinfo[row][col].rightlines = colinfo[col].rightlines;
- cellinfo[row][col].align = colinfo[col].align;
}
+ cells.resize(1);
+ cellinfo[row][col].align = colinfo[col].align;
+ cellinfo[row][col].multi = CELL_BEGIN_OF_MULTICOLUMN;
ostringstream os;
parse_text_in_inset(p, os, FLAG_CELL, false, context);
cellinfo[row][col].content += os.str();
- if (usecaption) {
- // add dummy multicolumn cells
- for (size_t c = 1; c < colinfo.size(); ++c)
- cellinfo[row][c].multi = CELL_PART_OF_MULTICOLUMN;
- }
+ // add dummy multicolumn cells
+ for (size_t c = 1; c < colinfo.size(); ++c)
+ cellinfo[row][c].multi = CELL_PART_OF_MULTICOLUMN;
} else {
+ bool turn = false;
+ int rotate = 0;
+ if (p.next_token().cs() == "begin") {
+ p.pushPosition();
+ p.get_token();
+ string const env = p.getArg('{', '}');
+ if (env == "sideways" || env == "turn") {
+ string angle = "90";
+ if (env == "turn") {
+ turn = true;
+ angle = p.getArg('{', '}');
+ }
+ active_environments.push_back(env);
+ p.ertEnvironment(env);
+ active_environments.pop_back();
+ p.skip_spaces();
+ if (!p.good() && support::isStrInt(angle))
+ rotate = convert<int>(angle);
+ }
+ p.popPosition();
+ }
cellinfo[row][col].leftlines = colinfo[col].leftlines;
cellinfo[row][col].rightlines = colinfo[col].rightlines;
cellinfo[row][col].align = colinfo[col].align;
ostringstream os;
- parse_text_in_inset(p, os, FLAG_CELL, false, context);
+ if (rotate != 0) {
+ cellinfo[row][col].rotate = rotate;
+ p.get_token();
+ active_environments.push_back(p.getArg('{', '}'));
+ if (turn)
+ p.getArg('{', '}');
+ parse_text_in_inset(p, os, FLAG_END, false, context);
+ active_environments.pop_back();
+ preamble.registerAutomaticallyLoadedPackage("rotating");
+ } else {
+ parse_text_in_inset(p, os, FLAG_CELL, false, context);
+ }
cellinfo[row][col].content += os.str();
}
}
//cerr << "// output what we have\n";
// output what we have
+ string const rotate = "0";
os << "\n<lyxtabular version=\"3\" rows=\"" << rowinfo.size()
<< "\" columns=\"" << colinfo.size() << "\">\n";
os << "<features"
- << write_attribute("rotate", false)
+ << write_attribute("rotate", rotate)
<< write_attribute("booktabs", booktabs)
<< write_attribute("islongtable", is_long_tabular);
if (is_long_tabular) {