+ if ((row < 0) || (row >= rows_))
+ return 0;
+
+ int const fcell = GetFirstCellInRow(row);
+ int const n = NumberOfCellsInRow(fcell) + fcell;
+ int tmp = 0;
+
+ for (int i = fcell; i < n; ++i) {
+ if (TopLine(i))
+ ++tmp;
+ }
+ if (tmp == (n - fcell)){
+ os << "\\hline ";
+ } else if (tmp) {
+ for (int i = fcell; i < n; ++i) {
+ if (TopLine(i)) {
+ os << "\\cline{"
+ << column_of_cell(i) + 1
+ << '-'
+ << right_column_of_cell(i) + 1
+ << "} ";
+ }
+ }
+ } else {
+ return 0;
+ }
+ os << "\n";
+ return 1;
+}
+
+
+int LyXTabular::TeXBottomHLine(ostream & os, int row) const
+{
+ if ((row < 0) || (row >= rows_))
+ return 0;
+
+ int const fcell = GetFirstCellInRow(row);
+ int const n = NumberOfCellsInRow(fcell) + fcell;
+ int tmp = 0;
+
+ for (int i = fcell; i < n; ++i) {
+ if (BottomLine(i))
+ ++tmp;
+ }
+ if (tmp == (n-fcell)){
+ os << "\\hline";
+ } else if (tmp) {
+ for (int i = fcell; i < n; ++i) {
+ if (BottomLine(i)) {
+ os << "\\cline{"
+ << column_of_cell(i) + 1
+ << '-'
+ << right_column_of_cell(i) + 1
+ << "} ";
+ }
+ }
+ } else {
+ return 0;
+ }
+ os << "\n";
+ return 1;
+}
+
+
+int LyXTabular::TeXCellPreamble(ostream & os, int cell) const
+{
+ int ret = 0;
+
+ if (GetRotateCell(cell)) {
+ os << "\\begin{sideways}\n";
+ ++ret;
+ }
+ if (IsMultiColumn(cell)) {
+ os << "\\multicolumn{" << cells_in_multicolumn(cell) << "}{";
+ if (!cellinfo_of_cell(cell)->align_special.empty()) {
+ os << cellinfo_of_cell(cell)->align_special << "}{";
+ } else {
+ if (LeftLine(cell))
+ os << '|';
+ if (!GetPWidth(cell).empty()) {
+ switch (GetVAlignment(cell)) {
+ case LYX_VALIGN_TOP:
+ os << "p";
+ break;
+ case LYX_VALIGN_CENTER:
+ os << "m";
+ break;
+ case LYX_VALIGN_BOTTOM:
+ os << "b";
+ break;
+ }
+ os << "{" << GetPWidth(cell) << '}';
+ } else {
+ switch (GetAlignment(cell)) {
+ case LYX_ALIGN_LEFT:
+ os << 'l';
+ break;
+ case LYX_ALIGN_RIGHT:
+ os << 'r';
+ break;
+ default:
+ os << 'c';
+ break;
+ }
+ }
+ if (RightLine(cell))
+ os << '|';
+ if (((cell + 1) < numberofcells) && !IsFirstCellInRow(cell+1) &&
+ LeftLine(cell+1))
+ os << '|';
+ os << "}{";
+ }
+ }
+ if (GetUsebox(cell) == BOX_PARBOX) {
+ os << "\\parbox[";
+ switch (GetVAlignment(cell)) {
+ case LYX_VALIGN_TOP:
+ os << "t";
+ break;
+ case LYX_VALIGN_CENTER:
+ os << "c";
+ break;
+ case LYX_VALIGN_BOTTOM:
+ os << "b";
+ break;
+ }
+ os << "]{" << GetPWidth(cell) << "}{";
+ } else if (GetUsebox(cell) == BOX_MINIPAGE) {
+ os << "\\begin{minipage}[";
+ switch (GetVAlignment(cell)) {
+ case LYX_VALIGN_TOP:
+ os << "t";
+ break;
+ case LYX_VALIGN_CENTER:
+ os << "m";
+ break;
+ case LYX_VALIGN_BOTTOM:
+ os << "b";
+ break;
+ }
+ os << "]{" << GetPWidth(cell) << "}\n";
+ ++ret;
+ }
+ return ret;
+}
+
+
+int LyXTabular::TeXCellPostamble(ostream & os, int cell) const
+{
+ int ret = 0;
+
+ // usual cells
+ if (GetUsebox(cell) == BOX_PARBOX)
+ os << "}";
+ else if (GetUsebox(cell) == BOX_MINIPAGE) {
+ os << "%\n\\end{minipage}";
+ ret += 2;
+ }
+ if (IsMultiColumn(cell)){
+ os << '}';
+ }
+ if (GetRotateCell(cell)) {
+ os << "%\n\\end{sideways}";
+ ++ret;
+ }
+ return ret;
+}
+
+
+int LyXTabular::Latex(Buffer const * buf,
+ ostream & os, bool fragile, bool fp) const
+{
+ int ret = 0;
+ int cell = 0;
+
+ //+---------------------------------------------------------------------
+ //+ first the opening preamble +
+ //+---------------------------------------------------------------------
+
+ if (rotate) {
+ os << "\\begin{sideways}\n";
+ ++ret;
+ }
+ if (is_long_tabular)
+ os << "\\begin{longtable}{";
+ else
+ os << "\\begin{tabular}{";
+ for (int i = 0; i < columns_; ++i) {
+ if (column_info[i].left_line)
+ os << '|';
+ if (!column_info[i].align_special.empty()) {
+ os << column_info[i].align_special;
+ } else if (!column_info[i].p_width.empty()) {
+ switch (column_info[i].valignment) {
+ case LYX_VALIGN_TOP:
+ os << "p";
+ break;
+ case LYX_VALIGN_CENTER:
+ os << "m";
+ break;
+ case LYX_VALIGN_BOTTOM:
+ os << "b";
+ break;
+ }
+ os << "{"
+ << column_info[i].p_width
+ << '}';
+ } else {
+ switch (column_info[i].alignment) {
+ case LYX_ALIGN_LEFT:
+ os << 'l';
+ break;
+ case LYX_ALIGN_RIGHT:
+ os << 'r';
+ break;
+ default:
+ os << 'c';
+ break;
+ }
+ }
+ if (column_info[i].right_line)
+ os << '|';
+ }
+ os << "}\n";
+ ++ret;
+
+ //+---------------------------------------------------------------------
+ //+ the single row and columns (cells) +
+ //+---------------------------------------------------------------------
+
+ for (int i = 0; i < rows_; ++i) {
+ ret += TeXTopHLine(os, i);
+ int bret = ret;
+ if (IsLongTabular()) {
+ if ((endhead < 0) && (i == (abs(endhead)-1))) {
+ os << "\\endhead\n";
+ ++ret;
+ }
+ if ((endfirsthead < 0) && (i == (abs(endfirsthead)-1))) {
+ os << "\\endfirsthead\n";
+ ++ret;
+ }
+ if ((endfoot < 0) && (i == (abs(endfoot)-1))) {
+ os << "\\endfoot\n";
+ ++ret;
+ }
+ if ((endlastfoot < 0) && (i == (abs(endlastfoot)-1))) {
+ os << "\\endlastfoot\n";
+ ++ret;
+ }
+ }
+ if (ret > bret) {
+ ret += TeXBottomHLine(os, i-1);
+ ret += TeXTopHLine(os, i);
+ }
+ for (int j = 0; j < columns_; ++j) {
+ if (IsPartOfMultiColumn(i,j))
+ continue;
+ ret += TeXCellPreamble(os, cell);
+ InsetText * inset = GetCellInset(cell);
+
+ bool rtl = inset->par->isRightToLeftPar(buf->params) &&
+#ifndef NEW_INSETS
+ inset->par->Last() > 0 && GetPWidth(cell).empty();
+#else
+ inset->par->size() > 0 && GetPWidth(cell).empty();
+#endif
+ if (rtl)
+ os << "\\R{";
+ ret += inset->Latex(buf, os, fragile, fp);
+ if (rtl)
+ os << "}";
+
+ ret += TeXCellPostamble(os, cell);
+ if (!IsLastCellInRow(cell)) { // not last cell in row
+ os << "&\n";
+ ++ret;
+ }
+ ++cell;
+ }
+ os << "\\\\\n";
+ ret += TeXBottomHLine(os, i);
+ bret = ret;
+ if (IsLongTabular()) {
+ if ((endhead > 0) && (i == (endhead - 1))) {
+ os << "\\endhead\n";
+ ++ret;
+ }
+ if ((endfirsthead > 0) && (i == (endfirsthead - 1))) {
+ os << "\\endfirsthead\n";
+ ++ret;
+ }
+ if ((endfoot > 0) && (i == (endfoot - 1))) {
+ os << "\\endfoot\n";
+ ++ret;
+ }
+ if ((endlastfoot > 0) && (i == (endlastfoot - 1))) {
+ os << "\\endlastfoot\n";
+ ++ret;
+ }
+// if (ret > bret)
+// ret += TeXBottomHLine(os, i);
+ if (row_info[i].newpage) {
+ os << "\\newpage\n";
+ ++ret;
+ }
+ }
+ }
+
+ //+---------------------------------------------------------------------
+ //+ the closing of the tabular +
+ //+---------------------------------------------------------------------
+
+ if (is_long_tabular)
+ os << "\\end{longtable}";
+ else
+ os << "\\end{tabular}";
+ if (rotate) {
+ os << "\n\\end{sideways}";
+ ++ret;
+ }
+
+ return ret;
+}
+
+
+int LyXTabular::DocBook(Buffer const * buf, ostream & os) const
+{
+ int ret = 0;
+
+ //+---------------------------------------------------------------------
+ //+ first the opening preamble +
+ //+---------------------------------------------------------------------
+
+ os << "<tgroup cols=\"" << columns_
+ << "\" colsep=\"1\" rowsep=\"1\">\n";
+
+ for (int i = 0; i < columns_; ++i) {
+ os << "<colspec colname=\"col" << i << "\" align=\"";
+ switch (column_info[i].alignment) {
+ case LYX_ALIGN_LEFT:
+ os << "left";
+ break;
+ case LYX_ALIGN_RIGHT:
+ os << "right";
+ break;
+ default:
+ os << "center";
+ break;
+ }
+ os << "\"/>\n";
+ ++ret;
+ }
+
+ //+---------------------------------------------------------------------
+ //+ the single row and columns (cells) +
+ //+---------------------------------------------------------------------
+
+ int cell = 0;
+ os << "<tbody>\n";
+ for (int i = 0; i < rows_; ++i) {
+ os << "<row>\n";
+ for (int j = 0; j < columns_; ++j) {
+ if (IsPartOfMultiColumn(i, j))
+ continue;
+
+ os << "<entry align=\"";
+ switch (GetAlignment(cell)) {
+ case LYX_ALIGN_LEFT:
+ os << "left";
+ break;
+ case LYX_ALIGN_RIGHT:
+ os << "right";
+ break;
+ default:
+ os << "center";
+ break;
+ }
+
+ os << "\" valign=\"";
+ switch (GetVAlignment(cell)) {
+ case LYX_VALIGN_TOP:
+ os << "top";
+ break;
+ case LYX_VALIGN_BOTTOM:
+ os << "bottom";
+ break;
+ case LYX_VALIGN_CENTER:
+ os << "middle";
+ }
+ os << "\"";
+
+ if (IsMultiColumn(cell)) {
+ os << " namest=\"col" << j << "\" ";
+ os << "nameend=\"col" << j + cells_in_multicolumn(cell) - 1<< "\"";
+ }
+
+ os << ">";
+ ret += GetCellInset(cell)->DocBook(buf, os);
+ os << "</entry>";
+ ++cell;
+ }
+ os << "</row>\n";
+ }
+ os << "</tbody>\n";
+ //+---------------------------------------------------------------------
+ //+ the closing of the tabular +
+ //+---------------------------------------------------------------------
+
+ os << "</tgroup>";
+ ++ret;
+
+ return ret;
+}
+
+
+static
+inline
+void print_n_chars(ostream & os, unsigned char ch, int n)
+{
+ os << string(n, ch);
+}
+
+
+int LyXTabular::AsciiTopHLine(ostream & os, int row,
+ vector<unsigned int> const & clen) const
+{
+ int const fcell = GetFirstCellInRow(row);
+ int const n = NumberOfCellsInRow(fcell) + fcell;
+ int tmp = 0;
+
+ for (int i = fcell; i < n; ++i) {
+ if (TopLine(i)) {
+ ++tmp;
+ break;
+ }
+ }
+ if (!tmp)
+ return 0;
+
+ unsigned char ch;
+ for (int i = fcell; i < n; ++i) {
+ if (TopLine(i)) {
+ if (LeftLine(i))
+ os << "+-";
+ else
+ os << "--";
+ ch = '-';
+ } else {
+ os << " ";
+ ch = ' ';
+ }
+ int column = column_of_cell(i);
+ int len = clen[column];
+ while(IsPartOfMultiColumn(row, ++column))
+ len += clen[column] + 4;
+ print_n_chars(os, ch, len);
+ if (TopLine(i)) {
+ if (RightLine(i))
+ os << "-+";
+ else
+ os << "--";
+ } else {
+ os << " ";
+ }
+ }
+ os << endl;
+ return 1;
+}
+
+
+int LyXTabular::AsciiBottomHLine(ostream & os, int row,
+ vector<unsigned int> const & clen) const
+{
+ int const fcell = GetFirstCellInRow(row);
+ int const n = NumberOfCellsInRow(fcell) + fcell;
+ int tmp = 0;
+
+ for (int i = fcell; i < n; ++i) {
+ if (BottomLine(i)) {
+ ++tmp;
+ break;
+ }
+ }
+ if (!tmp)
+ return 0;
+
+ unsigned char ch;
+ for (int i = fcell; i < n; ++i) {
+ if (BottomLine(i)) {
+ if (LeftLine(i))
+ os << "+-";
+ else
+ os << "--";
+ ch = '-';
+ } else {
+ os << " ";
+ ch = ' ';
+ }
+ int column = column_of_cell(i);
+ int len = clen[column];
+ while(IsPartOfMultiColumn(row, ++column))
+ len += clen[column] + 4;
+ print_n_chars(os, ch, len);
+ if (BottomLine(i)) {
+ if (RightLine(i))
+ os << "-+";
+ else
+ os << "--";
+ } else {
+ os << " ";
+ }
+ }
+ os << endl;
+ return 1;
+}
+
+
+int LyXTabular::AsciiPrintCell(Buffer const * buf, ostream & os,
+ int cell, int row, int column,
+ vector<unsigned int> const & clen) const
+{
+ ostringstream sstr;
+ int ret = GetCellInset(cell)->Ascii(buf, sstr, 0);
+
+ if (LeftLine(cell))
+ os << "| ";
+ else
+ os << " ";
+
+ unsigned int len1 = sstr.str().length();
+ unsigned int len2 = clen[column];
+ while(IsPartOfMultiColumn(row, ++column))
+ len2 += clen[column] + 4;
+ len2 -= len1;
+
+ switch (GetAlignment(cell)) {
+ default:
+ case LYX_ALIGN_LEFT:
+ len1 = 0;
+ break;
+ case LYX_ALIGN_RIGHT:
+ len1 = len2;
+ len2 = 0;
+ break;
+ case LYX_ALIGN_CENTER:
+ len1 = len2 / 2;
+ len2 -= len1;
+ break;
+ }
+
+ for (unsigned int i = 0; i < len1; ++i)
+ os << " ";
+ os << sstr.str();
+ for (unsigned int i = 0; i < len2; ++i)
+ os << " ";
+ if (RightLine(cell))
+ os << " |";
+ else
+ os << " ";
+
+ return ret;
+}
+
+
+int LyXTabular::Ascii(Buffer const * buf, ostream & os) const
+{
+ int ret = 0;
+
+ //+---------------------------------------------------------------------
+ //+ first calculate the width of the single columns +
+ //+---------------------------------------------------------------------
+ vector<unsigned int> clen(columns_);
+
+ // first all non (real) multicolumn cells!
+ for (int j = 0; j < columns_; ++j) {
+ clen[j] = 0;
+ for (int i = 0; i < rows_; ++i) {
+ int cell = GetCellNumber(i, j);
+ if (IsMultiColumn(cell, true))
+ continue;
+ ostringstream sstr;
+ GetCellInset(cell)->Ascii(buf, sstr, 0);
+ if (clen[j] < sstr.str().length())
+ clen[j] = sstr.str().length();
+ }
+ }
+ // then all (real) multicolumn cells!
+ for (int j = 0; j < columns_; ++j) {
+ for (int i = 0; i < rows_; ++i) {
+ int cell = GetCellNumber(i, j);
+ if (!IsMultiColumn(cell, true) || IsPartOfMultiColumn(i, j))
+ continue;
+ ostringstream sstr;
+ GetCellInset(cell)->Ascii(buf, sstr, 0);
+ int len = int(sstr.str().length());
+ int const n = cells_in_multicolumn(cell);
+ for (int k = j; (len > 0) && (k < (j + n - 1)); ++k)
+ len -= clen[k];
+ if (len > int(clen[j + n - 1]))
+ clen[j + n - 1] = len;
+ }
+ }
+ int cell = 0;
+ for (int i = 0; i < rows_; ++i) {
+ AsciiTopHLine(os, i, clen);
+ for (int j = 0; j < columns_; ++j) {
+ if (IsPartOfMultiColumn(i,j))
+ continue;
+ ret += AsciiPrintCell(buf, os, cell, i, j, clen);
+ ++cell;
+ }
+ os << endl;
+ AsciiBottomHLine(os, i, clen);
+ }
+ return ret;