'Truncate HTML to a certain number of chars (not counting tags and
comments), or, if words is True, then to a certain number of words.
Close opened tags if they were correctly closed in the given HTML.
Preserve newlines in the HTML.'

def _truncate_html(self, length, truncate, text, truncate_len, words):

    if (words and (length <= 0)):
        return ''
    html4_singlets = ('br', 'col', 'link', 'base', 'img', 'param', 'area', 'hr', 'input')
    pos = 0
    end_text_pos = 0
    current_len = 0
    open_tags = []
    regex = (re_words if words else re_chars)
    while (current_len <= length):
        m = regex.search(text, pos)
        if (not m):
            break
        pos = m.end(0)
        if m.group(1):
            current_len += 1
            if (current_len == truncate_len):
                end_text_pos = pos
            continue
        tag = re_tag.match(m.group(0))
        if ((not tag) or (current_len >= truncate_len)):
            continue
        (closing_tag, tagname, self_closing) = tag.groups()
        tagname = tagname.lower()
        if (self_closing or (tagname in html4_singlets)):
            pass
        elif closing_tag:
            try:
                i = open_tags.index(tagname)
            except ValueError:
                pass
            else:
                open_tags = open_tags[(i + 1):]
        else:
            open_tags.insert(0, tagname)
    if (current_len <= length):
        return text
    out = text[:end_text_pos]
    truncate_text = self.add_truncation_text('', truncate)
    if truncate_text:
        out += truncate_text
    for tag in open_tags:
        out += ('</%s>' % tag)
    return out
