package cgeo.geocaching.utils;
import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
import org.xml.sax.XMLReader;
import android.text.Editable;
import android.text.Html.TagHandler;
import android.text.Spanned;
import android.text.style.StrikethroughSpan;
public class UnknownTagsHandler implements TagHandler {
private enum ListType {
Ordered, Unordered
}
private static final int UNDEFINED_POSITION = -1;
private int countCells = 0;
private int strikePos = UNDEFINED_POSITION;
private boolean problematicDetected = false;
private int listIndex = 0;
private ListType listType = ListType.Unordered;
@Override
public void handleTag(final boolean opening, final String tag, final Editable output,
final XMLReader xmlReader) {
if ("strike".equalsIgnoreCase(tag) || "s".equals(tag)) {
handleStrike(opening, output);
} else if ("table".equalsIgnoreCase(tag)) {
handleProblematic();
} else if ("td".equalsIgnoreCase(tag)) {
handleTd(opening, output);
} else if ("tr".equalsIgnoreCase(tag)) {
handleTr(opening, output);
} else if ("pre".equalsIgnoreCase(tag)) {
handleProblematic();
} else if ("ol".equalsIgnoreCase(tag)) {
handleOl(opening);
} else if ("li".equalsIgnoreCase(tag)) {
handleLi(opening, output);
} else if ("hr".equalsIgnoreCase(tag)) {
handleHr(opening, output);
}
}
private void handleStrike(final boolean opening, final Editable output) {
final int length = output.length();
if (opening) {
strikePos = length;
} else if (strikePos > UNDEFINED_POSITION) {
output.setSpan(new StrikethroughSpan(), strikePos, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
strikePos = UNDEFINED_POSITION;
}
}
public boolean isProblematicDetected() {
return problematicDetected;
}
private void handleProblematic() {
problematicDetected = true;
}
private void handleTd(final boolean opening, final Editable output) {
// insert bar for each table column, see https://en.wikipedia.org/wiki/Box-drawing_characters
if (opening && countCells++ > 0) {
output.append(CgeoApplication.getInstance().getString(R.string.triple_dash_vertical));
}
}
private void handleTr(final boolean opening, final Editable output) {
// insert new line for each table row
if (opening) {
output.append('\n');
countCells = 0;
}
}
// Ordered lists are handled in a simple manner. They are rendered as Arabic numbers starting at 1
// with no handling for alpha or Roman numbers or arbitrary numbering.
private void handleOl(final boolean opening) {
if (opening) {
listIndex = 1;
listType = ListType.Ordered;
} else {
listType = ListType.Unordered;
}
}
private void handleLi(final boolean opening, final Editable output) {
if (opening) {
if (listType == ListType.Ordered) {
output.append("\n ").append(String.valueOf(listIndex++)).append(". ");
} else {
output.append("\n • ");
}
}
}
private static void handleHr(final boolean opening, final Editable output) {
if (opening) {
// If we are in the middle of a line, add a line feed.
if (output.length() > 0 && output.charAt(output.length() - 1) != '\n') {
output.append('\n');
}
final int start = output.length();
output.append(" ");
output.setSpan(new StrikethroughSpan(), start, output.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
output.append("\n");
}
}
}