def __handleOtherLines(self):
        out = ""
        line = self.__diff.getCurrentLine()

        m1 = re.match(r"^Property changes on: (.*)", line)
        if m1 and (not m1.group(1) in self.__seen or self.__seen[m1.group(1)] <= 0):
            out += self.__handlePropertyChange(m1)
        elif re.match(r"^\@\@", line):
            if self.__inSpan:
                out += self.__inSpan.getCloseTag()
            spanTag = HtmlTag("span")
            spanTag.addClass("lines")
            spanTag.setText(self.html_escape(line) + "\n")
            out += spanTag.toHtml(TagMode.CLOSED)
            self.__inSpan = None
        else:
            m2 = re.match(r"^([-+])", line)
            if m2:
                out += self.__handleDiff(m2)
            else:
                if self.__inSpan == "cx":
                    out += self.html_escape(line) + "\n"
                else:
                    if self.__inSpan:
                        out += self.__inSpan.getCloseTag()
                    spanTag = HtmlTag("span")
                    spanTag.addClass("cx")
                    spanTag.setText(self.html_escape(line) + "\n")
                    out += spanTag.toHtml()
                    self.__inSpan = HtmlTag("span")

        return out
    def __handleBinaryDiff(self, line, html_id, action, filename):
        out = ""

        tag = HtmlTag("a", html_id)
        out += tag.toHtml(TagMode.CLOSED) + "\n"

        tag = HtmlTag("div")
        tag.addClass("binary")
        out += tag.toHtml()

        tag = HtmlTag("h4")
        tag.setText(action + ": " + filename)
        out += tag.toHtml(TagMode.CLOSED) + "\n"

        tag = HtmlTag("pre")
        tag.addClass("diff")
        out += tag.toHtml() + HtmlTag("span").toHtml() + "\n"

        tag = HtmlTag("span")
        tag.addClass("cx")
        tag.setText(line + "\n")
        out += tag.toHtml(TagMode.CLOSED)

        out += HtmlTag.printCloseTag("span") + HtmlTag.printCloseTag("span")
        out += HtmlTag.printCloseTag("pre") + HtmlTag.printCloseTag("div") + "\n"

        self.__inSpan = None
        self.__inDiv = False
        self.__diff.goToNextLine()

        return out
    def __handleNoDiffAttached(self, html_id, theClass, action, filename):
        out = ""

        self.__inSpan = None
        self.__inDiv = False
        tag = HtmlTag("a", html_id)
        out += tag.toHtml(TagMode.CLOSED) + "\n"

        tag = HtmlTag("div")
        tag.addClass(theClass)
        out += tag.toHtml()

        tag = HtmlTag("h4")
        tag.setText(action + ": " + filename)
        out += tag.toHtml(TagMode.CLOSED)
        out += HtmlTag.printCloseTag("div") + "\n"
        self.__diff.goToNextLine()

        return out
    def output_file_lists(self):
        out = ""
        while not self.__fileChanges.isEndReached():
            line = self.__fileChanges.cleanCurrentLine()
            m = re.match("^(.)(.).+", line)
            if m:
                filename = re.sub("^(.)(.)\s+", "", line)
                self.__files[m.group(1)].append(filename)
                if m.group(2) != " " and m.group(1) != "_":
                    self.__files["_"].append(filename)
            self.__fileChanges.goToNextLine()

        for t in ["U", "A", "D", "_"]:
            if not self.__files[t]:
                continue

            tag = HtmlTag("h3")
            tag.setText(self.__changeCodes[t])
            out += tag.toHtml(TagMode.CLOSED) + "\n" + HtmlTag("ul").toHtml() + "\n"
            for filename in self.__files[t]:
                f = self.html_escape(filename)
                if f.endswith("/") and t != "_":
                    # Directories don't link, unless it's a prop change
                    li = HtmlTag("li")
                    li.setText(f)
                    out += li.toHtml(TagMode.CLOSED) + "\n"
                else:
                    html_id = re.sub(r"[^\w_]", r"", f)
                    aTag = HtmlTag("a")
                    aTag.setText(f)
                    aTag.addAttribute("href", "#" + html_id)
                    li = HtmlTag("li")
                    li.setInnerHtml(aTag.toHtml(TagMode.CLOSED))
                    out += li.toHtml(TagMode.CLOSED) + "\n"

            out += "</ul>\n\n"

        return out
    def __closeAfterMaxLength(self):
        out = ""

        if self.__inSpan:
            out += self.__inSpan.getCloseTag()

        tag = HtmlTag("span")
        tag.addClass("lines")
        tag.setText("@@ Diff output truncated at " + str(self.max_length) + " characters. @@\n")
        out += tag.toHtml(TagMode.CLOSED)

        self.__inSpan = None

        return out
    def output_formatted_diff(self):
        length = 0

        tag = HtmlTag("h3")
        tag.setText("Diff")
        divTag = HtmlTag("div", "patch")
        divTag.setInnerHtml("\n" + tag.toHtml(TagMode.CLOSED))
        out = divTag.toHtml() + "\n"

        self.__diff.resetCurrentLine()
        while not self.__diff.isEndReached():
            line = self.__diff.cleanCurrentLine()
            if not line:
                self.__diff.goToNextLine()
                continue

            length += len(line)
            if self.__isMaxLengthReached(length):
                out += self.__closeAfterMaxLength()
                break

            if self.__diff.isFileChangeLine():
                out += self.__handleFileChange()
            else:
                out += self.__handleOtherLines()

            self.__diff.goToNextLine()

        if self.__inSpan:
            out += self.__inSpan.getCloseTag()
        if self.__inDiv:
            out += HtmlTag.printCloseTag("span")
            out += HtmlTag.printCloseTag("pre") + "\n"
            out += HtmlTag.printCloseTag("div") + "\n"
        out += HtmlTag.printCloseTag("div") + "\n"

        return out
    def __handleFileChange(self):
        out = ""

        m = self.__diff.isFileChangeLine()
        action = m.group(1)
        theClass = self.__types[action]
        if m.group(2) in self.__seen:
            self.__seen[m.group(2)] += 1
        else:
            self.__seen[m.group(2)] = 1

        filename = self.html_escape(m.group(2))
        html_id = re.sub(r"[^\w_]", r"", filename)

        if self.__inSpan:
            out += self.__inSpan.getCloseTag()
        if self.__inDiv:
            out += HtmlTag.printCloseTag("span")
            out += HtmlTag.printCloseTag("pre")
            out += HtmlTag.printCloseTag("div") + "\n"

            # Dump line, but check it's content.
        self.__diff.goToNextLine()
        line = self.__diff.getCurrentLine()
        if not self.__diff.hasDiffAttached(line):
            # Looks like they used --no-diff-added or --no-diff-deleted.
            out += self.__handleNoDiffAttached(html_id, theClass, action, filename)
            return out

        self.__diff.goToNextLine()
        before = self.__diff.cleanCurrentLine()

        if self.__diff.isBinaryDiffLine(before):
            # Just output the whole filename div.
            out += self.__handleBinaryDiff(before, html_id, action, filename)
            return out

        rev1 = self.__getRevision(before)
        self.__diff.goToNextLine()
        after = self.__diff.cleanCurrentLine()
        rev2 = self.__getRevision(after)

        # Output the headers.
        tag = HtmlTag("a", html_id)
        out += tag.toHtml(TagMode.CLOSED) + "\n"

        tag = HtmlTag("div")
        tag.addClass(theClass)
        out += tag.toHtml()

        tag = HtmlTag("h4")
        tag.setText(action + ": " + filename + " (" + rev1 + " => " + rev2 + ")")
        out += tag.toHtml(TagMode.CLOSED) + "\n"

        tag = HtmlTag("pre")
        tag.addClass("diff")
        out += tag.toHtml() + HtmlTag("span").toHtml() + "\n"

        tag = HtmlTag("span")
        tag.addClass("info")
        out += tag.toHtml()

        self.__inDiv = True
        out += self.html_escape(before) + "\n"
        out += self.html_escape(after) + "\n"
        out += HtmlTag.printCloseTag("span")
        self.__inSpan = None

        return out