Dokuwiki - improvements to code and rowspan transformations
diff --git a/conf/converter.dokuwiki.properties b/conf/converter.dokuwiki.properties
index 3d33c8e..d8d1f8e 100644
--- a/conf/converter.dokuwiki.properties
+++ b/conf/converter.dokuwiki.properties
@@ -75,7 +75,7 @@
 # Code (needs to be early so we can tokenize the contents)

 DokuWiki.002.code.java-regex-tokenizer=(?s)<code>(.*?)<\/code>{replace-with}{code}$1{code}

 DokuWiki.002.code-tsql.java-regex-tokenizer=(?s)\<code (tsql)\>(.*?)<\/code>{replace-with}{code:sql}$2{code}

-DokuWiki.002.code-type.java-regex-tokenizer=(?s)\<code ([^>]+?)\>(.*?)<\/code>{replace-with}{code:$1}$2{code}

+DokuWiki.002.code-type.java-regex-tokenizer=(?s)\<code ([^> ]+).*?\>(.*?)<\/code>{replace-with}{code:$1}$2{code}

 DokuWiki.002.noformat.java-regex-tokenizer=(?s)%%(.*?)%%{replace-with}{noformat}$1{noformat}

 # We do this after code because code blocks often have leading spaces and we

 # don't want to transform a code block more than once

@@ -136,6 +136,7 @@
 

 # Tables -- must be run before the image and link converters

 DokuWiki.21.prep-colspans.class=com.atlassian.uwc.converters.dokuwiki.PrepColSpansConverter

+DokuWiki.22.prep-rowspans.class=com.atlassian.uwc.converters.dokuwiki.PrepRowSpansConverter

 DokuWiki.23.table1.perl=s/\^/||/g

 

 # Interwiki links

diff --git a/src/com/atlassian/uwc/converters/dokuwiki/PrepRowSpansConverter.java b/src/com/atlassian/uwc/converters/dokuwiki/PrepRowSpansConverter.java
new file mode 100644
index 0000000..fd927d6
--- /dev/null
+++ b/src/com/atlassian/uwc/converters/dokuwiki/PrepRowSpansConverter.java
@@ -0,0 +1,104 @@
+package com.atlassian.uwc.converters.dokuwiki;
+
+import java.util.HashMap;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.atlassian.uwc.converters.BaseConverter;
+import com.atlassian.uwc.converters.tikiwiki.RegexUtil;
+import com.atlassian.uwc.ui.Page;
+
+public class PrepRowSpansConverter extends BaseConverter {
+
+
+	public static final String TOKENKEY = "UWCTOKENROWSPANS:";
+	private static final String DELIM = "::";
+	@Override
+	public void convert(Page page) {
+		String input = page.getOriginalText();
+		String converted = prep(input);
+		page.setConvertedText(converted);
+	}
+	
+	Pattern rowspan = Pattern.compile("(?<=^|\n)[|^](.*?):::(.*?)((\n(?=\\s*[^|^]))|$)", Pattern.DOTALL);
+	protected String prep(String input) {
+		Matcher rowspanFinder = rowspan.matcher(input);
+		StringBuffer sb = new StringBuffer();
+		boolean found = false;
+		while (rowspanFinder.find()) {
+			found = true;
+			String table = rowspanFinder.group();
+			//how many columns
+			int numcols = getNumCols(table);
+			//Look for a cell without the signal. Does the one following have it?
+			for (int i = 0; i < numcols; i++) {
+				//for each :::, if the one above is not :::, put the token?
+				table = handleColumn(i, table);
+			}
+			table = RegexUtil.handleEscapesInReplacement(table);
+			rowspanFinder.appendReplacement(sb, table);
+		}
+		if (found) {
+			rowspanFinder.appendTail(sb);
+			return sb.toString();
+		}
+		return input;
+	}
+	
+	String cellstring = "[|^][^|^]*";
+	Pattern cell = Pattern.compile(cellstring);
+	protected String handleColumn(int i, String input) {
+		String pre = "(?<=^|\n)";
+		while (i-- > 0) { pre += cellstring;} 
+		Pattern p = Pattern.compile(pre+"("+cellstring+")");
+		Matcher colFinder = p.matcher(input);
+		int lastrow = -1;
+		int length = 0;
+		TreeMap<Integer, String> additions = new TreeMap<Integer, String>();
+		while (colFinder.find()) {
+			String cellcontents = colFinder.group(1);
+			if (!cellcontents.contains(":::")) {
+				if (length > 0) {
+					additions.put(lastrow, DELIM + TOKENKEY + (length+1) + DELIM);
+					length = 0;
+				}
+				lastrow = colFinder.end();
+			}
+			else {
+				length++;
+			}
+		}
+		if (length > 0) {
+			additions.put(lastrow, DELIM + TOKENKEY + (length+1) + DELIM);
+		}
+		Set<Integer> keySet = additions.keySet();
+		Vector<Integer> keys = new Vector<Integer>(keySet);
+		if (keys.isEmpty()) return input;
+		String output = "";
+		int first = 0, last = 0;
+		for (int index = 0; index < keys.size(); index ++ ) {
+			last = keys.get(index);
+			String part = input.substring(first, last);
+			output += part + additions.get(last); 
+			first = last;
+		}
+		output += input.substring(last);
+		return output;
+	}
+
+	Pattern line = Pattern.compile("^[^\n]+", Pattern.MULTILINE);
+	protected int getNumCols(String input) {
+		Matcher lineFinder = line.matcher(input);
+		while (lineFinder.find()) {
+			String firstline = lineFinder.group();
+			if (firstline.contains(PrepColSpansConverter.TOKENKEY)) continue;
+			String[] cols = firstline.split("[|^]");
+			return cols.length - 1;
+		}
+		return 0;
+	}
+
+}
diff --git a/src/com/atlassian/uwc/converters/dokuwiki/PrepRowSpansConverterTest.java b/src/com/atlassian/uwc/converters/dokuwiki/PrepRowSpansConverterTest.java
new file mode 100644
index 0000000..7db56bf
--- /dev/null
+++ b/src/com/atlassian/uwc/converters/dokuwiki/PrepRowSpansConverterTest.java
@@ -0,0 +1,188 @@
+package com.atlassian.uwc.converters.dokuwiki;
+
+import junit.framework.TestCase;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+
+public class PrepRowSpansConverterTest extends TestCase {
+
+	PrepRowSpansConverter tester = null;
+	Logger log = Logger.getLogger(this.getClass());
+	protected void setUp() throws Exception {
+		tester = new PrepRowSpansConverter();
+		PropertyConfigurator.configure("log4j.properties");
+	}
+
+	public void testPrep_MultiRow() {
+		String input, expected, actual;
+		input = "^ 1            ^ 2                ^ 1            ^ 2                ^\n" + 
+				"| a | b     | a         | b             |\n" + 
+				"| :::                | b      | :::                | d              |\n" + 
+				"| :::                | b  | :::                | d |\n" + 
+				"| :::                | b | :::                | d |\n" + 
+				"^ 1 ^ 2 ^ 3 ^ 4 ^\n" + 
+				"| a        | b               | c     | d |\n" + 
+				"| :::                |b             | :::                | d        |\n" + 
+				"| :::                | b    | :::                | d     |\n" + 
+				"| :::                |b     | :::                | d     |\n" + 
+				"";
+		expected ="^ 1            ^ 2                ^ 1            ^ 2                ^\n" + 
+				"| a ::UWCTOKENROWSPANS:4::| b     | a         ::UWCTOKENROWSPANS:4::| b             |\n" + 
+				"| :::                | b      | :::                | d              |\n" + 
+				"| :::                | b  | :::                | d |\n" + 
+				"| :::                | b | :::                | d |\n" + 
+				"^ 1 ^ 2 ^ 3 ^ 4 ^\n" + 
+				"| a        ::UWCTOKENROWSPANS:4::| b               | c     ::UWCTOKENROWSPANS:4::| d |\n" + 
+				"| :::                |b             | :::                | d        |\n" + 
+				"| :::                | b    | :::                | d     |\n" + 
+				"| :::                |b     | :::                | d     |\n" + 
+				"";
+		actual = tester.prep(input);
+		assertNotNull(actual);
+		assertEquals(expected, actual);
+	}
+	
+	public void testPrep_MultiRow_b() {
+		String input, expected, actual;
+		input = "^ 1            ^ 2                ^ 1            ^ 2                ^\n" + 
+				"| a | b     | a         | b             |\n" + 
+				"| :::                | b      | :::                | d              |\n" + 
+				"| :::                | b  | :::                | d |\n" + 
+				"| :::                | b | :::                | d |\n" + 
+				"^ 1 ^ 2 ^ 3 ^ 4 ^\n" + 
+				"| a        | b               | c     | d |\n" + 
+				"| :::                |b             | :::                | d        |\n" + 
+				"| :::                | b    | :::                | d     |\n" + 
+				"| :::                |b     | c                | d     |\n" + 
+				"no longer a table";
+		expected ="^ 1            ^ 2                ^ 1            ^ 2                ^\n" + 
+				"| a ::UWCTOKENROWSPANS:4::| b     | a         ::UWCTOKENROWSPANS:4::| b             |\n" + 
+				"| :::                | b      | :::                | d              |\n" + 
+				"| :::                | b  | :::                | d |\n" + 
+				"| :::                | b | :::                | d |\n" + 
+				"^ 1 ^ 2 ^ 3 ^ 4 ^\n" + 
+				"| a        ::UWCTOKENROWSPANS:4::| b               | c     ::UWCTOKENROWSPANS:3::| d |\n" + 
+				"| :::                |b             | :::                | d        |\n" + 
+				"| :::                | b    | :::                | d     |\n" + 
+				"| :::                |b     | c                | d     |\n" + 
+				"no longer a table";
+		actual = tester.prep(input);
+		assertNotNull(actual);
+		assertEquals(expected, actual);
+	}
+	
+	public void testGetNumCols() {
+		String input;
+		int expected, actual;
+		input = "^ 1            ^ 2                ^ 1            ^ 2                ^\n" + 
+				"| a | b     | a         | b             |\n" + 
+				"| :::                | b      | :::                | d              |\n";
+		expected = 4;
+		actual = tester.getNumCols(input);
+		assertNotNull(actual);
+		assertEquals(expected, actual);
+	}
+	
+	
+	public void testGetNumCols_WithColspan() {
+		String input;
+		int expected, actual;
+		input = "^ h1  ::UWCTOKENCOLSPANS:6::^\n" + 
+				"^ h1       ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^\n" + 
+				"| Trala        | abc.def.ghu.jkl.edu       | D:\\Path\\TO\\Some\\Place_tada\\asd     | D:\\Path\\TO\\Some\\Place_tada\\asd[mmyyyy].txt  | asd.asd.asd.org  | Asdlkj_askjda_BD  |\n" + 
+				"| :::           | foo-1234-bar.abc.def.org:0986  | :::                                       | D:\\AppLogFiles\\BindingLogs_[yyyy-mm].txt        | :::                                      | :::             |\n" + 
+				"| Lala         | a.b.c.d.e       | D:\\Apps\\INT\\Do\\ComparioXMLSite_es\\Web     | D:\\AppLogFiles\\ComparioXmlSite.xml[mmyyyy].txt  | sqlcompariopreview.internet.conseur.org  | Compario_ES_ES  |\n" + 
+				"";
+		expected = 6;
+		actual = tester.getNumCols(input);
+		assertNotNull(actual);
+		assertEquals(expected, actual);
+	}
+	
+	public void testHandleColumn_0() {
+		String input, expected, actual;
+		input = "^ 1            ^ 2                ^ 1            ^ 2                ^\n" + 
+				"| a | b     | a         | b             |\n" + 
+				"| :::                | b      | :::                | d              |\n" + 
+				"| :::                | b  | :::                | d |\n" + 
+				"| :::                | b | :::                | d |\n" + 
+				"^ 1 ^ 2 ^ 3 ^ 4 ^\n" + 
+				"| a        | b               | c     | d |\n" + 
+				"| :::                |b             | :::                | d        |\n";
+		expected = "^ 1            ^ 2                ^ 1            ^ 2                ^\n" + 
+				"| a ::UWCTOKENROWSPANS:4::| b     | a         | b             |\n" + 
+				"| :::                | b      | :::                | d              |\n" + 
+				"| :::                | b  | :::                | d |\n" + 
+				"| :::                | b | :::                | d |\n" + 
+				"^ 1 ^ 2 ^ 3 ^ 4 ^\n" + 
+				"| a        ::UWCTOKENROWSPANS:2::| b               | c     | d |\n" + 
+				"| :::                |b             | :::                | d        |\n";
+		actual = tester.handleColumn(0, input);
+		assertNotNull(actual);
+		assertEquals(expected, actual);
+	}
+	
+	public void testHandleColumn_2() {
+		String input, expected, actual;
+		input = "^ 1            ^ 2                ^ 1            ^ 2                ^\n" + 
+				"| a | b     | a         | b             |\n" + 
+				"| :::                | b      | :::                | d              |\n" + 
+				"| :::                | b  | :::                | d |\n" + 
+				"| :::                | b | :::                | d |\n" + 
+				"^ 1 ^ 2 ^ 3 ^ 4 ^\n" + 
+				"| a        | b               | c     | d |\n" + 
+				"| :::                |b             | :::                | d        |\n";
+		expected = "^ 1            ^ 2                ^ 1            ^ 2                ^\n" + 
+				"| a | b     | a         ::UWCTOKENROWSPANS:4::| b             |\n" + 
+				"| :::                | b      | :::                | d              |\n" + 
+				"| :::                | b  | :::                | d |\n" + 
+				"| :::                | b | :::                | d |\n" + 
+				"^ 1 ^ 2 ^ 3 ^ 4 ^\n" + 
+				"| a        | b               | c     ::UWCTOKENROWSPANS:2::| d |\n" + 
+				"| :::                |b             | :::                | d        |\n";
+		actual = tester.handleColumn(2, input);
+		assertNotNull(actual);
+		assertEquals(expected, actual);
+	}
+	
+	public void testExample() {
+		String input, expected, actual;
+		input = "^ h1  ^ h2                           ^ h3                                       ^ h4                                       ^ h5                                       ^ h6                                                        ^\n" + 
+				"^ r1c1   | r1c2  |  r1c3| r1c4            | r1c5 | r1c6 |\n" + 
+				"^ :::          | r2c2                       | r2c3| c4  | c5 | c6 |\n" + 
+				"^ :::          | c2 | c3|c4| c5|c6  |\n" + 
+				"^ :::          | c2 | c3|c4| c5|c6  |\n" + 
+				"^ Health page  | c2  ::UWCTOKENCOLSPANS:5::|\n" + 
+				"";
+		expected = "^ h1  ^ h2                           ^ h3                                       ^ h4                                       ^ h5                                       ^ h6                                                        ^\n" + 
+				"^ r1c1   ::UWCTOKENROWSPANS:4::| r1c2  |  r1c3| r1c4            | r1c5 | r1c6 |\n" + 
+				"^ :::          | r2c2                       | r2c3| c4  | c5 | c6 |\n" + 
+				"^ :::          | c2 | c3|c4| c5|c6  |\n" + 
+				"^ :::          | c2 | c3|c4| c5|c6  |\n" + 
+				"^ Health page  | c2  ::UWCTOKENCOLSPANS:5::|\n";
+		actual = tester.prep(input);
+		assertNotNull(actual);
+		assertEquals(expected, actual);
+	}
+	
+	public void testExample2() {
+		String input, expected, actual;
+		input = "^ h1  ::UWCTOKENCOLSPANS:6::^\n" + 
+				"^ h1       ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^\n" + 
+				"| Trala        | abc.def.ghu.jkl.edu       | D:\\Path\\TO\\Some\\Place_tada\\asd     | D:\\Path\\TO\\Some\\Place_tada\\asd[mmyyyy].txt  | asd.asd.asd.org  | Asdlkj_askjda_BD  |\n" + 
+				"| :::           | foo-1234-bar.abc.def.org:0986  | :::                                       | D:\\AppLogFiles\\BindingLogs_[yyyy-mm].txt        | :::                                      | :::             |\n" + 
+				"| Lala         | a.b.c.d.e       | D:\\Apps\\INT\\Do\\ComparioXMLSite_es\\Web     | D:\\AppLogFiles\\ComparioXmlSite.xml[mmyyyy].txt  | sqlcompariopreview.internet.conseur.org  | Compario_ES_ES  |\n" + 
+				"";
+		expected = "^ h1  ::UWCTOKENCOLSPANS:6::^\n" + 
+				"^ h1       ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^\n" + 
+				"| Trala        ::UWCTOKENROWSPANS:2::| abc.def.ghu.jkl.edu       | D:\\Path\\TO\\Some\\Place_tada\\asd     ::UWCTOKENROWSPANS:2::| D:\\Path\\TO\\Some\\Place_tada\\asd[mmyyyy].txt  | asd.asd.asd.org  ::UWCTOKENROWSPANS:2::| Asdlkj_askjda_BD  ::UWCTOKENROWSPANS:2::|\n" + 
+				"| :::           | foo-1234-bar.abc.def.org:0986  | :::                                       | D:\\AppLogFiles\\BindingLogs_[yyyy-mm].txt        | :::                                      | :::             |\n" + 
+				"| Lala         | a.b.c.d.e       | D:\\Apps\\INT\\Do\\ComparioXMLSite_es\\Web     | D:\\AppLogFiles\\ComparioXmlSite.xml[mmyyyy].txt  | sqlcompariopreview.internet.conseur.org  | Compario_ES_ES  |\n" + 
+				"";
+		actual = tester.prep(input);
+		assertNotNull(actual);
+		assertEquals(expected, actual);
+	}
+	
+}
diff --git a/src/com/atlassian/uwc/converters/dokuwiki/TableRowColSpanConverter.java b/src/com/atlassian/uwc/converters/dokuwiki/TableRowColSpanConverter.java
index a09ab76..76ec28f 100644
--- a/src/com/atlassian/uwc/converters/dokuwiki/TableRowColSpanConverter.java
+++ b/src/com/atlassian/uwc/converters/dokuwiki/TableRowColSpanConverter.java
@@ -61,185 +61,48 @@
 		}
 		return input;
 	}
-
-	Pattern table = Pattern.compile("<table>(.*?)</table>", Pattern.DOTALL);
+	
+	Pattern uwctokenrowspan = Pattern.compile("::" + PrepRowSpansConverter.TOKENKEY + "(\\d+)::");
 	Pattern rowspan = Pattern.compile(":::");
-	Pattern tablerow = Pattern.compile("<tr>(.*?)</tr>", Pattern.DOTALL);
-	Pattern tdWithColspan = Pattern.compile("<t([dh])(?: colspan='(\\d+)')?>(.*?)</t[dh]>", Pattern.DOTALL);
 	protected String convertRowspans(String input) {
-		Matcher tableFinder = table.matcher(input);
+		Matcher tdFinder = td.matcher(input);
 		StringBuffer sb = new StringBuffer();
 		boolean found = false;
-		while (tableFinder.find()) {
-			Vector<Integer> rowindeces = new Vector<Integer>();
-			Vector<Integer> colindeces = new Vector<Integer>();
-			Vector<Integer> rowvals = new Vector<Integer>();
-			Vector<Integer> colclear = new Vector<Integer>();
+		while (tdFinder.find()) {
 			found = true;
-			String tableContents = tableFinder.group(1);
-			Matcher rowspanFinder = rowspan.matcher(tableContents);
-			if (!rowspanFinder.find()) continue;
-
-			int rowspanVal = 1; //the value of the rowspan attribute
-			int lastrow = 0;
-			int rowspancount = 0;
-
-			Matcher rowFinder = tablerow.matcher(tableContents);
-			StringBuffer rowsb = new StringBuffer();
-			boolean rowfound = false;
-			boolean noteindex = true;
-
-			boolean clearrow = false;
-			while (rowFinder.find()) {
-				int lastcol = -1;
-				rowfound = true;
-				boolean newrow = true;
-
-				String rowcontents = rowFinder.group(1);
-				Matcher tdFinder = tdWithColspan.matcher(rowcontents);
-				StringBuffer tdsb = new StringBuffer();
-				boolean tdfound = false;
-				boolean rowspanfoundLast = true;
-				boolean rowspanfoundCurrent = true;
-				int rowspancountThisRow = 0;
-				int currentColOffset = 0;
-				while (tdFinder.find()) {
-					tdfound = true;
-					lastcol++;
-					String cell = tdFinder.group(3);
-					String colspanOffset = tdFinder.group(2);
-
-					rowspanFinder = rowspan.matcher(cell);
-					rowspanfoundLast = rowspanfoundCurrent;
-					rowspanfoundCurrent = rowspanFinder.find();
-					if (!rowspanfoundCurrent) { //no rowspan
-						colclear.add(lastcol+currentColOffset);
-					}
-					else { //found a rowspan!
-						tdFinder.appendReplacement(tdsb, ""); //remove the ::: cells
-						if (newrow && clearrow && rowspanVal > 1) {
-							rowspancount++;
-							fillRowSpanVals(rowindeces, rowvals, rowspanVal);
-							rowspanVal = currentColOffset+1;
-							colindeces.add(lastcol); //note the index of the current cell
-							rowindeces.add(lastrow-1);//note the index of the previous row
-							noteindex = false;
-						}
-						rowspanVal++;
-
-						if (noteindex || !newrow) {
-							rowspancount++;
-							rowspancountThisRow++;
-							colindeces.add(lastcol); //note the index of the current cell
-							rowindeces.add(lastrow-1);//note the index of the previous row
-							noteindex = false;
-							if (!newrow && rowspancountThisRow > 0) rowspanVal--;
-							colclear.removeAllElements();
-						}
-						else if (!rowspanfoundLast) {
-							noteindex = true; 
-							rowvals.add(rowspanVal);
-							rowspanVal=currentColOffset+1;
-						}
-
-						newrow = false;
-					}
-					if (colspanOffset != null) 
-						currentColOffset += (Integer.parseInt(colspanOffset));
-				}
-				if (tdfound) {
-					tdFinder.appendTail(tdsb);
-					rowcontents = "<tr>"+tdsb.toString()+"</tr>";
-				}
-				else
-					rowcontents = "<tr>" + rowcontents + "</tr>";
-
-
-				String replacement = rowcontents;
-				replacement = RegexUtil.handleEscapesInReplacement(replacement);
-				rowFinder.appendReplacement(rowsb, replacement);
-				lastrow++;
-				boolean tmpclear = true;
-				for (int i = 0; i < lastcol-1; i++) {
-					if (!colclear.contains(i+currentColOffset)) tmpclear = false; 
-				}
-				clearrow = tmpclear;
-				colclear.removeAllElements();
+			String type = tdFinder.group(1);
+			String row = tdFinder.group(2);
+			Matcher rowspanFinder = rowspan.matcher(row);
+			if (rowspanFinder.find()) {
+				tdFinder.appendReplacement(sb, "");
+				continue;
 			}
-			if (rowfound) {
-				fillRowSpanVals(rowindeces, rowvals, rowspanVal);
-				rowspanVal=1;
-				rowFinder.appendTail(rowsb);
-				tableContents = rowsb.toString();
+			
+			Matcher uwctokenFinder = uwctokenrowspan.matcher(row);
+			boolean found2 = false;
+			String len = "";
+			StringBuffer sb2 = new StringBuffer();
+			while (uwctokenFinder.find()) {
+				found2 = true;
+				len = uwctokenFinder.group(1);
+				String rep2= RegexUtil.handleEscapesInReplacement("");
+				uwctokenFinder.appendReplacement(sb2, rep2);
 			}
-
-			rowFinder = tablerow.matcher(tableContents);
-			rowsb = new StringBuffer();
-			rowfound = false;
-			int currentrow = 0;
-			int index = 0;
-			while (rowFinder.find()) {
-				rowfound = true;
-				String rowcontents = rowFinder.group(1);
-
-				if (index >= rowspancount) break;
-				int rowindex = rowindeces.get(index);
-				int colindex = colindeces.get(index);
-				int rowval = rowvals.get(index);
-				if (currentrow == rowindex) {
-					Matcher tdFinder = td.matcher(rowcontents);
-					StringBuffer tdsb = new StringBuffer();
-					boolean tdfound = false;
-
-					int currentcell = 0;
-					while (tdFinder.find()) {
-						tdfound = true;
-						String type = tdFinder.group(1);
-						if (currentcell == colindex) {
-							String newcell = "<t"+type+" rowspan='"+rowval+"'>"+tdFinder.group(2)+"</t"+type+">";
-							tdFinder.appendReplacement(tdsb, newcell); //replace the rowspan cell
-							index++;
-							if (index < rowspancount) { //get these now in case we have more rowspans in the same row
-								colindex = colindeces.get(index); 
-								rowval = rowvals.get(index);
-							}
-						}
-						currentcell++;
-					}
-					if (tdfound) {
-						tdFinder.appendTail(tdsb);
-						rowcontents = tdsb.toString();
-					}
-				}
-
-				String replacement = "<tr>"+rowcontents+"</tr>";
-				replacement = RegexUtil.handleEscapesInReplacement(replacement);
-				rowFinder.appendReplacement(rowsb, replacement);
-				currentrow++;
+			if (found2) {
+				uwctokenFinder.appendTail(sb2);
+				row = sb2.toString();
 			}
-			if (rowfound) {
-				rowFinder.appendTail(rowsb);
-				tableContents = rowsb.toString();
-			}
-
-			String replacement = "<table>" + tableContents + "</table>";
+			else continue;
+			String replacement = "<t"+type+" rowspan='"+len+"'>"+row+"</t"+type+">";
 			replacement = RegexUtil.handleEscapesInReplacement(replacement);
-			tableFinder.appendReplacement(sb, replacement);
+			tdFinder.appendReplacement(sb, replacement);
 		}
 		if (found) {
-			tableFinder.appendTail(sb);
+			tdFinder.appendTail(sb);
 			return sb.toString();
 		}
 		return input;
 	}
-	public void fillRowSpanVals(Vector<Integer> indeces, Vector<Integer> vals, int val) {
-		vals.add(val);
-		int last = indeces.get(vals.size()-1);
-		while (indeces.size() > vals.size()) {
-			if (indeces.get(vals.size()-1) == last)
-				vals.add(val);
-			else break;
-		}
-	}
+
 
 }
diff --git a/src/com/atlassian/uwc/converters/dokuwiki/TableRowColSpanConverterTest.java b/src/com/atlassian/uwc/converters/dokuwiki/TableRowColSpanConverterTest.java
index 7562a09..b233331 100644
--- a/src/com/atlassian/uwc/converters/dokuwiki/TableRowColSpanConverterTest.java
+++ b/src/com/atlassian/uwc/converters/dokuwiki/TableRowColSpanConverterTest.java
@@ -130,7 +130,7 @@
 				"<th><p> Head 6 </p></th>\n" + 
 				"</tr>\n" + 
 				"<tr>\n" + 
-				"<th><p> Row 1 </p></th>\n" + 
+				"<th><p> Row 1 ::UWCTOKENROWSPANS:4::</p></th>\n" + 
 				"<td> Row 2 </td>\n" + 
 				"<td> Row 3 </td>\n" +
 				"<td> Row 4 </td>\n" +
@@ -233,7 +233,7 @@
 				"</tr>\n" + 
 				"<tr>\n" + 
 				"<td><p> Row 4 Col 1    </p></td>\n" + 
-				"<td><p> this cell spans vertically </p></td>\n" + 
+				"<td><p> this cell spans vertically ::UWCTOKENROWSPANS:3::</p></td>\n" + 
 				"<td><p> Row 4 Col 3        </p></td>\n" + 
 				"</tr>\n" + 
 				"<tr>\n" + 
@@ -255,7 +255,7 @@
 				"<td><p> Row 8 some colspan (note the double pipe) ::UWCTOKENCOLSPANS:3::</p></td>\n" + 
 				"</tr>\n" + 
 				"<tr>\n" + 
-				"<td><p> Row 9 Col 1    </p></td>\n" + 
+				"<td><p> Row 9 Col 1    ::UWCTOKENROWSPANS:3::</p></td>\n" + 
 				"<td><p> Row 9 Col 2     </p></td>\n" + 
 				"<td><p> Row 9 Col 3        </p></td>\n" + 
 				"</tr>\n" + 
@@ -360,7 +360,7 @@
 				"</tr>\n" + 
 				"<tr>\n" + 
 				"<td><p> Row 4 Col 1    </p></td>\n" + 
-				"<td><p> this cell spans vertically </p></td>\n" + 
+				"<td><p> this cell spans vertically ::UWCTOKENROWSPANS:3::</p></td>\n" + 
 				"<td><p> Row 4 Col 3        </p></td>\n" + 
 				"</tr>\n" + 
 				"<tr>\n" + 
@@ -384,7 +384,7 @@
 				"<td><p> Row 8 Col 3</p></td>\n" +
 				"</tr>\n" + 
 				"<tr>\n" + 
-				"<td><p> Row 9 Col 1    </p></td>\n" + 
+				"<td><p> Row 9 Col 1    ::UWCTOKENROWSPANS:3::</p></td>\n" + 
 				"<td><p> Row 9 Col 2     </p></td>\n" + 
 				"<td><p> Row 9 Col 3        </p></td>\n" + 
 				"</tr>\n" + 
@@ -481,8 +481,8 @@
 				"</tr>\n" +
 				"<tr>\n" + 
 				"<td><p> Row 1 Col 1    </p></td>\n" + 
-				"<td><p> Row 1 Col 2     </p></td>\n" + 
-				"<td><p> Row 1 Col 3        </p></td>\n" + 
+				"<td><p> Row 1 Col 2     ::UWCTOKENROWSPANS:4::</p></td>\n" + 
+				"<td><p> Row 1 Col 3        ::UWCTOKENROWSPANS:3::</p></td>\n" + 
 				"</tr>\n" +
 				"<tr>\n" + 
 				"<td><p> Row 2 Col 1    </p></td>\n" + 
@@ -559,7 +559,7 @@
 				"</tr>\n" + 
 				"<tr>\n" + 
 				"<td><p> Row 4 Col 1    </p></td>\n" + 
-				"<td><p> this cell spans vertically </p></td>\n" + 
+				"<td><p> this cell spans vertically ::UWCTOKENROWSPANS:3::</p></td>\n" + 
 				"<td><p> Row 4 Col 3        </p></td>\n" + 
 				"</tr>\n" + 
 				"<tr>\n" + 
@@ -581,7 +581,7 @@
 				"<td><p> Row 8 some colspan (note the double pipe) ::UWCTOKENCOLSPANS:3::</p></td>\n" + 
 				"</tr>\n" + 
 				"<tr>\n" + 
-				"<td><p> Row 9 Col 1    </p></td>\n" + 
+				"<td><p> Row 9 Col 1    ::UWCTOKENROWSPANS:3::</p></td>\n" + 
 				"<td><p> Row 9 Col 2     </p></td>\n" + 
 				"<td><p> Row 9 Col 3        </p></td>\n" + 
 				"</tr>\n" + 
@@ -605,8 +605,8 @@
 				"</tr>\n" + 
 				"<tr>\n" + 
 				"<td><p> Row 1 Col 1    </p></td>\n" + 
-				"<td><p> Row 1 Col 2     </p></td>\n" + 
-				"<td><p> Row 1 Col 3        </p></td>\n" + 
+				"<td><p> Row 1 Col 2     ::UWCTOKENROWSPANS:4::</p></td>\n" + 
+				"<td><p> Row 1 Col 3        ::UWCTOKENROWSPANS:3::</p></td>\n" + 
 				"</tr>\n" + 
 				"<tr>\n" + 
 				"<td><p> Row 2 Col 1    </p></td>\n" + 
@@ -727,9 +727,9 @@
 				"<th><p> h4                </p></th>\n" + 
 				"</tr>\n" + 
 				"<tr>\n" + 
-				"<td><p> foo           </p></td>\n" + 
+				"<td><p> foo           ::UWCTOKENROWSPANS:2::</p></td>\n" + 
 				"<td><p> bar               </p></td>\n" + 
-				"<td><p> baz      </p></td>\n" + 
+				"<td><p> baz      ::UWCTOKENROWSPANS:2::</p></td>\n" + 
 				"<td><p> tralala          </p></td>\n" + 
 				"</tr>\n" + 
 				"<tr>\n" + 
@@ -783,12 +783,12 @@
 				"<th><p> h6 </p></th>\n" + 
 				"</tr>\n" + 
 				"<tr>\n" + 
-				"<td><p> thin        </p></td>\n" + 
+				"<td><p> thin        ::UWCTOKENROWSPANS:2::</p></td>\n" + 
 				"<td><p> man </p></td>\n" + 
-				"<td><p> starring </p></td>\n" + 
+				"<td><p> starring ::UWCTOKENROWSPANS:2::</p></td>\n" + 
 				"<td><p> myrna </p></td>\n" + 
-				"<td><p> loy  </p></td>\n" + 
-				"<td><p> tralalala  </p></td>\n" + 
+				"<td><p> loy  ::UWCTOKENROWSPANS:2::</p></td>\n" + 
+				"<td><p> tralalala  ::UWCTOKENROWSPANS:2::</p></td>\n" + 
 				"</tr>\n" + 
 				"<tr>\n" + 
 				"<td><p> :::           </p></td>\n" + 
@@ -799,12 +799,12 @@
 				"<td><p> :::             </p></td>\n" + 
 				"</tr>\n" + 
 				"<tr>\n" + 
-				"<td><p> foo         </p></td>\n" + 
+				"<td><p> foo         ::UWCTOKENROWSPANS:2::</p></td>\n" + 
 				"<td><p> bar     </p></td>\n" + 
-				"<td><p> arg</p></td>\n" + 
+				"<td><p> arg::UWCTOKENROWSPANS:2::</p></td>\n" + 
 				"<td><p> this </p></td>\n" + 
-				"<td><p> is </p></td>\n" + 
-				"<td><p> annoying </p></td>\n" + 
+				"<td><p> is ::UWCTOKENROWSPANS:2::</p></td>\n" + 
+				"<td><p> annoying ::UWCTOKENROWSPANS:2::</p></td>\n" + 
 				"</tr>\n" + 
 				"<tr>\n" + 
 				"<td><p> :::           </p></td>\n" + 
@@ -815,12 +815,12 @@
 				"<td><p> :::             </p></td>\n" + 
 				"</tr>\n" + 
 				"<tr>\n" + 
-				"<td><p> 1      </p></td>\n" + 
+				"<td><p> 1      ::UWCTOKENROWSPANS:2::</p></td>\n" + 
 				"<td><p> 2    </p></td>\n" + 
-				"<td><p> 3   </p></td>\n" + 
+				"<td><p> 3   ::UWCTOKENROWSPANS:2::</p></td>\n" + 
 				"<td><p> 4  </p></td>\n" + 
-				"<td><p> 5 </p></td>\n" + 
-				"<td><p> 6  </p></td>\n" + 
+				"<td><p> 5 ::UWCTOKENROWSPANS:2::</p></td>\n" + 
+				"<td><p> 6  ::UWCTOKENROWSPANS:2::</p></td>\n" + 
 				"</tr>\n" + 
 				"<tr>\n" + 
 				"<td><p> :::           </p></td>\n" + 
@@ -990,4 +990,137 @@
 	}
 
 
+	
+	public void testConvertMoreRowSpanTroubles() {
+		String input, expected, actual;
+		input = "<table><tbody>\n" + 
+				"<tr>\n" + 
+				"<th><p> HEADER         ::UWCTOKENCOLSPANS:6::</p></th>\n" + 
+				"</tr>\n" + 
+				"<tr>\n" + 
+				"<th><p> h1       </p></th>\n" + 
+				"<th><p> h2                                                </p></th>\n" + 
+				"<th><p> h3                             </p></th>\n" + 
+				"<th><p> h4                                        </p></th>\n" + 
+				"<th><p> h5                        </p></th>\n" + 
+				"<th><p> h6        </p></th>\n" + 
+				"</tr>\n" + 
+				"<tr>\n" + 
+				"<td><p> r1c1        ::UWCTOKENROWSPANS:3::</p></td>\n" + 
+				"<td><p> r1c2     </p></td>\n" + 
+				"<td><p> r1c3     ::UWCTOKENROWSPANS:3::</p></td>\n" + 
+				"<td><p> r1c4  </p></td>\n" + 
+				"<td><p> r1c5  ::UWCTOKENROWSPANS:3::</p></td>\n" + 
+				"<td><p> r1c6  ::UWCTOKENROWSPANS:3::</p></td>\n" + 
+				"</tr>\n" + 
+				"<tr>\n" + 
+				"<td><p> :::           </p></td>\n" + 
+				"<td><p> r2c2          </p></td>\n" + 
+				"<td><p> :::                                       </p></td>\n" + 
+				"<td><p> r2c4        </p></td>\n" + 
+				"<td><p> :::                               </p></td>\n" + 
+				"<td><p> :::             </p></td>\n" + 
+				"</tr>\n" + 
+				"<tr>\n" + 
+				"<td><p> :::           </p></td>\n" + 
+				"<td><p> r3c2          </p></td>\n" + 
+				"<td><p> :::                                       </p></td>\n" + 
+				"<td><p>r3c4</p></td>\n" + 
+				"<td><p> :::                               </p></td>\n" + 
+				"<td><p> :::             </p></td>\n" + 
+				"</tr>\n" + 
+				"<tr>\n" + 
+				"<td><p> r4c1         ::UWCTOKENROWSPANS:3::</p></td>\n" + 
+				"<td><p> r4c2     </p></td>\n" + 
+				"<td><p> r4c3     ::UWCTOKENROWSPANS:3::</p></td>\n" + 
+				"<td><p> r4c4  </p></td>\n" + 
+				"<td><p> r4c5  ::UWCTOKENROWSPANS:3::</p></td>\n" + 
+				"<td><p> r4c6  ::UWCTOKENROWSPANS:3::</p></td>\n" + 
+				"</tr>\n" + 
+				"<tr>\n" + 
+				"<td><p> :::           </p></td>\n" + 
+				"<td><p> r2c2          </p></td>\n" + 
+				"<td><p> :::                                       </p></td>\n" + 
+				"<td><p> r2c4        </p></td>\n" + 
+				"<td><p> :::                               </p></td>\n" + 
+				"<td><p> :::             </p></td>\n" + 
+				"</tr>\n" + 
+				"<tr>\n" + 
+				"<td><p> :::           </p></td>\n" + 
+				"<td><p> r3c2          </p></td>\n" + 
+				"<td><p> :::                                       </p></td>\n" + 
+				"<td><p>r3c4</p></td>\n" + 
+				"<td><p> :::                               </p></td>\n" + 
+				"<td><p> :::             </p></td>\n" + 
+				"</tr>\n" + 
+				"</table>\n" + 
+				"";
+		expected = "<table><tbody>\n" + 
+				"<tr>\n" + 
+				"<th colspan='6'><p> HEADER         </p></th>\n" + 
+				"</tr>\n" + 
+				"<tr>\n" + 
+				"<th><p> h1       </p></th>\n" + 
+				"<th><p> h2                                                </p></th>\n" + 
+				"<th><p> h3                             </p></th>\n" + 
+				"<th><p> h4                                        </p></th>\n" + 
+				"<th><p> h5                        </p></th>\n" + 
+				"<th><p> h6        </p></th>\n" + 
+				"</tr>\n" + 
+				"<tr>\n" + 
+				"<td rowspan='3'><p> r1c1        </p></td>\n" + 
+				"<td><p> r1c2     </p></td>\n" + 
+				"<td rowspan='3'><p> r1c3     </p></td>\n" + 
+				"<td><p> r1c4  </p></td>\n" + 
+				"<td rowspan='3'><p> r1c5  </p></td>\n" + 
+				"<td rowspan='3'><p> r1c6  </p></td>\n" + 
+				"</tr>\n" + 
+				"<tr>\n" +
+				"\n" + 
+				"<td><p> r2c2          </p></td>\n" +
+				"\n" +
+				"<td><p> r2c4        </p></td>\n" +
+				"\n" +
+				"\n" +
+				"</tr>\n" + 
+				"<tr>\n" +
+				"\n" +
+				"<td><p> r3c2          </p></td>\n" +
+				"\n" +
+				"<td><p>r3c4</p></td>\n" +
+				"\n" +
+				"\n" +
+				"</tr>\n" + 
+				"<tr>\n" + 
+				"<td rowspan='3'><p> r4c1         </p></td>\n" + 
+				"<td><p> r4c2     </p></td>\n" + 
+				"<td rowspan='3'><p> r4c3     </p></td>\n" + 
+				"<td><p> r4c4  </p></td>\n" + 
+				"<td rowspan='3'><p> r4c5  </p></td>\n" + 
+				"<td rowspan='3'><p> r4c6  </p></td>\n" + 
+				"</tr>\n" + 
+				"<tr>\n" +
+				"\n" + 
+				"<td><p> r2c2          </p></td>\n" +
+				"\n" +
+				"<td><p> r2c4        </p></td>\n" +
+				"\n" +
+				"\n" +
+				"</tr>\n" + 
+				"<tr>\n" +
+				"\n" +
+				"<td><p> r3c2          </p></td>\n" +
+				"\n" +
+				"<td><p>r3c4</p></td>\n" +
+				"\n" +
+				"\n" +
+				"</tr>\n" + 
+				"</table>\n";
+		Page page = new Page(null);
+		page.setOriginalText(input);
+		tester.convert(page);
+		actual = page.getConvertedText();
+		assertNotNull(actual);
+		assertEquals(expected, actual);
+	}
 }