Edwin Leuven wrote:
Stefan Schimanski wrote:
To bring this thread to the top again: what is the status for the alpha?

i would like to commit my tab lines patch before we freeze

and, latest version attached...
Index: development/FORMAT
===================================================================
--- development/FORMAT	(revision 23801)
+++ development/FORMAT	(working copy)
@@ -1,6 +1,9 @@
 LyX file-format changes
 -----------------------
 
+2008-03-15 Edwin Leuven <[EMAIL PROTECTED]>
+	* Format incremented to 320: ensure consistency between cell and row/col lines
+
 2008-03-10 Jürgen Spitzmüller <[EMAIL PROTECTED]>
 	* Format incremented to 319: hspace and extended hfill support.
 
@@ -956,3 +959,5 @@
 
  \end_inset
 
+
+
Index: lib/lyx2lyx/LyX.py
===================================================================
--- lib/lyx2lyx/LyX.py	(revision 23801)
+++ lib/lyx2lyx/LyX.py	(working copy)
@@ -80,7 +80,7 @@
                    ("1_3",     [221], minor_versions("1.3" , 7)),
                    ("1_4", range(222,246), minor_versions("1.4" , 5)),
                    ("1_5", range(246,277), minor_versions("1.5" , 2)),
-                   ("1_6", range(277,320), minor_versions("1.6" , 0))]
+                   ("1_6", range(277,321), minor_versions("1.6" , 0))]
 
 
 def formats_list():
Index: lib/lyx2lyx/lyx_1_6.py
===================================================================
--- lib/lyx2lyx/lyx_1_6.py	(revision 23801)
+++ lib/lyx2lyx/lyx_1_6.py	(working copy)
@@ -47,6 +47,155 @@
 
 ####################################################################
 
+def get_option(document, m, option, default):
+    l = document.body[m].find(option)
+    val = default
+    if l != -1:
+        val = document.body[m][l:].split('"')[1]
+    return val
+
+def remove_option(document, m, option):
+    l = document.body[m].find(option)
+    if l != -1:
+        val = document.body[m][l:].split('"')[1]
+        document.body[m] = document.body[m][:l-1] + document.body[m][l+len(option + '="' + val + '"'):]
+    return l
+
+def set_option(document, m, option, value):
+    l = document.body[m].find(option)
+    if l != -1:
+        oldval = document.body[m][l:].split('"')[1]
+        l = l + len(option + '="')
+        document.body[m] = document.body[m][:l] + value + document.body[m][l+len(oldval):]
+    else:
+        document.body[m] = document.body[m][:-1] + ' ' + option + '="' + value + '">'
+    return l
+
+def convert_tablines(document):
+    i = 0
+    while True:
+        i = find_token(document.body, "\\begin_inset Tabular", i)
+        if i == -1:
+            return
+        j = find_end_of_inset(document.body, i + 1)
+        if j == -1:
+            document.warning("Malformed LyX document: Could not find end of tabular.")
+            continue
+
+        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)
+            left = get_option(document, m, 'leftline', 'false')
+            right = get_option(document, m, 'rightline', 'false')
+            col_info.append([left, right])
+            remove_option(document, m, 'leftline')
+            remove_option(document, m, 'rightline')
+            m = m + 1
+
+        row_info = []
+        for k in range(nrows):
+            m = find_token(document.body, "<row", m)
+            top = get_option(document, m, 'topline', 'false')
+            bottom = get_option(document, m, 'bottomline', 'false')
+            row_info.append([top, bottom])
+            remove_option(document, m, 'topline')
+            remove_option(document, m, 'bottomline')
+            m = m + 1
+
+        m = i + 1
+        mc_info = []
+        for k in range(nrows*ncols):
+            m = find_token(document.body, "<cell", m)
+            mc_info.append(get_option(document, m, 'multicolumn', '0'))
+            m = m + 1
+        m = i + 1
+        for l in range(nrows):
+            for k in range(ncols):
+                m = find_token(document.body, '<cell', m)
+                if mc_info[l*ncols + k] == '0':
+                    r = set_option(document, m, 'topline', row_info[l][0])
+                    r = set_option(document, m, 'bottomline', row_info[l][1])
+                    r = set_option(document, m, 'leftline', col_info[k][0])
+                    r = set_option(document, m, 'rightline', col_info[k][1])
+                elif mc_info[l*ncols + k] == '1':
+                    s = k + 1
+                    while s < ncols and mc_info[l*ncols + s] == '2':
+                        s = s + 1
+                    if s < ncols and mc_info[l*ncols + s] != '1':
+                        r = set_option(document, m, 'rightline', col_info[k][1])
+                    if k > 0 and mc_info[l*ncols + k - 1] == '0':
+                        r = set_option(document, m, 'leftline', col_info[k][0])
+                m = m + 1
+        i = j + 1
+
+
+def revert_tablines(document):
+    i = 0
+    while True:
+        i = find_token(document.body, "\\begin_inset Tabular", i)
+        if i == -1:
+            return
+        j = find_end_of_inset(document.body, i + 1)
+        if j == -1:
+            document.warning("Malformed LyX document: Could not find end of tabular.")
+            continue
+
+        m = i + 1
+        nrows = int(document.body[i+1].split('"')[3])
+        ncols = int(document.body[i+1].split('"')[5])
+
+        lines = []
+        for k in range(nrows*ncols):
+            m = find_token(document.body, "<cell", m)
+            top = get_option(document, m, 'topline', 'false')
+            bottom = get_option(document, m, 'bottomline', 'false')
+            left = get_option(document, m, 'leftline', 'false')
+            right = get_option(document, m, 'rightline', 'false')
+            lines.append([top, bottom, left, right])
+            m = m + 1
+
+        m = i + 1
+        col_info = []
+        for k in range(ncols):
+            m = find_token(document.body, "<column", m)
+            left = 'true'
+            for l in range(nrows):
+                left = lines[k*ncols + k][2]
+                if left == 'false':
+                    break
+            set_option(document, m, 'leftline', left)
+            right = 'true'
+            for l in range(nrows):
+                right = lines[k*ncols + k][3]
+                if right == 'false':
+                    break
+            set_option(document, m, 'rightline', right)
+            m = m + 1
+
+        row_info = []
+        for k in range(nrows):
+            m = find_token(document.body, "<row", m)
+            top = 'true'
+            for l in range(ncols):
+                top = lines[k*ncols + l][0]
+                if top == 'false':
+                    break
+            set_option(document, m, 'topline', top)
+            bottom = 'true'
+            for l in range(ncols):
+                bottom = lines[k*ncols + l][1]
+                if bottom == 'false':
+                    break
+            set_option(document, m, 'bottomline', bottom)
+            m = m + 1
+
+        i = j + 1
+
+
 def fix_wrong_tables(document):
     i = 0
     while True:
@@ -1505,10 +1654,12 @@
            [316, [convert_subfig]],
            [317, []],
            [318, []],
-           [319, [convert_spaceinset, convert_hfill]]
+           [319, [convert_spaceinset, convert_hfill]],
+           [320, [convert_tablines]]
           ]
 
-revert =  [[318, [revert_spaceinset, revert_hfills, revert_hspace]],
+revert =  [[319, [revert_tablines]],
+           [318, [revert_spaceinset, revert_hfills, revert_hspace]],
            [317, [remove_extra_embedded_files]],
            [316, [revert_wrapplacement]],
            [315, [revert_subfig]],
Index: src/Buffer.cpp
===================================================================
--- src/Buffer.cpp	(revision 23801)
+++ src/Buffer.cpp	(working copy)
@@ -116,7 +116,7 @@
 
 namespace {
 
-int const LYX_FORMAT = 319;
+int const LYX_FORMAT = 320;
 
 typedef map<string, bool> DepClean;
 typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
Index: src/frontends/qt4/GuiTabular.cpp
===================================================================
--- src/frontends/qt4/GuiTabular.cpp	(revision 23801)
+++ src/frontends/qt4/GuiTabular.cpp	(working copy)
@@ -283,28 +283,28 @@
 
 void GuiTabular::leftBorder_changed()
 {
-	toggleLeftLine();
+	set(Tabular::TOGGLE_LINE_LEFT);
 	changed();
 }
 
 
 void GuiTabular::rightBorder_changed()
 {
-	toggleRightLine();
+	set(Tabular::TOGGLE_LINE_RIGHT);
 	changed();
 }
 
 
 void GuiTabular::topBorder_changed()
 {
-	toggleTopLine();
+	set(Tabular::TOGGLE_LINE_TOP);
 	changed();
 }
 
 
 void GuiTabular::bottomBorder_changed()
 {
-	toggleBottomLine();
+	set(Tabular::TOGGLE_LINE_BOTTOM);
 	changed();
 }
 
@@ -554,39 +554,10 @@
 void GuiTabular::update_borders()
 {
 	Tabular::idx_type const cell = getActiveCell();
-	bool const isMulticolumnCell = tabular_.isMultiColumn(cell);
-
-	if (!isMulticolumnCell) {
-		borders->setLeftEnabled(true);
-		borders->setRightEnabled(true);
-		borders->setTop(tabular_.topLine(cell, true));
-		borders->setBottom(tabular_.bottomLine(cell, true));
-		borders->setLeft(tabular_.leftLine(cell, true));
-		borders->setRight(tabular_.rightLine(cell, true));
-		// repaint the setborder widget
-		borders->update();
-		return;
-	}
-
 	borders->setTop(tabular_.topLine(cell));
 	borders->setBottom(tabular_.bottomLine(cell));
-	// pay attention to left/right lines: they are only allowed
-	// to set if we are in first/last cell of row or if the left/right
-	// cell is also a multicolumn.
-	if (tabular_.isFirstCellInRow(cell) || tabular_.isMultiColumn(cell - 1)) {
-		borders->setLeftEnabled(true);
-		borders->setLeft(tabular_.leftLine(cell));
-	} else {
-		borders->setLeft(false);
-		borders->setLeftEnabled(false);
-	}
-	if (tabular_.isLastCellInRow(cell) || tabular_.isMultiColumn(cell + 1)) {
-		borders->setRightEnabled(true);
-		borders->setRight(tabular_.rightLine(cell));
-	} else {
-		borders->setRight(false);
-		borders->setRightEnabled(false);
-	}
+	borders->setLeft(tabular_.leftLine(cell));
+	borders->setRight(tabular_.rightLine(cell));
 	// repaint the setborder widget
 	borders->update();
 }
@@ -988,42 +959,6 @@
 }
 
 
-void GuiTabular::toggleTopLine()
-{
-	if (tabular_.isMultiColumn(getActiveCell()))
-		set(Tabular::M_TOGGLE_LINE_TOP);
-	else
-		set(Tabular::TOGGLE_LINE_TOP);
-}
-
-
-void GuiTabular::toggleBottomLine()
-{
-	if (tabular_.isMultiColumn(getActiveCell()))
-		set(Tabular::M_TOGGLE_LINE_BOTTOM);
-	else
-		set(Tabular::TOGGLE_LINE_BOTTOM);
-}
-
-
-void GuiTabular::toggleLeftLine()
-{
-	if (tabular_.isMultiColumn(getActiveCell()))
-		set(Tabular::M_TOGGLE_LINE_LEFT);
-	else
-		set(Tabular::TOGGLE_LINE_LEFT);
-}
-
-
-void GuiTabular::toggleRightLine()
-{
-	if (tabular_.isMultiColumn(getActiveCell()))
-		set(Tabular::M_TOGGLE_LINE_RIGHT);
-	else
-		set(Tabular::TOGGLE_LINE_RIGHT);
-}
-
-
 void GuiTabular::setSpecial(string const & special)
 {
 	if (tabular_.isMultiColumn(getActiveCell()))
Index: src/frontends/qt4/GuiTabular.h
===================================================================
--- src/frontends/qt4/GuiTabular.h	(revision 23801)
+++ src/frontends/qt4/GuiTabular.h	(working copy)
@@ -95,12 +95,6 @@
 	/// set a parameter
 	void set(Tabular::Feature, std::string const & arg = std::string());
 
-	/// borders
-	void toggleTopLine();
-	void toggleBottomLine();
-	void toggleLeftLine();
-	void toggleRightLine();
-
 	void setSpecial(std::string const & special);
 
 	void setWidth(std::string const & width);
Index: src/insets/InsetTabular.cpp
===================================================================
--- src/insets/InsetTabular.cpp	(revision 23801)
+++ src/insets/InsetTabular.cpp	(working copy)
@@ -86,10 +86,10 @@
 
 namespace {
 
-int const ADD_TO_HEIGHT = 2;
-int const ADD_TO_TABULAR_WIDTH = 2;
-int const default_line_space = 10;
-int const WIDTH_OF_LINE = 5;
+int const ADD_TO_HEIGHT = 2; // in cell
+int const ADD_TO_TABULAR_WIDTH = 6; // horiz space before and after the table
+int const default_line_space = 10; // ?
+int const WIDTH_OF_LINE = 5; // space between double lines
 
 
 ///
@@ -121,10 +121,6 @@
 	{ Tabular::VALIGN_TOP, "valign-top" },
 	{ Tabular::VALIGN_BOTTOM, "valign-bottom" },
 	{ Tabular::VALIGN_MIDDLE, "valign-middle" },
-	{ Tabular::M_TOGGLE_LINE_TOP, "m-toggle-line-top" },
-	{ Tabular::M_TOGGLE_LINE_BOTTOM, "m-toggle-line-bottom" },
-	{ Tabular::M_TOGGLE_LINE_LEFT, "m-toggle-line-left" },
-	{ Tabular::M_TOGGLE_LINE_RIGHT, "m-toggle-line-right" },
 	{ Tabular::M_ALIGN_LEFT, "m-align-left" },
 	{ Tabular::M_ALIGN_RIGHT, "m-align-right" },
 	{ Tabular::M_ALIGN_CENTER, "m-align-center" },
@@ -479,9 +475,9 @@
 	  multicolumn(Tabular::CELL_NORMAL),
 	  alignment(LYX_ALIGN_CENTER),
 	  valignment(LYX_VALIGN_TOP),
-	  top_line(true),
+	  top_line(false),
 	  bottom_line(false),
-	  left_line(true),
+	  left_line(false),
 	  right_line(false),
 	  usebox(BOX_NONE),
 	  rotate(false),
@@ -539,8 +535,6 @@
 Tabular::RowData::RowData()
 	: ascent(0),
 	  descent(0),
-	  top_line(true),
-	  bottom_line(false),
 	  top_space_default(false),
 	  bottom_space_default(false),
 	  interline_space_default(false),
@@ -555,8 +549,6 @@
 Tabular::ColumnData::ColumnData()
 	: alignment(LYX_ALIGN_CENTER),
 	  valignment(LYX_VALIGN_TOP),
-	  left_line(true),
-	  right_line(false),
 	  width(0)
 {
 }
@@ -593,29 +585,26 @@
 	column_info.reserve(10);
 	cell_info.reserve(100);
 	fixCellNums();
-	for (row_type i = 0; i < rows_arg; ++i)
-		cell_info[i].back().right_line = true;
-	row_info.back().bottom_line = true;
-	row_info.front().bottom_line = true;
-	column_info.back().right_line = true;
 	is_long_tabular = false;
 	rotate = false;
 	use_booktabs = false;
+	// set silly default lines
+	for (row_type i = 0; i < rowCount(); ++i)
+		for (col_type j = 0; j < columnCount(); ++j) {
+			cell_info[i][j].top_line = true;
+			cell_info[i][j].left_line = true;
+			cell_info[i][j].bottom_line = i == 0 || i == rowCount() - 1;
+			cell_info[i][j].right_line = j == columnCount() - 1;
+		}
 }
 
 
 void Tabular::fixCellNums()
 {
 	idx_type cellno = 0;
-	for (row_type i = 0; i < rowCount(); ++i) {
-		for (col_type j = 0; j < columnCount(); ++j) {
-			// When debugging it can be nice to set
-			// this to true.
-			cell_info[i][j].inset->setDrawFrame(false);
+	for (row_type i = 0; i < rowCount(); ++i)
+		for (col_type j = 0; j < columnCount(); ++j)
 			cell_info[i][j].cellno = cellno++;
-		}
-		cell_info[i].back().right_line = true;
-	}
 
 	updateIndexes();
 }
@@ -749,7 +738,7 @@
 	for (row_type row = 0; row < rowCount(); ++row) {
 		for (col_type column = 0; column < columnCount(); ++column) {
 			if (cell_info[row][column].multicolumn
-				!= Tabular::CELL_PART_OF_MULTICOLUMN)
+				!= CELL_PART_OF_MULTICOLUMN)
 				++numberofcells;
 			BOOST_ASSERT(numberofcells != 0);
 			cell_info[row][column].cellno =
@@ -807,78 +796,51 @@
 }
 
 
-bool Tabular::topLine(idx_type const cell, bool const wholerow) const
+bool Tabular::topLine(idx_type const cell) const
 {
-	if (!wholerow && isMultiColumn(cell) &&
-	    !(use_booktabs && cellRow(cell) == 0))
-		return cellinfo_of_cell(cell).top_line;
-	return row_info[cellRow(cell)].top_line;
+	return cellinfo_of_cell(cell).top_line;
 }
 
 
-bool Tabular::bottomLine(idx_type const cell, bool wholerow) const
+bool Tabular::bottomLine(idx_type const cell) const
 {
-	if (!wholerow && isMultiColumn(cell) &&
-	    !(use_booktabs && isLastRow(cell)))
-		return cellinfo_of_cell(cell).bottom_line;
-	return row_info[cellRow(cell)].bottom_line;
+	return cellinfo_of_cell(cell).bottom_line;
 }
 
 
-bool Tabular::leftLine(idx_type cell, bool wholecolumn) const
+bool Tabular::leftLine(idx_type cell) const
 {
 	if (use_booktabs)
 		return false;
-	if (!wholecolumn && isMultiColumn(cell) &&
-		(isFirstCellInRow(cell) || isMultiColumn(cell-1)))
-		return cellinfo_of_cell(cell).left_line;
-	return column_info[cellColumn(cell)].left_line;
+	return cellinfo_of_cell(cell).left_line;
 }
 
 
-bool Tabular::rightLine(idx_type cell, bool wholecolumn) const
+bool Tabular::rightLine(idx_type cell) const
 {
 	if (use_booktabs)
 		return false;
-	if (!wholecolumn && isMultiColumn(cell) &&
-		(isLastCellInRow(cell) || isMultiColumn(cell + 1)))
-		return cellinfo_of_cell(cell).right_line;
-	return column_info[cellRightColumn(cell)].right_line;
+	return cellinfo_of_cell(cell).right_line;
 }
 
 
 bool Tabular::topAlreadyDrawn(idx_type cell) const
 {
 	row_type row = cellRow(cell);
-	if (row > 0 && !getAdditionalHeight(row)) {
-		col_type column = cellColumn(cell);
-		--row;
-		while (column
-			   && cell_info[row][column].multicolumn
-			   == Tabular::CELL_PART_OF_MULTICOLUMN)
-			--column;
-		if (cell_info[row][column].multicolumn == Tabular::CELL_NORMAL)
-			return row_info[row].bottom_line;
-		else
-			return cell_info[row][column].bottom_line;
-	}
-	return false;
+	if (row == 0)
+		return false;
+	idx_type i = cellIndex(row - 1, cellColumn(cell));
+	return !rowBottomLine(row - 1) && bottomLine(i);
 }
 
 
 bool Tabular::leftAlreadyDrawn(idx_type cell) const
 {
-	col_type column = cellColumn(cell);
-	if (column > 0) {
-		row_type row = cellRow(cell);
-		while (--column &&
-			   (cell_info[row][column].multicolumn ==
-				Tabular::CELL_PART_OF_MULTICOLUMN)) { }
-		if (getAdditionalWidth(cell_info[row][column].cellno))
-			return false;
-		return rightLine(cell_info[row][column].cellno);
-	}
-	return false;
+	col_type col = cellColumn(cell);
+	if (col == 0)
+		return false;
+	idx_type i = cellIndex(cellRow(cell), col - 1);
+	return !columnRightLine(col - 1) && rightLine(i);
 }
 
 
@@ -893,31 +855,10 @@
 	if (!row || row >= rowCount())
 		return 0;
 
-	bool top = true;
-	bool bottom = true;
-
-	for (col_type column = 0; column < columnCount() && bottom; ++column) {
-		switch (cell_info[row - 1][column].multicolumn) {
-		case Tabular::CELL_BEGIN_OF_MULTICOLUMN:
-			bottom = cell_info[row - 1][column].bottom_line;
-			break;
-		case Tabular::CELL_NORMAL:
-			bottom = row_info[row - 1].bottom_line;
-		}
-	}
-	for (col_type column = 0; column < columnCount() && top; ++column) {
-		switch (cell_info[row][column].multicolumn) {
-		case Tabular::CELL_BEGIN_OF_MULTICOLUMN:
-			top = cell_info[row][column].top_line;
-			break;
-		case Tabular::CELL_NORMAL:
-			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());
-	if (top && bottom)
+	if (rowTopLine(row) && rowBottomLine(row - 1))
 		return interline_space + WIDTH_OF_LINE;
 	return interline_space;
 }
@@ -927,13 +868,11 @@
 {
 	// internally already set in setCellWidth
 	// used to get it back in text.cpp
-	col_type const col = cellRightColumn(cell);
-	row_type const row = cellRow(cell);
-	if (col < columnCount() - 1 && rightLine(cell) &&
-		leftLine(cell_info[row][col+1].cellno)) // column_info[col+1].left_line)
-	{
+	col_type c = cellColumn(cell);
+	if (c < columnCount() - 1 
+		&& columnRightLine(c) && columnLeftLine(c + 1)
+		&& cellinfo_of_cell(cell).multicolumn == CELL_NORMAL)
 		return WIDTH_OF_LINE;
-	}
 	return 0;
 }
 
@@ -1022,15 +961,13 @@
 void Tabular::setCellWidth(idx_type cell, int new_width)
 {
 	row_type const row = cellRow(cell);
-	col_type const column1 = cellColumn(cell);
+	col_type const col = cellColumn(cell);
 	bool tmp = false;
 	int width = 0;
 	int add_width = 0;
 
-	if (rightLine(cell_info[row][column1].cellno, true) &&
-		column1 < columnCount() - 1 &&
-		leftLine(cell_info[row][column1+1].cellno, true))
-	{
+	if (col < columnCount() - 1 && columnRightLine(col) &&
+		columnLeftLine(col + 1)) {
 		add_width = WIDTH_OF_LINE;
 	}
 
@@ -1041,10 +978,10 @@
 		tmp = setWidthOfMulticolCell(cell, new_width);
 	} else {
 		width = new_width + 2 * WIDTH_OF_LINE + add_width;
-		cell_info[row][column1].width = width;
-		tmp = calculate_width_of_column_NMC(column1);
+		cell_info[row][col].width = width;
+		tmp = calculate_width_of_column_NMC(col);
 		if (tmp)
-			recalculateMulticolumnsOfColumn(column1);
+			recalculateMulticolumnsOfColumn(col);
 	}
 	if (tmp) {
 		for (col_type i = 0; i < columnCount(); ++i)
@@ -1160,43 +1097,77 @@
 }
 
 
-void Tabular::setTopLine(idx_type cell, bool line, bool wholerow)
+void Tabular::setTopLine(idx_type i, bool line)
 {
-	row_type const row = cellRow(cell);
-	if (wholerow || !isMultiColumn(cell))
-		row_info[row].top_line = line;
-	else
-		cellinfo_of_cell(cell).top_line = line;
+	cellinfo_of_cell(i).top_line = line;
 }
 
 
-void Tabular::setBottomLine(idx_type cell, bool line, bool wholerow)
+void Tabular::setBottomLine(idx_type i, bool line)
 {
-	if (wholerow || !isMultiColumn(cell))
-		row_info[cellRow(cell)].bottom_line = line;
-	else
-		cellinfo_of_cell(cell).bottom_line = line;
+	cellinfo_of_cell(i).bottom_line = line;
 }
 
 
-void Tabular::setLeftLine(idx_type cell, bool line, bool wholecolumn)
+void Tabular::setLeftLine(idx_type cell, bool line)
 {
-	if (wholecolumn || !isMultiColumn(cell))
-		column_info[cellColumn(cell)].left_line = line;
-	else
-		cellinfo_of_cell(cell).left_line = line;
+	cellinfo_of_cell(cell).left_line = line;
 }
 
 
-void Tabular::setRightLine(idx_type cell, bool line, bool wholecolumn)
+void Tabular::setRightLine(idx_type cell, bool line)
 {
-	if (wholecolumn || !isMultiColumn(cell))
-		column_info[cellRightColumn(cell)].right_line = line;
-	else
-		cellinfo_of_cell(cell).right_line = line;
+	cellinfo_of_cell(cell).right_line = line;
 }
 
+bool Tabular::rowTopLine(row_type r) const
+{
+	idx_type i0 = getFirstCellInRow(r);
+	idx_type i1 = getLastCellInRow(r);
+	bool all_rows_set = true;
+	for (idx_type j = i0; all_rows_set && j <= i1; ++j)
+		all_rows_set = cellinfo_of_cell(j).top_line;
+	return all_rows_set;
+}
 
+
+bool Tabular::rowBottomLine(row_type r) const
+{
+	idx_type i0 = getFirstCellInRow(r);
+	idx_type i1 = getLastCellInRow(r);
+	bool all_rows_set = true;
+	for (idx_type j = i0; all_rows_set && j <= i1; ++j)
+		all_rows_set = cellinfo_of_cell(j).bottom_line;
+	return all_rows_set;
+}
+
+
+bool Tabular::columnLeftLine(col_type c) const
+{
+	bool all_cols_set = true;
+	row_type nrows = rowCount();
+	for (row_type r = 0; all_cols_set && r < nrows; ++r) {
+		idx_type i = cellIndex(r, c);
+		if (columnSpan(i) == 1)
+			all_cols_set = cellinfo_of_cell(i).left_line;
+	}
+	return all_cols_set;
+}
+
+
+bool Tabular::columnRightLine(col_type c) const
+{
+	bool all_cols_set = true;
+	row_type nrows = rowCount();
+	for (row_type r = 0; all_cols_set && r < nrows; ++r) {
+		idx_type i = cellIndex(r, c);
+		if (c == cellColumn(i) + columnSpan(i) - 1)
+			all_cols_set = cellinfo_of_cell(i).right_line;
+	}
+	return all_cols_set;
+}
+
+
 LyXAlignment Tabular::getAlignment(idx_type cell, bool onlycolumn) const
 {
 	if (!onlycolumn && isMultiColumn(cell))
@@ -1365,7 +1336,7 @@
 	row_type const row = cellRow(cell);
 	col_type column = cellColumn(cell);
 	while (column < columnCount() - 1 &&
-		   cell_info[row][column + 1].multicolumn == Tabular::CELL_PART_OF_MULTICOLUMN)
+		   cell_info[row][column + 1].multicolumn == CELL_PART_OF_MULTICOLUMN)
 		++column;
 	return column;
 }
@@ -1399,17 +1370,13 @@
 		os << "<column"
 		   << write_attribute("alignment", column_info[j].alignment)
 		   << write_attribute("valignment", column_info[j].valignment)
-		   << write_attribute("leftline", column_info[j].left_line)
-		   << write_attribute("rightline", column_info[j].right_line)
 		   << write_attribute("width", column_info[j].p_width.asString())
 		   << write_attribute("special", column_info[j].align_special)
 		   << ">\n";
 	}
 	for (row_type i = 0; i < rowCount(); ++i) {
-		os << "<row"
-		   << write_attribute("topline", row_info[i].top_line)
-		   << write_attribute("bottomline", row_info[i].bottom_line);
 		static const string def("default");
+		os << "<row";
 		if (row_info[i].top_space_default)
 			os << write_attribute("topspace", def);
 		else
@@ -1505,8 +1472,6 @@
 		}
 		getTokenValue(line, "alignment", column_info[j].alignment);
 		getTokenValue(line, "valignment", column_info[j].valignment);
-		getTokenValue(line, "leftline", column_info[j].left_line);
-		getTokenValue(line, "rightline", column_info[j].right_line);
 		getTokenValue(line, "width", column_info[j].p_width);
 		getTokenValue(line, "special", column_info[j].align_special);
 	}
@@ -1518,8 +1483,6 @@
 			       << line << ')' << endl;
 			return;
 		}
-		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,
@@ -1576,14 +1539,14 @@
 
 bool Tabular::isMultiColumn(idx_type cell) const
 {
-	return cellinfo_of_cell(cell).multicolumn != Tabular::CELL_NORMAL;
+	return cellinfo_of_cell(cell).multicolumn != CELL_NORMAL;
 }
 
 
 bool Tabular::isMultiColumnReal(idx_type cell) const
 {
 	return cellColumn(cell) != cellRightColumn(cell) &&
-			cellinfo_of_cell(cell).multicolumn != Tabular::CELL_NORMAL;
+			cellinfo_of_cell(cell).multicolumn != CELL_NORMAL;
 }
 
 
@@ -1598,21 +1561,18 @@
 	CellData & cs = cellinfo_of_cell(cell);
 	cs.multicolumn = CELL_BEGIN_OF_MULTICOLUMN;
 	cs.alignment = column_info[cellColumn(cell)].alignment;
-	cs.top_line = row_info[cellRow(cell)].top_line;
-	cs.bottom_line = row_info[cellRow(cell)].bottom_line;
-	cs.left_line = column_info[cellColumn(cell)].left_line;
-	cs.right_line = column_info[cellColumn(cell+number-1)].right_line;
 	for (idx_type i = 1; i < number; ++i) {
 		CellData & cs1 = cellinfo_of_cell(cell + i);
 		cs1.multicolumn = CELL_PART_OF_MULTICOLUMN;
 		cs.inset->appendParagraphs(cs1.inset->paragraphs());
 		cs1.inset->clear();
 	}
+	setRightLine(cell, rightLine(cell + number - 1));
 	updateIndexes();
 }
 
 
-Tabular::idx_type Tabular::cells_in_multicolumn(idx_type cell) const
+Tabular::idx_type Tabular::columnSpan(idx_type cell) const
 {
 	row_type const row = cellRow(cell);
 	col_type column = cellColumn(cell);
@@ -2031,18 +1991,20 @@
 		os << "\\begin{sideways}\n";
 		++ret;
 	}
-	if (isMultiColumn(cell)) {
-		os << "\\multicolumn{" << cells_in_multicolumn(cell) << "}{";
-		if (leftLine(cell) &&
-			(isFirstCellInRow(cell) ||
-			 (!isMultiColumn(cell - 1) && !leftLine(cell, true) &&
-			  !rightLine(cell - 1, true))))
+	Tabular::VAlignment valign =  getVAlignment(cell, !isMultiColumn(cell));
+	LyXAlignment align = getAlignment(cell, !isMultiColumn(cell));
+	col_type c = cellColumn(cell);
+	if (isMultiColumn(cell)
+		|| (leftLine(cell) && !columnLeftLine(c))
+		|| (rightLine(cell) && !columnRightLine(c))) {
+		os << "\\multicolumn{" << columnSpan(cell) << "}{";
+		if (leftLine(cell))
 			os << '|';
 		if (!cellinfo_of_cell(cell).align_special.empty()) {
 			os << cellinfo_of_cell(cell).align_special;
 		} else {
 			if (!getPWidth(cell).zero()) {
-				switch (getVAlignment(cell)) {
+				switch (valign) {
 				case LYX_VALIGN_TOP:
 					os << 'p';
 					break;
@@ -2057,7 +2019,7 @@
 				   << from_ascii(getPWidth(cell).asLatexString())
 				   << '}';
 			} else {
-				switch (getAlignment(cell)) {
+				switch (align) {
 				case LYX_ALIGN_LEFT:
 					os << 'l';
 					break;
@@ -2072,14 +2034,11 @@
 		} // end if else !cellinfo_of_cell
 		if (rightLine(cell))
 			os << '|';
-		if (((cell + 1) < cellCount()) && !isFirstCellInRow(cell+1) &&
-			leftLine(cell+1))
-			os << '|';
 		os << "}{";
 		}
 	if (getUsebox(cell) == BOX_PARBOX) {
 		os << "\\parbox[";
-		switch (getVAlignment(cell)) {
+		switch (valign) {
 		case LYX_VALIGN_TOP:
 			os << 't';
 			break;
@@ -2094,7 +2053,7 @@
 		   << "}{";
 	} else if (getUsebox(cell) == BOX_MINIPAGE) {
 		os << "\\begin{minipage}[";
-		switch (getVAlignment(cell)) {
+		switch (valign) {
 		case LYX_VALIGN_TOP:
 			os << 't';
 			break;
@@ -2124,7 +2083,10 @@
 		os << "%\n\\end{minipage}";
 		ret += 2;
 	}
-	if (isMultiColumn(cell)) {
+	col_type c = cellColumn(cell);
+	if (isMultiColumn(cell)
+		|| (leftLine(cell) && !columnLeftLine(c))
+		|| (rightLine(cell) && !columnRightLine(c))) {
 		os << '}';
 	}
 	if (getRotateCell(cell)) {
@@ -2343,8 +2305,9 @@
 		os << "\\begin{longtable}{";
 	else
 		os << "\\begin{tabular}{";
+
 	for (col_type i = 0; i < columnCount(); ++i) {
-		if (!use_booktabs && column_info[i].left_line)
+		if (!use_booktabs && columnLeftLine(i))
 			os << '|';
 		if (!column_info[i].align_special.empty()) {
 			os << column_info[i].align_special;
@@ -2395,7 +2358,7 @@
 				}
 			} // end if else !column_info[i].p_width
 		} // end if else !column_info[i].align_special
-		if (!use_booktabs && column_info[i].right_line)
+		if (!use_booktabs && columnRightLine(i))
 			os << '|';
 	}
 	os << "}\n";
@@ -2473,7 +2436,7 @@
 
 		if (isMultiColumn(cell)) {
 			os << " namest=\"col" << j << "\" ";
-			os << "nameend=\"col" << j + cells_in_multicolumn(cell) - 1<< '"';
+			os << "nameend=\"col" << j + columnSpan(cell) - 1<< '"';
 		}
 
 		os << '>';
@@ -2747,7 +2710,7 @@
 				odocstringstream sstr;
 				getCellInset(cell)->plaintext(sstr, runparams);
 				int len = int(sstr.str().length());
-				idx_type const n = cells_in_multicolumn(cell);
+				idx_type const n = columnSpan(cell);
 				for (col_type k = j; len > 0 && k < j + n - 1; ++k)
 					len -= clen[k];
 				if (len > int(clen[j + n - 1]))
@@ -2922,6 +2885,34 @@
 }
 
 
+int InsetTabular::rowFromY(Cursor & cur, int y) const
+{
+	// top y coordinate of tabular
+	int h = yo(cur.bv()) - tabular.rowAscent(0);
+	size_t nrows = tabular.rowCount();
+	row_type r = 0;
+	for (;r < nrows && y > h; ++r) {
+		h += tabular.rowAscent(r);
+		h += tabular.rowDescent(r);
+		h += tabular.getAdditionalHeight(r);
+	}
+	return r - 1;
+}
+
+
+int InsetTabular::columnFromX(Cursor & cur, int x) const
+{
+	// left x coordinate of tabular
+	int w = xo(cur.bv()) + ADD_TO_TABULAR_WIDTH;
+	size_t ncols = tabular.columnCount();
+	col_type c = 0;
+	for (;c < ncols && x > w; ++c) {
+		w += tabular.columnWidth(c);
+	}
+	return c - 1;
+}
+
+
 void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
 {
 	//lyxerr << "InsetTabular::metrics: " << mi.base.bv << " width: " <<
@@ -2943,7 +2934,7 @@
 			MetricsInfo m = mi;
 			Length p_width;
 			if (tabular.cell_info[i][j].multicolumn ==
-			    Tabular::CELL_BEGIN_OF_MULTICOLUMN)
+				Tabular::CELL_BEGIN_OF_MULTICOLUMN)
 				p_width = tabular.cellinfo_of_cell(cell).p_width;
 			else
 				p_width = tabular.column_info[j].p_width;
@@ -3193,9 +3184,36 @@
 
 	switch (cmd.action) {
 
-	case LFUN_MOUSE_PRESS:
+	case LFUN_MOUSE_PRESS: {
 		//lyxerr << "# InsetTabular::MousePress\n" << cur.bv().cursor() << endl;
 
+		// select row
+		if (cmd.x < xo(cur.bv()) + ADD_TO_TABULAR_WIDTH
+			|| cmd.x > xo(cur.bv()) + tabular.width()) {
+			row_type r = rowFromY(cur, cmd.y);
+			cur.idx() = tabular.getFirstCellInRow(r);
+			cur.pos() = 0;
+			cur.resetAnchor();
+			cur.idx() = tabular.getLastCellInRow(r);
+			cur.pos() = cur.lastpos();
+			cur.selection() = true;
+			bvcur = cur; 
+			break;
+		}
+		// select column
+		int const y0 = yo(cur.bv()) - tabular.rowAscent(0);
+		if (cmd.y < y0 + ADD_TO_TABULAR_WIDTH 
+			|| cmd.y > y0 + tabular.height()) {
+			col_type c = columnFromX(cur, cmd.x);
+			cur.idx() = tabular.cellIndex(0, c);
+			cur.pos() = 0;
+			cur.resetAnchor();
+			cur.idx() = tabular.cellIndex(tabular.rowCount() - 1, c);
+			cur.pos() = cur.lastpos();
+			cur.selection() = true;
+			bvcur = cur; 
+			break;
+		}
 		// do not reset cursor/selection if we have selected
 		// some cells (bug 2715).
 		if (cmd.button() == mouse_button::button3
@@ -3206,20 +3224,41 @@
 			// Let InsetText do it
 			cell(cur.idx())->dispatch(cur, cmd);
 		break;
+	}
 	case LFUN_MOUSE_MOTION:
 		//lyxerr << "# InsetTabular::MouseMotion\n" << bvcur << endl;
 		if (cmd.button() == mouse_button::button1) {
 			// only accept motions to places not deeper nested than the real anchor
-			if (bvcur.anchor_.hasPart(cur)) {
-				// only update if selection changes
-				if (bvcur.idx() == cur.idx() &&
-					!(bvcur.anchor_.idx() == cur.idx() && bvcur.pos() != cur.pos()))
-					cur.noUpdate();
-				setCursorFromCoordinates(cur, cmd.x, cmd.y);
+			if (!bvcur.anchor_.hasPart(cur)) {
+				cur.undispatched();
+				break;
+			}
+			// select (additional) row
+			if (cmd.x < xo(cur.bv()) + ADD_TO_TABULAR_WIDTH
+				|| cmd.x > xo(cur.bv()) + tabular.width()) {
+				row_type r = rowFromY(cur, cmd.y);
+				cur.idx() = tabular.getLastCellInRow(r);
 				bvcur.setCursor(cur);
 				bvcur.selection() = true;
-			} else
-				cur.undispatched();
+				break;
+			}
+			// select (additional) column
+			int const y0 = yo(cur.bv()) - tabular.rowAscent(0);
+			if (cmd.y < y0 + ADD_TO_TABULAR_WIDTH 
+				|| cmd.y > y0 + tabular.height()) {
+				col_type c = columnFromX(cur, cmd.x);
+				cur.idx() = tabular.cellIndex(tabular.rowCount() - 1, c);
+				bvcur.setCursor(cur);
+				bvcur.selection() = true;
+				break;
+			}
+			// only update if selection changes
+			if (bvcur.idx() == cur.idx() &&
+				!(bvcur.anchor_.idx() == cur.idx() && bvcur.pos() != cur.pos()))
+				cur.noUpdate();
+			setCursorFromCoordinates(cur, cmd.x, cmd.y);
+			bvcur.setCursor(cur);
+			bvcur.selection() = true;
 		}
 		break;
 
@@ -3238,7 +3277,6 @@
 		moveNextCell(cur);
 		cur.selection() = false;
 		break;
-
 	case LFUN_CHAR_FORWARD_SELECT:
 	case LFUN_CHAR_FORWARD:
 		cell(cur.idx())->dispatch(cur, cmd);
@@ -3576,28 +3614,20 @@
 			status.setOnOff(tabular.isMultiColumn(cur.idx()));
 			break;
 
-		case Tabular::M_TOGGLE_LINE_TOP:
-			flag = false;
 		case Tabular::TOGGLE_LINE_TOP:
-			status.setOnOff(tabular.topLine(cur.idx(), flag));
+			status.setOnOff(tabular.topLine(cur.idx()));
 			break;
 
-		case Tabular::M_TOGGLE_LINE_BOTTOM:
-			flag = false;
 		case Tabular::TOGGLE_LINE_BOTTOM:
-			status.setOnOff(tabular.bottomLine(cur.idx(), flag));
+			status.setOnOff(tabular.bottomLine(cur.idx()));
 			break;
 
-		case Tabular::M_TOGGLE_LINE_LEFT:
-			flag = false;
 		case Tabular::TOGGLE_LINE_LEFT:
-			status.setOnOff(tabular.leftLine(cur.idx(), flag));
+			status.setOnOff(tabular.leftLine(cur.idx()));
 			break;
 
-		case Tabular::M_TOGGLE_LINE_RIGHT:
-			flag = false;
 		case Tabular::TOGGLE_LINE_RIGHT:
-			status.setOnOff(tabular.rightLine(cur.idx(), flag));
+			status.setOnOff(tabular.rightLine(cur.idx()));
 			break;
 
 		case Tabular::M_ALIGN_LEFT:
@@ -4218,51 +4248,35 @@
 		cur.idx() = tabular.cellIndex(row, column);
 		break;
 
-	case Tabular::M_TOGGLE_LINE_TOP:
-		flag = false;
 	case Tabular::TOGGLE_LINE_TOP: {
-		bool lineSet = !tabular.topLine(cur.idx(), flag);
+		bool lineSet = !tabular.topLine(cur.idx());
 		for (row_type i = sel_row_start; i <= sel_row_end; ++i)
 			for (col_type j = sel_col_start; j <= sel_col_end; ++j)
-				tabular.setTopLine(
-					tabular.cellIndex(i, j),
-					lineSet, flag);
+				tabular.setTopLine(tabular.cellIndex(i, j), lineSet);
 		break;
 	}
 
-	case Tabular::M_TOGGLE_LINE_BOTTOM:
-		flag = false;
 	case Tabular::TOGGLE_LINE_BOTTOM: {
-		bool lineSet = !tabular.bottomLine(cur.idx(), flag);
+		bool lineSet = !tabular.bottomLine(cur.idx());
 		for (row_type i = sel_row_start; i <= sel_row_end; ++i)
 			for (col_type j = sel_col_start; j <= sel_col_end; ++j)
-				tabular.setBottomLine(
-					tabular.cellIndex(i, j),
-					lineSet,
-					flag);
+				tabular.setBottomLine(tabular.cellIndex(i, j), lineSet);
 		break;
 	}
 
-	case Tabular::M_TOGGLE_LINE_LEFT:
-		flag = false;
 	case Tabular::TOGGLE_LINE_LEFT: {
-		bool lineSet = !tabular.leftLine(cur.idx(), flag);
+		bool lineSet = !tabular.leftLine(cur.idx());
 		for (row_type i = sel_row_start; i <= sel_row_end; ++i)
 			for (col_type j = sel_col_start; j <= sel_col_end; ++j)
-				tabular.setLeftLine(
-					tabular.cellIndex(i,j),
-					lineSet,
-					flag);
+				tabular.setLeftLine(tabular.cellIndex(i, j), lineSet);
 		break;
 	}
 
-	case Tabular::M_TOGGLE_LINE_RIGHT:
-		flag = false;
 	case Tabular::TOGGLE_LINE_RIGHT: {
-		bool lineSet = !tabular.rightLine(cur.idx(), flag);
+		bool lineSet = !tabular.rightLine(cur.idx());
 		for (row_type i = sel_row_start; i <= sel_row_end; ++i)
 			for (col_type j = sel_col_start; j <= sel_col_end; ++j)
-				tabular.setRightLine(tabular.cellIndex(i,j), lineSet, flag);
+				tabular.setRightLine(tabular.cellIndex(i, j), lineSet);
 		break;
 	}
 
@@ -4520,10 +4534,6 @@
 	while (paste_tabular->rowCount() > rows)
 		paste_tabular->deleteRow(rows);
 
-	paste_tabular->setTopLine(0, true, true);
-	paste_tabular->setBottomLine(paste_tabular->getFirstCellInRow(rows - 1),
-				     true, true);
-
 	for (col_type i = 0; i < cs; ++i)
 		paste_tabular->deleteColumn(0);
 
@@ -4531,10 +4541,6 @@
 	while (paste_tabular->columnCount() > columns)
 		paste_tabular->deleteColumn(columns);
 
-	paste_tabular->setLeftLine(0, true, true);
-	paste_tabular->setRightLine(paste_tabular->getLastCellInRow(0),
-				    true, true);
-
 	odocstringstream os;
 	OutputParams const runparams(0);
 	paste_tabular->plaintext(os, runparams, 0, true, '\t');
Index: src/insets/InsetTabular.h
===================================================================
--- src/insets/InsetTabular.h	(revision 23801)
+++ src/insets/InsetTabular.h	(working copy)
@@ -107,14 +107,6 @@
 		///
 		VALIGN_MIDDLE,
 		///
-		M_TOGGLE_LINE_TOP,
-		///
-		M_TOGGLE_LINE_BOTTOM,
-		///
-		M_TOGGLE_LINE_LEFT,
-		///
-		M_TOGGLE_LINE_RIGHT,
-		///
 		M_ALIGN_LEFT,
 		///
 		M_ALIGN_RIGHT,
@@ -245,13 +237,13 @@
 	Tabular(Buffer const &, col_type columns_arg, row_type rows_arg);
 
 	/// Returns true if there is a topline, returns false if not
-	bool topLine(idx_type cell, bool wholerow = false) const;
+	bool topLine(idx_type cell) const;
 	/// Returns true if there is a topline, returns false if not
-	bool bottomLine(idx_type cell, bool wholerow = false) const;
+	bool bottomLine(idx_type cell) const;
 	/// Returns true if there is a topline, returns false if not
-	bool leftLine(idx_type cell, bool wholecolumn = false) const;
+	bool leftLine(idx_type cell) const;
 	/// Returns true if there is a topline, returns false if not
-	bool rightLine(idx_type cell, bool wholecolumn = false) const;
+	bool rightLine(idx_type cell) const;
 
 	///
 	bool topAlreadyDrawn(idx_type cell) const;
@@ -286,14 +278,22 @@
 	///
 	void setAllLines(idx_type cell, bool line);
 	///
-	void setTopLine(idx_type cell, bool line, bool wholerow = false);
+	void setTopLine(idx_type cell, bool line);
 	///
-	void setBottomLine(idx_type cell, bool line, bool wholerow = false);
+	void setBottomLine(idx_type cell, bool line);
 	///
-	void setLeftLine(idx_type cell, bool line, bool wholecolumn = false);
+	void setLeftLine(idx_type cell, bool line);
 	///
-	void setRightLine(idx_type cell, bool line, bool wholecolumn = false);
+	void setRightLine(idx_type cell, bool line);
 	///
+	bool rowTopLine(row_type row) const;
+	///
+	bool rowBottomLine(row_type row) const;
+	///
+	bool columnLeftLine(col_type column) const;
+	///
+	bool columnRightLine(col_type column) const;
+
 	void setAlignment(idx_type cell, LyXAlignment align,
 			  bool onlycolumn = false);
 	///
@@ -611,7 +611,7 @@
 	///
 	bool calculate_width_of_column_NMC(col_type column); // no multi cells
 	///
-	idx_type cells_in_multicolumn(idx_type cell) const;
+	idx_type columnSpan(idx_type cell) const;
 	///
 	BoxType useParbox(idx_type cell) const;
 	///
@@ -744,6 +744,10 @@
 
 	/// lock cell with given index
 	void edit(Cursor & cur, bool front, EntryDirection entry_from);
+	/// get table row from x coordinate
+	int rowFromY(Cursor & cur, int y) const;
+	/// get table column from y coordinate
+	int columnFromX(Cursor & cur, int x) const;
 	///
 	Inset * editXY(Cursor & cur, int x, int y);
 	/// can we go further down on mouse click?

Reply via email to