Lars Gullik Bjønnes wrote:
> Georg Baum <[EMAIL PROTECTED]>
> writes:
>
> | class ColInfo {
> | public:
> | - ColInfo() : align('c'), rightline(false), leftline(false) {}
> | + ColInfo() : align('n'), valign('n'), rightlines(0), leftlines(0) {}
> | /// column alignment
> | char align;
> | + /// vertical alignment
> | + char valign;
>
> We really should have proper type for these.
> But that is for later.
Yes, I think we can reuse code and data structures from LyX in the future.
For now the character is simply the LaTeX alignment character (or 'n' for
"none").
> | @@ -114,6 +139,14 @@ inline char const * verbose_align(char c
> | }
> |
> |
> | +/// translate a vertical alignment (as stored in ColInfo and CellInfo)
> | to LyX +inline char const * verbose_valign(char c)
> | +{
> | + // The default value for no special alignment is "top".
> | + return c == 'p' ? "top" : c == 'm' ? "middle" : c == 'b' ? "bottom" :
> | "top"; +}
>
> Can we have this a bit more readable? a switch perhaps?
Yes. This was simply copy and paste from verbose_align. I have changed both.
> | + if (!ci.width.empty()) {
> | + switch (ci.align) {
> | + case 'l':
> | + ci.special += ">{\\raggedright}";
> | + case 'r':
> | + ci.special += ">{\\raggedleft}";
> | + case 'c':
> | + ci.special += ">{\\centering}";
> | + }
>
> If fall-through is ok here, then please comment it.
> (Is it ok?)
No, it is not. I forgot the breaks. An updated patch and updated test file
which exercises this part of the code is attached.
To all: Please test it!
Georg
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[latin1]{inputenc}
\usepackage{array}
\begin{document}
A table with different columns:
\begin{tabular}{lcrp{1cm}b{1cm}m{1cm}*{3}{|c|}}
1&
2&
3&
4&
5&
6&
7&
8&
9\\
1&
2&
3&
4&
5&
6&
7&
8&
9
\end{tabular}
[EMAIL PROTECTED]>{.}c<{.}r!{,}p{1cm}b{1cm}m{1cm}*{3}{|c|}}
1&
2&
3&
4&
5&
6&
7&
8&
9\\
1&
2&
3&
4&
5&
6&
7&
8&
9
\end{tabular}
\begin{tabular}{>{\raggedright}p{1cm}>{\raggedleft}p{1cm}>{\centering}p{1cm}llllll}
1&
2&
3&
4&
5&
6&
7&
8&
9\\
1&
2&
3&
4&
5&
6&
7&
8&
9
\end{tabular}
\begin{tabular}{||||>{\raggedright}p{1cm}||||>{\raggedleft}p{1cm}||||>{\centering}p{1cm}|||llllll}
1&
2&
3&
4&
5&
6&
7&
8&
9\\
1&
2&
3&
4&
5&
6&
7&
8&
9
\end{tabular}
Separators with 'l' columns:
[EMAIL PROTECTED]
1&
2&
3&
4&
5&
6&
7&
8&
9\\
1&
2&
3&
4&
5&
6&
7&
8&
9
\end{tabular}
A table without the last tabularnewline
\begin{tabular}{l|c|r}
left&
center&
right\\
left&
center&
right
\end{tabular}
A table with the last tabularnewline
\begin{tabular}{l|c|r}
left&
center&
right\\
left&
center&
right\\
\end{tabular}
A table with a hline and the last tabularnewline
\begin{tabular}{l|c|r}
left&
center&
right\\
left&
center&
right\\
\hline
\end{tabular}
A table with multicolumns
\begin{tabular}{ccc}
col1&
col2&
col3\tabularnewline
\multicolumn{2}{|c|}{left rule multicol1-2 right rule}&
col3\tabularnewline
\multicolumn{2}{|c|}{left rule multicol1-2 right rule}&
\multicolumn{1}{|c|}{left rule multicol3 right rule}\tabularnewline
\multicolumn{2}{|c|}{left rule multicol1-2 right rule}&
\multicolumn{1}{c}{multicol3}\tabularnewline
\multicolumn{2}{c}{multicol1-2}&
\multicolumn{1}{|c|}{left rule multicol3 right rule}\tabularnewline
\multicolumn{2}{||c||}{2 left rules multicol1-2 2 right rules}&
\multicolumn{1}{|c|}{left rule multicol3 right rule}\tabularnewline
\multicolumn{2}{|||c|||}{3 left rules multicol1-2 3 right rules}&
\multicolumn{1}{|c|}{left rule multicol3 right rule}\tabularnewline
\multicolumn{2}{||c||}{2 left rules multicol1-2 2 right rules}&
\multicolumn{1}{c}{multicol3}\tabularnewline
\multicolumn{2}{|||c|||}{3 left rules multicol1-2 3 right rules}&
\multicolumn{1}{c}{multicol3}\tabularnewline
\multicolumn{2}{|c|}{left rule multicol1-2 right rule}&
\multicolumn{1}{||c||}{2 left rules multicol3 2 right rules}\tabularnewline
\multicolumn{2}{||c||}{2 left rules multicol1-2 2 right rules}&
\multicolumn{1}{|||c|||}{3 left rules multicol3 3 right rules}\tabularnewline
\end{tabular}
A table with vrules:
\begin{tabular}{|c|c|c|}
col1&
col2&
col3 \tabularnewline
\multicolumn{2}{|c|}{left rule multicol1-2 right rule}&
col3\tabularnewline
\multicolumn{2}{|c|}{left rule multicol1-2 right rule}&
\multicolumn{1}{|c|}{left rule multicol3 right rule}\tabularnewline
\multicolumn{2}{|c|}{left rule multicol1-2 right rule}&
\multicolumn{1}{c}{multicol3}\tabularnewline
\multicolumn{2}{c}{multicol1-2}&
\multicolumn{1}{|c|}{left rule multicol3 right rule}\tabularnewline
\multicolumn{2}{||c||}{2 left rules multicol1-2 2 right rules}&
\multicolumn{1}{|c|}{left rule multicol3 right rule}\tabularnewline
\multicolumn{2}{|||c|||}{3 left rules multicol1-2 3 right rules}&
\multicolumn{1}{|c|}{left rule multicol3 right rule}\tabularnewline
\multicolumn{2}{||c||}{2 left rules multicol1-2 2 right rules}&
\multicolumn{1}{c}{multicol3}\tabularnewline
\multicolumn{2}{|||c|||}{3 left rules multicol1-2 3 right rules}&
\multicolumn{1}{c}{multicol3}\tabularnewline
\multicolumn{2}{|c|}{left rule multicol1-2 right rule}&
\multicolumn{1}{||c||}{2 left rules multicol3 2 right rules}\tabularnewline
\multicolumn{2}{||c||}{2 left rules multicol1-2 2 right rules}&
\multicolumn{1}{|||c|||}{3 left rules multicol3 3 right rules}\tabularnewline
\end{tabular}
\end{document}
Index: src/tex2lyx/ChangeLog
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/tex2lyx/ChangeLog,v
retrieving revision 1.84
diff -u -p -r1.84 ChangeLog
--- src/tex2lyx/ChangeLog 25 Feb 2005 22:13:12 -0000 1.84
+++ src/tex2lyx/ChangeLog 7 Mar 2005 12:15:39 -0000
@@ -1,3 +1,18 @@
+2005-03-07 Georg Baum <[EMAIL PROTECTED]>
+
+ * table.C (verbose_valign): new
+ * table.C (string2int): remove, use convert<int>() instead since the
+ default value is always 0 and this is also the default of
+ convert<int>().
+ * table.C (ci2special): new
+ * table.C (handle_colalign): handle b{}, p{} and m{} correctly
+ * table.C (handle_colalign): fix >{\raggedleft} and >{\raggedright}
+ (they were swapped)
+ * table.C (handle_colalign): handle >{\centering}
+ * table.C (handle_colalign): handle <{}, *{}, @{} and !{}
+ * table.C (fix_colalign): new
+ * table.C (handle_tabular): fix multicolumns with vertical lines
+
2005-02-25 Angus Leeming <[EMAIL PROTECTED]>
* context.h: declare as "class Font" rather than "struct Font".
Index: src/tex2lyx/table.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/tex2lyx/table.C,v
retrieving revision 1.29
diff -u -p -r1.29 table.C
--- src/tex2lyx/table.C 25 Feb 2005 22:13:13 -0000 1.29
+++ src/tex2lyx/table.C 7 Mar 2005 12:15:39 -0000
@@ -16,6 +16,9 @@
#include "tex2lyx.h"
+#include "support/convert.h"
+#include "support/lstrings.h"
+
#include <cctype>
#include <fstream>
#include <iostream>
@@ -40,17 +43,19 @@ namespace {
class ColInfo {
public:
- ColInfo() : align('c'), rightline(false), leftline(false) {}
+ ColInfo() : align('n'), valign('n'), rightlines(0), leftlines(0) {}
/// column alignment
char align;
+ /// vertical alignment
+ char valign;
/// column width
string width;
/// special column alignment
string special;
- /// how many lines on the right?
- int rightline;
- /// a line on the left?
- bool leftline;
+ /// number of lines on the right
+ int rightlines;
+ /// number of lines on the left
+ int leftlines;
};
@@ -86,31 +91,76 @@ public:
};
+enum Multicolumn {
+ /// A normal cell
+ CELL_NORMAL = 0,
+ /// A multicolumn cell. The number of columns is <tt>1 + number
+ /// of CELL_PART_OF_MULTICOLUMN cells</tt> that follow directly
+ CELL_BEGIN_OF_MULTICOLUMN,
+ /// This is a dummy cell (part of a multicolumn cell)
+ CELL_PART_OF_MULTICOLUMN
+};
+
+
class CellInfo {
public:
- CellInfo() : multi(0), align('n'), leftline(false), rightline(false),
- topline(false), bottomline(false) {}
+ CellInfo() : multi(CELL_NORMAL), align('n'), valign('n'),
+ leftlines(0), rightlines(0), topline(false),
+ bottomline(false), rotate(false) {}
/// cell content
string content;
/// multicolumn flag
- int multi;
+ Multicolumn multi;
/// cell alignment
char align;
- /// do we have a line on the left?
- bool leftline;
- /// do we have a line on the right?
- bool rightline;
+ /// vertical cell alignment
+ char valign;
+ /// number of lines on the left
+ int leftlines;
+ /// number of lines on the right
+ int rightlines;
/// do we have a line above?
bool topline;
/// do we have a line below?
bool bottomline;
+ /// is the cell rotated?
+ bool rotate;
+ /// width for multicolumn cells
+ string width;
+ /// special formatting for multicolumn cells
+ string special;
};
/// translate a horizontal alignment (as stored in ColInfo and CellInfo) to LyX
inline char const * verbose_align(char c)
{
- return c == 'c' ? "center" : c == 'r' ? "right" : c == 'l' ? "left" : "none";
+ switch (c) {
+ case 'c':
+ return "center";
+ case 'r':
+ return "right";
+ case 'l':
+ return "left";
+ default:
+ return "none";
+ }
+}
+
+
+/// translate a vertical alignment (as stored in ColInfo and CellInfo) to LyX
+inline char const * verbose_valign(char c)
+{
+ // The default value for no special alignment is "top".
+ switch (c) {
+ case 'm':
+ return "middle";
+ case 'b':
+ return "bottom";
+ case 'p':
+ default:
+ return "top";
+ }
}
@@ -130,44 +180,96 @@ string const write_attribute(string cons
}
-int string2int(string const & s, int deflt = 0)
-{
- istringstream is(s);
- int i = deflt;
- is >> i;
- return i;
-}
-
-
-/* rather brutish way to code table structure in a string:
+/*! rather brutish way to code table structure in a string:
+\verbatim
\begin{tabular}{ccc}
1 & 2 & 3\\ \hline
\multicolumn{2}{c}{4} & 5 //
6 & 7 \\
+ 8 \endhead
\end{tabular}
+\endverbatim
gets "translated" to:
- HLINE 1 TAB 2 TAB 3 HLINE HLINE LINE
- \hline HLINE \multicolumn{2}{c}{4} TAB 5 HLINE HLINE LINE
- HLINE 6 TAB 7 HLINE HLINE LINE
-*/
+\verbatim
+ HLINE 1 TAB 2 TAB 3 HLINE HLINE LINE
+ \hline HLINE \multicolumn{2}{c}{4} TAB 5 HLINE HLINE LINE
+ HLINE 6 TAB 7 HLINE HLINE LINE
+ HLINE 8 HLINE \endhead HLINE LINE
+\endverbatim
+ */
char const TAB = '\001';
char const LINE = '\002';
char const HLINE = '\004';
-/// handle column specifications for tabulars and multicolumns
-void handle_colalign(Parser & p, vector<ColInfo> & colinfo)
+/*!
+ * Move the information in leftlines, rightlines, align and valign to the
+ * special field. This is necessary if the special field is not empty,
+ * because LyX ignores leftlines, rightlines, align and valign in this case.
+ */
+void ci2special(ColInfo & ci)
{
- if (p.get_token().cat() != catBegin)
- cerr << "wrong syntax for table column alignment. '{' expected\n";
+ if (ci.width.empty() && ci.align == 'n')
+ // The alignment setting is already in special, since
+ // handle_colalign() never stores ci with these settings
+ // and ensures that leftlines == 0 and rightlines == 0 in
+ // this case.
+ return;
+
+ if (!ci.width.empty()) {
+ switch (ci.align) {
+ case 'l':
+ ci.special += ">{\\raggedright}";
+ break;
+ case 'r':
+ ci.special += ">{\\raggedleft}";
+ break;
+ case 'c':
+ ci.special += ">{\\centering}";
+ break;
+ }
+ if (ci.valign == 'n')
+ ci.special += 'p';
+ else
+ ci.special += ci.valign;
+ ci.special += '{' + ci.width + '}';
+ ci.width.erase();
+ } else
+ ci.special += ci.align;
+
+ for (int i = 0; i < ci.leftlines; ++i)
+ ci.special.insert(0, "|");
+ for (int i = 0; i < ci.rightlines; ++i)
+ ci.special += '|';
+ ci.leftlines = 0;
+ ci.rightlines = 0;
+ ci.align = 'n';
+ ci.valign = 'n';
+}
+
- char nextalign = 'b';
- bool leftline = false;
- for (Token t=p.get_token(); p.good() && t.cat() != catEnd; t = p.get_token()){
+/*!
+ * Handle column specifications for tabulars and multicolumns.
+ * The next token of the parser \p p must be an opening brace, and we read
+ * everything until the matching closing brace.
+ * The resulting column specifications are filled into \p colinfo. This is
+ * in an intermediate form. fix_colalign() makes it suitable for LyX output.
+ */
+void handle_colalign(Parser & p, vector<ColInfo> & colinfo,
+ ColInfo const & start)
+{
+ if (p.get_token().cat() != catBegin)
+ cerr << "Wrong syntax for table column alignment.\n"
+ "Expected '{', got '" << p.curr_token().asInput()
+ << "'.\n";
+
+ ColInfo next = start;
+ for (Token t = p.get_token(); p.good() && t.cat() != catEnd;
+ t = p.get_token()) {
#ifdef FILEDEBUG
cerr << "t: " << t << " c: '" << t.character() << "'\n";
#endif
@@ -185,57 +287,179 @@ void handle_colalign(Parser & p, vector<
switch (t.character()) {
case 'c':
case 'l':
- case 'r': {
- ColInfo ci;
- ci.align = t.character();
- if (colinfo.size() && colinfo.back().rightline > 1) {
- ci.leftline = true;
- --colinfo.back().rightline;
- }
- colinfo.push_back(ci);
+ case 'r':
+ // new column, horizontal aligned
+ next.align = t.character();
+ if (!next.special.empty())
+ ci2special(next);
+ colinfo.push_back(next);
+ next = ColInfo();
break;
- }
case 'p':
- colinfo.push_back(ColInfo());
- colinfo.back().align = nextalign;
- colinfo.back().width = p.verbatim_item();
- nextalign = 'b';
+ case 'b':
+ case 'm':
+ // new column, vertical aligned box
+ next.valign = t.character();
+ next.width = p.verbatim_item();
+ if (!next.special.empty())
+ ci2special(next);
+ colinfo.push_back(next);
+ next = ColInfo();
break;
case '|':
- if (colinfo.empty())
- leftline = true;
+ // vertical rule
+ if (colinfo.empty()) {
+ if (next.special.empty())
+ ++next.leftlines;
+ else
+ next.special += '|';
+ } else if (colinfo.back().special.empty())
+ ++colinfo.back().rightlines;
+ else if (next.special.empty())
+ ++next.leftlines;
else
- ++colinfo.back().rightline;
+ colinfo.back().special += '|';
break;
case '>': {
- string s = p.verbatim_item();
- if (s == "\\raggedleft ")
- nextalign = 'l';
- else if (s == "\\raggedright ")
- nextalign = 'r';
- else
- cerr << "unknown '>' column '" << s << "'\n";
+ // text before the next column
+ string const s = trim(p.verbatim_item());
+ if (next.special.empty() &&
+ next.align == 'n') {
+ // Maybe this can be converted to a
+ // horizontal alignment setting for
+ // fixed width columns
+ if (s == "\\raggedleft")
+ next.align = 'r';
+ else if (s == "\\raggedright")
+ next.align = 'l';
+ else if (s == "\\centering")
+ next.align = 'c';
+ else
+ next.special = ">{" + s + '}';
+ } else
+ next.special += ">{" + s + '}';
break;
}
- default:
- if (special_columns.find(t.character()) != special_columns.end()) {
- ColInfo ci;
- ci.align = 'c';
- ci.special += t.character();
- int const nargs = special_columns[t.character()];
- for (int i = 0; i < nargs; ++i)
- ci.special += "{" + p.verbatim_item() + "}";
- //cerr << "handling special column '" << t << "' " << nargs
- // << " '" << ci.special << "'\n";
- colinfo.push_back(ci);
+ case '<': {
+ // text after the last column
+ string const s = trim(p.verbatim_item());
+ if (colinfo.empty())
+ // This is not possible in LaTeX.
+ cerr << "Ignoring separator '<{"
+ << s << "}'." << endl;
+ else {
+ ColInfo & ci = colinfo.back();
+ ci2special(ci);
+ ci.special += "<{" + s + '}';
+ }
+ break;
+ }
+ case '*': {
+ // *{n}{arg} means 'n' columns of type 'arg'
+ string const num = p.verbatim_item();
+ string const arg = p.verbatim_item();
+ size_t const n = convert<unsigned int>(num);
+ if (!arg.empty() && n > 0) {
+ string s("{");
+ for (size_t i = 0; i < n; ++i)
+ s += arg;
+ s += '}';
+ Parser p2(s);
+ handle_colalign(p2, colinfo, next);
+ next = ColInfo();
} else {
- cerr << "ignoring special separator '" << t << "'\n";
+ cerr << "Ignoring column specification"
+ " '*{" << num << "}{"
+ << arg << "}'." << endl;
}
break;
}
+ case '@':
+ // text instead of the column spacing
+ case '!':
+ // text in addition to the column spacing
+ next.special += t.character();
+ next.special += '{' + p.verbatim_item() + '}';
+ break;
+ 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;
+ break;
+ }
}
- if (colinfo.size() && leftline)
- colinfo[0].leftline = true;
+
+ // Maybe we have some column separators that need to be added to the
+ // last column?
+ ci2special(next);
+ if (!next.special.empty()) {
+ ColInfo & ci = colinfo.back();
+ ci2special(ci);
+ ci.special += next.special;
+ next.special.erase();
+ }
+}
+
+
+/*!
+ * Move the left and right lines and alignment settings of the column \p ci
+ * to the special field if necessary.
+ */
+void fix_colalign(ColInfo & ci)
+{
+ if (ci.leftlines > 1 || ci.rightlines > 1)
+ ci2special(ci);
+}
+
+
+/*!
+ * LyX can't handle more than one vertical line at the left or right side
+ * of a column.
+ * This function moves the left and right lines and alignment settings of all
+ * columns in \p colinfo to the special field if necessary.
+ */
+void fix_colalign(vector<ColInfo> & colinfo)
+{
+ // Try to move extra leftlines to the previous column.
+ // We do this only if both special fields are empty, otherwise we
+ // can't tell wether the result will be the same.
+ for (size_t col = 0; col < colinfo.size(); ++col) {
+ if (colinfo[col].leftlines > 1 &&
+ colinfo[col].special.empty() && col > 0 &&
+ colinfo[col - 1].rightlines == 0 &&
+ colinfo[col - 1].special.empty()) {
+ ++colinfo[col - 1].rightlines;
+ --colinfo[col].leftlines;
+ }
+ }
+ // Try to move extra rightlines to the next column
+ for (size_t col = 0; col < colinfo.size(); ++col) {
+ if (colinfo[col].rightlines > 1 &&
+ colinfo[col].special.empty() &&
+ col < colinfo.size() - 1 &&
+ colinfo[col + 1].leftlines == 0 &&
+ colinfo[col + 1].special.empty()) {
+ ++colinfo[col + 1].leftlines;
+ --colinfo[col].rightlines;
+ }
+ }
+ // Move the lines and alignment settings to the special field if
+ // necessary
+ for (size_t col = 0; col < colinfo.size(); ++col)
+ fix_colalign(colinfo[col]);
}
@@ -551,6 +775,7 @@ void handle_tabular(Parser & p, ostream
{
string posopts = p.getOpt();
if (!posopts.empty()) {
+ // FIXME: Convert this to ERT
if (is_long_tabular)
cerr << "horizontal longtable";
else
@@ -558,10 +783,11 @@ void handle_tabular(Parser & p, ostream
cerr << " positioning '" << posopts << "' ignored\n";
}
- vector<ColInfo> colinfo;
+ vector<ColInfo> colinfo;
// handle column formatting
- handle_colalign(p, colinfo);
+ handle_colalign(p, colinfo, ColInfo());
+ fix_colalign(colinfo);
// first scan of cells
// use table mode to keep it minimal-invasive
@@ -630,14 +856,28 @@ void handle_tabular(Parser & p, ostream
vector<string> t;
split(arg, t, '-');
t.resize(2);
- size_t from = string2int(t[0]) - 1;
+ size_t from = convert<unsigned int>(t[0]);
+ if (from == 0)
+ cerr << "Could not parse "
+ "cline start column."
+ << endl;
+ else
+ // 1 based index -> 0 based
+ --from;
if (from >= colinfo.size()) {
cerr << "cline starts at non "
"existing column "
<< (from + 1) << endl;
from = colinfo.size() - 1;
}
- size_t to = string2int(t[1]) - 1;
+ size_t to = convert<unsigned int>(t[1]);
+ if (to == 0)
+ cerr << "Could not parse "
+ "cline end column."
+ << endl;
+ else
+ // 1 based index -> 0 based
+ --to;
if (to >= colinfo.size()) {
cerr << "cline ends at non "
"existing column "
@@ -691,6 +931,7 @@ void handle_tabular(Parser & p, ostream
if (row > 0)
rowinfo[row - 1].newpage = true;
else
+ // This does not work in LaTeX
cerr << "Ignoring "
"'\\newpage' "
"before rows."
@@ -706,63 +947,69 @@ void handle_tabular(Parser & p, ostream
// split into cells
vector<string> cells;
split(lines[row], cells, TAB);
- // Has the last multicolumn cell a rightline?
- bool last_rightline = false;
- for (size_t col = 0, cell = 0;
- cell < cells.size() && col < colinfo.size(); ++col, ++cell) {
+ for (size_t col = 0, cell = 0; cell < cells.size();
+ ++col, ++cell) {
//cerr << "cell content: '" << cells[cell] << "'\n";
+ if (col >= colinfo.size()) {
+ // This does not work in LaTeX
+ cerr << "Ignoring extra cell '"
+ << cells[cell] << "'." << endl;
+ continue;
+ }
Parser p(cells[cell]);
p.skip_spaces();
//cells[cell] << "'\n";
if (p.next_token().cs() == "multicolumn") {
// how many cells?
p.get_token();
- size_t const ncells = string2int(p.verbatim_item());
+ size_t const ncells =
+ convert<unsigned int>(p.verbatim_item());
// special cell properties alignment
vector<ColInfo> t;
- handle_colalign(p, t);
- cellinfo[row][col].multi = 1;
- cellinfo[row][col].align = t.front().align;
+ handle_colalign(p, t, ColInfo());
+ ColInfo & ci = t.front();
+
+ // The logic of LyX for multicolumn vertical
+ // lines is too complicated to reproduce it
+ // here (see LyXTabular::TeXCellPreamble()).
+ // Therefore we simply put everything in the
+ // special field.
+ ci2special(ci);
+
+ cellinfo[row][col].multi = CELL_BEGIN_OF_MULTICOLUMN;
+ cellinfo[row][col].align = ci.align;
+ cellinfo[row][col].special = ci.special;
+ cellinfo[row][col].leftlines = ci.leftlines;
+ cellinfo[row][col].rightlines = ci.rightlines;
ostringstream os;
parse_text_in_inset(p, os, FLAG_ITEM, false, context);
- cellinfo[row][col].content = os.str();
-
- // multicolumn cells are tricky: This
- // \multicolumn{2}{|c|}{col1-2}&
- // \multicolumn{2}{|c|}{col3-4} "\\"
- // gives | col1-2 | col3-4 | and not
- // | col1-2 || col3-4 |
- // So:
- if (last_rightline && t.front().leftline) {
- t.front().leftline = false;
+ if (!cellinfo[row][col].content.empty()) {
+ // This may or may not work in LaTeX,
+ // but it does not work in LyX.
+ // FIXME: Handle it correctly!
+ cerr << "Moving cell content '"
+ << cells[cell]
+ << "' into a multicolumn cell. "
+ "This will probably not work."
+ << endl;
}
- last_rightline = t.front().rightline;
-
- // multicolumn lines override normal cell lines
- cellinfo[row][col].leftline = t.front().leftline;
- cellinfo[row][col].rightline = t.front().rightline;
+ cellinfo[row][col].content += os.str();
// add dummy cells for multicol
for (size_t i = 0; i < ncells - 1 && col < colinfo.size(); ++i) {
++col;
- cellinfo[row][col].multi = 2;
+ cellinfo[row][col].multi = CELL_PART_OF_MULTICOLUMN;
cellinfo[row][col].align = 'c';
}
- // more than one line on the right?
- if (t.front().rightline > 1)
- cellinfo[row][col + 1].leftline = true;
-
} else {
- // FLAG_END is a hack, we need to read all of it
- cellinfo[row][col].leftline = colinfo[col].leftline;
- cellinfo[row][col].rightline = colinfo[col].rightline;
- cellinfo[row][col].align = colinfo[col].align;
+ 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);
- cellinfo[row][col].content = os.str();
- last_rightline = false;
+ cellinfo[row][col].content += os.str();
}
}
@@ -777,7 +1024,20 @@ void handle_tabular(Parser & p, ostream
cellinfo[row - 1][col].bottomline = true;
rowinfo.pop_back();
}
+ }
+ // Now we have the table structure and content in rowinfo, colinfo
+ // and cellinfo.
+ // Unfortunately LyX has some limitations that we need to work around.
+
+ // Convert cells with special content to multicolumn cells
+ // (LyX ignores the special field for non-multicolumn cells).
+ for (size_t row = 0; row < rowinfo.size(); ++row) {
+ for (size_t col = 0; col < cellinfo[row].size(); ++col) {
+ if (cellinfo[row][col].multi == CELL_NORMAL &&
+ !cellinfo[row][col].special.empty())
+ cellinfo[row][col].multi = CELL_BEGIN_OF_MULTICOLUMN;
+ }
}
//cerr << "// output what we have\n";
@@ -785,6 +1045,7 @@ void handle_tabular(Parser & p, ostream
os << "\n<lyxtabular version=\"3\" rows=\"" << rowinfo.size()
<< "\" columns=\"" << colinfo.size() << "\">\n";
os << "<features"
+ << write_attribute("rotate", false)
<< write_attribute("islongtable", is_long_tabular)
<< ">\n";
@@ -792,9 +1053,10 @@ void handle_tabular(Parser & p, ostream
for (size_t col = 0; col < colinfo.size(); ++col) {
os << "<column alignment=\""
<< verbose_align(colinfo[col].align) << "\""
- << " valignment=\"top\""
- << write_attribute("leftline", colinfo[col].leftline)
- << write_attribute("rightline", colinfo[col].rightline)
+ << " valignment=\""
+ << verbose_valign(colinfo[col].valign) << "\""
+ << write_attribute("leftline", colinfo[col].leftlines > 0)
+ << write_attribute("rightline", colinfo[col].rightlines > 0)
<< write_attribute("width", colinfo[col].width)
<< write_attribute("special", colinfo[col].special)
<< ">\n";
@@ -818,22 +1080,27 @@ void handle_tabular(Parser & p, ostream
for (size_t col = 0; col < colinfo.size(); ++col) {
CellInfo const & cell = cellinfo[row][col];
os << "<cell";
- if (cell.multi)
+ if (cell.multi != CELL_NORMAL)
os << " multicolumn=\"" << cell.multi << "\"";
os << " alignment=\"" << verbose_align(cell.align)
<< "\""
- << " valignment=\"top\""
+ << " valignment=\"" << verbose_valign(cell.valign)
+ << "\""
<< write_attribute("topline", cell.topline)
<< write_attribute("bottomline", cell.bottomline)
- << write_attribute("leftline", cell.leftline)
- << write_attribute("rightline", cell.rightline);
+ << write_attribute("leftline", cell.leftlines > 0)
+ << write_attribute("rightline", cell.rightlines > 0)
+ << write_attribute("rotate", cell.rotate);
//cerr << "\nrow: " << row << " col: " << col;
//if (cell.topline)
// cerr << " topline=\"true\"";
//if (cell.bottomline)
// cerr << " bottomline=\"true\"";
os << " usebox=\"none\""
- << ">"
+ << write_attribute("width", cell.width);
+ if (cell.multi != CELL_NORMAL)
+ os << write_attribute("special", cell.special);
+ os << ">"
<< "\n\\begin_inset Text\n"
<< cell.content
<< "\n\\end_inset\n"