home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 June / maximum-cd-2009-06.iso / DiscContents / digsby_setup.exe / lib / util / rtf.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-02-26  |  11.2 KB  |  396 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. import string
  5. import itertools
  6. symbols = {
  7.     '\\': '\\',
  8.     '~': ' ',
  9.     'tab': '\t',
  10.     "'7b": '{',
  11.     "'7d": '}' }
  12. rev_symbols = { }
  13. for k, v in symbols.items():
  14.     rev_symbols[v] = k
  15.  
  16. rtf_fcharsets = {
  17.     0: 'ANSI',
  18.     1: 'Default',
  19.     2: 'Symbol',
  20.     3: 'Invalid',
  21.     77: 'Mac',
  22.     128: 'shiftjis',
  23.     130: 'johab',
  24.     134: 'GB2312',
  25.     136: 'Big5',
  26.     161: 'Greek',
  27.     162: 'iso-8859-9',
  28.     163: 'cp1258',
  29.     177: 'Hebrew',
  30.     178: 'Arabic',
  31.     179: 'Arabic Traditional',
  32.     180: 'Arabic user',
  33.     181: 'Hebrew user',
  34.     186: 'Baltic',
  35.     204: 'Russian',
  36.     222: 'Thai',
  37.     238: 'Eastern European',
  38.     254: 'PC 437',
  39.     255: 'OEM' }
  40.  
  41. def tokenize(string):
  42.     tokens = []
  43.     curr_token = ''
  44.     for c in string:
  45.         if c in '\\{} \r\n':
  46.             if curr_token:
  47.                 tokens.append(curr_token)
  48.                 curr_token = ''
  49.             
  50.             if c == '\n' and tokens[-1] == '\r':
  51.                 tokens[-1] = c
  52.             else:
  53.                 tokens.append(c)
  54.         tokens[-1] == '\r'
  55.         curr_token += c
  56.     
  57.     if curr_token:
  58.         tokens.append(curr_token)
  59.     
  60.     return tokens
  61.  
  62.  
  63. class TypedString(str):
  64.     
  65.     def __repr__(self):
  66.         return '<%s %s>' % (type(self).__name__, str.__repr__(self))
  67.  
  68.  
  69.  
  70. class TypedList(list):
  71.     
  72.     def __repr__(self):
  73.         return '<%s %s>' % (type(self).__name__, list.__repr__(self))
  74.  
  75.  
  76.  
  77. class ControlNode(TypedString):
  78.     pass
  79.  
  80.  
  81. class TextNode(TypedString):
  82.     pass
  83.  
  84.  
  85. class WhitespaceNode(TypedString):
  86.     pass
  87.  
  88.  
  89. class Group(TypedList):
  90.     pass
  91.  
  92.  
  93. def compress_text(doc):
  94.     new = Group()
  95.     cur_text = []
  96.     while doc:
  97.         node = doc.pop(0)
  98.         if type(node) is WhitespaceNode:
  99.             if cur_text:
  100.                 cur_text.append(node)
  101.             
  102.         cur_text
  103.         if type(node) is TextNode:
  104.             cur_text.append(node)
  105.             continue
  106.         if type(node) is Group:
  107.             if cur_text:
  108.                 new.append(TextNode(''.join(cur_text)))
  109.             
  110.             new.append(compress_text(node))
  111.             continue
  112.     return new
  113.  
  114.  
  115. def parse(tokens):
  116.     doc = None
  117.     while tokens:
  118.         token = tokens.pop(0)
  119.         if token == '{':
  120.             if doc is None:
  121.                 doc = Group()
  122.             else:
  123.                 tokens.insert(0, '{')
  124.                 doc.append(parse(tokens))
  125.         doc is None
  126.         if token == '}':
  127.             return doc
  128.             continue
  129.         if token == '\\':
  130.             next = tokens.pop(0)
  131.             if len(next) == 1 and next not in string.ascii_letters + string.digits:
  132.                 doc.append(TextNode(symbols.get(next, next)))
  133.             elif next.startswith("'"):
  134.                 hexchar = next[1:3]
  135.                 tokens.insert(0, next[3:])
  136.                 doc.append(TextNode(chr(int(hexchar, 16))))
  137.             else:
  138.                 doc.append(ControlNode(token + next))
  139.         next not in string.ascii_letters + string.digits
  140.         if token in string.whitespace:
  141.             last = doc[-1]
  142.             if type(last) is WhitespaceNode:
  143.                 doc[-1] = WhitespaceNode(last + token)
  144.             else:
  145.                 doc.append(WhitespaceNode(token))
  146.         type(last) is WhitespaceNode
  147.         last = doc[-1]
  148.         if type(last) is TextNode:
  149.             doc[-1] = TextNode(last + token)
  150.             continue
  151.         doc.append(TextNode(token))
  152.     doc = compress_text(doc)
  153.     return doc
  154.  
  155.  
  156. def tree_to_plain(tree):
  157.     tree = tree[:]
  158.     if not tree:
  159.         return ''
  160.     
  161.     if type(tree[0]) is ControlNode and str(tree[0]) in ('\\colortbl', '\\fonttbl'):
  162.         return ''
  163.     
  164.     res = []
  165.     encoding = None
  166.     last = None
  167.     uni_replace_len = None
  168.     while tree:
  169.         node = tree.pop(0)
  170.         if type(node) is Group:
  171.             res.append(tree_to_plain(node))
  172.         
  173.         if type(node) is TextNode:
  174.             s = str(node)
  175.             if encoding is not None:
  176.                 s = s.decode(encoding)
  177.             
  178.             res.append(s)
  179.         
  180.         if type(node) is WhitespaceNode:
  181.             s = str(node)
  182.             if type(last) in (ControlNode, Group):
  183.                 s = s[1:]
  184.             
  185.             res.append(s)
  186.         
  187.         if type(node) is ControlNode:
  188.             if str(node) == '\\par':
  189.                 res.append('\n')
  190.             elif str(node).startswith('\\ansicpg'):
  191.                 
  192.                 try:
  193.                     codepage = int(str(node)[len('\\ansicpg'):].strip())
  194.                 except (ValueError, IndexError):
  195.                     e = None
  196.  
  197.                 encoding = 'cp%d' % codepage
  198.             elif str(node).startswith('\\u') and str(node)[2] in '-' + string.digits:
  199.                 if tree:
  200.                     put_back = True
  201.                     replacement_charnode = tree.pop(0)
  202.                 else:
  203.                     put_back = False
  204.                     replacement_charnode = TextNode('')
  205.                 if type(replacement_char) is not TextNode:
  206.                     if put_back:
  207.                         tree.insert(0, replacement_charnode)
  208.                     
  209.                     replacement_char = ' '
  210.                 else:
  211.                     replacement_char = str(replacement_charnode)
  212.                     if uni_replace_len is not None:
  213.                         if len(replacement_char) > uni_replace_len:
  214.                             replacement_char = replacement_char[uni_replace_len:]
  215.                             rest = replacement_char[:uni_replace_len]
  216.                             if rest:
  217.                                 tree.insert(0, TextNode(rest))
  218.                             
  219.                         
  220.                     
  221.                 
  222.                 try:
  223.                     val = int(str(node)[2:])
  224.                 except ValueError:
  225.                     val = ord(replacement_char)
  226.  
  227.                 val = abs(val) + (val < 0) * 32767
  228.                 
  229.                 try:
  230.                     res.append(unichr(val))
  231.                 except ValueError:
  232.                     res.append(replacement_char)
  233.                 except:
  234.                     None<EXCEPTION MATCH>ValueError
  235.                 
  236.  
  237.             None<EXCEPTION MATCH>ValueError
  238.         
  239.         last = node
  240.     final = ''.join(res)
  241.     return final
  242.  
  243.  
  244. def rtf_to_plain(s):
  245.     return tree_to_plain(parse(tokenize(s)))
  246.  
  247.  
  248. def make_color_table(colors):
  249.     table = Group()
  250.     table.append(ControlNode('\\colortbl'))
  251.     table.append(TextNode(';'))
  252.     for color in colors:
  253.         (r, g, b, a) = tuple(color)
  254.         table.extend((ControlNode('\\red%d' % r), ControlNode('\\green%d' % g), ControlNode('\\blue%d' % b), TextNode(';')))
  255.     
  256.     return table
  257.  
  258.  
  259. def normalize_font_family(family):
  260.     family = family.lower()
  261.     if family not in set(('nil', 'roman', 'swiss', 'modern', 'script', 'decor', 'tech')):
  262.         return 'nil'
  263.     
  264.     return family
  265.  
  266.  
  267. def make_font_table(fonts):
  268.     table = Group()
  269.     table.append(ControlNode('\\fonttbl'))
  270.     for family, font in enumerate(fonts):
  271.         table.extend((ControlNode('\\f%d' % i), ControlNode('\\' + normalize_font_family(family)), TextNode(' ' + font + ';')))
  272.     
  273.     return table
  274.  
  275.  
  276. def storage_to_tree(s):
  277.     if s.get('backgrouncolor') and s.get('foregroundcolor'):
  278.         color_table = make_color_table([
  279.             s.backgroundcolor,
  280.             s.foregroundcolor])
  281.     else:
  282.         color_table = TextNode('')
  283.     if s.get('family') and s.get('font'):
  284.         font_table = make_font_table([
  285.             (s.family, s.font)])
  286.     else:
  287.         font_table = TextNode('')
  288.     top_level = Group([
  289.         ControlNode('\\rtf1'),
  290.         ControlNode('\\ansi'),
  291.         ControlNode('\\uc1'),
  292.         color_table,
  293.         font_table])
  294.     format_group = Group([])
  295.     if font_table:
  296.         format_group.append(ControlWord('\\f1'))
  297.     
  298.     if color_table:
  299.         format_group.append(ControlWord('\\cb1'))
  300.         format_group.append(ControlWord('\\cf2'))
  301.     
  302.     if s.get('bold'):
  303.         format_group.append(ControlWord('\\b'))
  304.     
  305.     if s.get('italic'):
  306.         format_group.append(ControlWord('\\i'))
  307.     
  308.     if s.get('underline'):
  309.         format_group.append(ControlWord('\\ul'))
  310.     
  311.     if s.get('size'):
  312.         format_group.append(ControlWord('\\fs%d' % s.size * 2))
  313.     
  314.     top_level.append(format_group)
  315.     return (top_level, format_group.append)
  316.  
  317.  
  318. def storage_to_rtf(s, text):
  319.     escaped = rtf_escape(text)
  320.     (doc, add_text) = storage_to_tree(s)
  321.     add_text(escaped)
  322.     return tree_to_rtf(doc)
  323.  
  324.  
  325. def rtf_escape(node):
  326.     if isinstance(node, unicode):
  327.         s = unicode(node)
  328.         
  329.         try:
  330.             s = s.encode('ascii')
  331.         except UnicodeEncodeError:
  332.             pass
  333.         except:
  334.             None<EXCEPTION MATCH>UnicodeEncodeError
  335.         
  336.  
  337.     None<EXCEPTION MATCH>UnicodeEncodeError
  338.     s = str(node)
  339.     return ''.join((lambda .0: for c in .0:
  340. rtf_escape_chr(c))(s))
  341.  
  342.  
  343. def rtf_escape_chr(c):
  344.     if c in rev_symbols:
  345.         return '\\' + rev_symbols[c]
  346.     elif isinstance(c, unicode):
  347.         val = ord(c)
  348.         (negate, val) = divmod(val, 32767)
  349.         if negate:
  350.             val = -abs(val)
  351.         
  352.         return '\\u%d ?' % val
  353.     elif ord(c) > 127 and isinstance(c, str):
  354.         return "\\'%x" % ord(c)
  355.     else:
  356.         return str(c)
  357.  
  358.  
  359. def tree_to_rtf(tree):
  360.     res = []
  361.     res.append('{')
  362.     for node in tree:
  363.         t = type(node)
  364.         if t is Group:
  365.             res.append(tree_to_rtf(node))
  366.             continue
  367.         if t is TextNode:
  368.             res.append(rtf_escape(node))
  369.             continue
  370.         res.append(str(node))
  371.     
  372.     res.append('}')
  373.     return ''.join(res)
  374.  
  375.  
  376. def main():
  377.     for test_string, test_plain in (('{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fonttbl{\\f0\\fmodern\\fprq1\\fcharset0 Courier New;}}{\\colortbl ;\\red0\\green255\\blue64;}\\viewkind4\\uc1\\pard\\cf1\\b\\f0\\fs32 this is the body\\par}', 'this is the body\n'), ('{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fonttbl{\\f0\\fswiss\\fcharset0 Arial;}{\\f1\\froman\\fprq2\\fcharset0 Bodoni;}}\\viewkind4\\uc1\\pard\\i\\f0\\fs20      first line\\par\\b second line\\par\\ul\\i0 third line\\par\\b0 fourth line\\par\\ulnone\\b bold\\par\\f1 newfont\\ul\\b0\\f0\\par}', '     first line\nsecond line\nthird line\nfourth line\nbold\nnewfont\n'), ('{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fonttbl{\\f0\\fmodern\\fprq1\\fcharset0 Courier New;}}\n{\\colortbl ;\\red0\\green255\\blue64;}\n\\viewkind4\\uc1\\pard\\cf1\\b\\f0\\fs32 newline\\par\nbackslash\\\\ rawr end\\par\n}', 'newline\nbackslash\\ rawr end\n')):
  378.         parsed = parse(tokenize(test_string))
  379.         plain = tree_to_plain(parsed)
  380.         print plain
  381.         if not test_plain == plain:
  382.             print repr(test_plain)
  383.             print repr(plain)
  384.             print 
  385.         
  386.         if not test_string == tree_to_rtf(parsed):
  387.             print repr(test_string)
  388.             print repr(tree_to_rtf(parsed))
  389.             print 
  390.             continue
  391.     
  392.  
  393. if __name__ == '__main__':
  394.     print main()
  395.  
  396.