Index: trac/util.py
===================================================================
--- trac/util.py	(revision 938)
+++ trac/util.py	(working copy)
@@ -72,6 +72,17 @@
                .replace('"', '&#34;')
     return text
 
+def unescape(text):
+    """Reverses Escapes &, <, > and \""""
+    if not text:
+        return ''
+    if type(text) is StringType:
+        text = text.replace('&#34;', '"') \
+               .replace('&gt;', '>') \
+               .replace('&lt;', '<') \
+               .replace('&amp;', '&') 
+    return text
+
 def get_first_line(text, maxlen):
     """
     returns the first line of text. If the line is longer then
Index: trac/wikimacros/rst.py
===================================================================
--- trac/wikimacros/rst.py	(revision 938)
+++ trac/wikimacros/rst.py	(working copy)
@@ -43,16 +43,20 @@
     raise EnvironmentError, 'Docutils version >= %s required, %s found' % (docutils_required, __version__)
 
 from trac.Href import Href
+from trac.WikiFormatter import WikiProcessor
 
 __docformat__ = 'reStructuredText'
 
-WIKI_LINK = re.compile(r'(?:wiki:)?(?P<w>[A-Za-z][\w\#\?]*[^\w\#\?]*)') # Links must begin with Letters, \# ? so we can link inside pages.
-#WIKI_LINK = re.compile(r'(?:wiki:)?(?P<w>(^|(?<=[^A-Za-z]))[!]?[A-Z][a-z/]+(?:[A-Z][a-z/]+)+)')
+WIKI_LINK = re.compile(r'(?:wiki:)?(.+)')
+#WIKI_LINK = re.compile(r'(?:wiki:)?(?P<wikilink>[A-Za-z][\w\-]*[^\w\#\?]*)')
 TICKET_LINK = re.compile(r'(?:#(\d+))|(?:ticket:(\d+))')
 REPORT_LINK = re.compile(r'(?:{(\d+)})|(?:report:(\d+))')
 CHANGESET_LINK = re.compile(r'(?:\[(\d+)\])|(?:changeset:(\d+))')
 FILE_LINK = re.compile(r'(?:browser|repos|source):([^#]+)#?(.*)')
 
+#import trac.Logging
+#log = trac.Logging.logger_factory(logtype='file', logfile="/tmp/debug_rst.txt", level='ALL')
+
 def _wikipage(href, args):
     return href.wiki(args[0])
 
@@ -71,29 +75,34 @@
     return href.browser(path, rev)
 
 # TracLink REs and callback functions
-LINKS = [(WIKI_LINK, _wikipage),
-         (TICKET_LINK, _ticket),
+LINKS = [(TICKET_LINK, _ticket),
          (REPORT_LINK, _report),
          (CHANGESET_LINK, _changeset),
-         (FILE_LINK, _browser)]
+         (FILE_LINK, _browser),
+         (WIKI_LINK, _wikipage)]
 
 
-def trac_get_reference(env, rawtext, text):
+def trac_get_reference(env, rawtext, link, text):
+
     for (pattern, function) in LINKS:
-        m = pattern.match(text)
+        m = pattern.match(link)
         if m:
             g = filter(None, m.groups())
             missing = False
+            if not text:
+                text = g[0]
             if pattern == WIKI_LINK:
-                if not (env._wiki_pages.has_key(g[0])):
+                pagename = re.search(r'^[^\#]+',g[0])
+                if not (env._wiki_pages.has_key(pagename.group())):
                         missing = True
-                        text = text + "?"
+                        text = text + "?"            
             uri = function(env.href, g)
             reference = nodes.reference(rawtext, text)
             reference['refuri']= uri
             if missing:
                 reference.set_class('missing')
             return reference
+        
     return None
 
 def trac(env, name, arguments, options, content, lineno,
@@ -119,8 +128,12 @@
 
     .. _TracLink: http://projects.edgewall.com/trac/wiki/TracLinks
     """
-    text = arguments[int(len(arguments) == 2)]
-    reference = trac_get_reference(env, block_text, text)
+    link = arguments[0]
+    if len(arguments) == 2:
+        text = arguments[1]
+    else:
+        text = None
+    reference = trac_get_reference(env, block_text, link, text)
     if reference:
         return reference
     # didn't find a match (invalid TracLink),
@@ -133,7 +146,13 @@
 
 
 def trac_role(env, name, rawtext, text, lineno, inliner, options={}, content=[]):
-    reference = trac_get_reference(env, rawtext, text)
+    args  = text.split(" ",1)
+    link = args[0]
+    if len(args)==2:
+        text = args[1]
+    else:
+        text = None
+    reference = trac_get_reference(env, rawtext, link, text)
     if reference:
         return [reference], []
     warning = nodes.warning(None,
@@ -159,6 +178,27 @@
     rst.roles.register_local_role('trac', do_trac_role)
 
     # The code_block could is taken from the leo plugin rst2
+    def code_formatter(language, text):
+        #log.debug("language '%s' args '%s'", % (language, arguments))
+        Format = WikiProcessor(env, language)
+        html = Format.process(hdf, text)        
+        #log.debug("language '%s' htmltext '%s'" % (language, html))
+        raw = nodes.raw('',html, format='html') #(self, rawsource='', text='', *children, **attributes):
+        return raw
+        
+    def code_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
+        args  = text.split(":",1)
+        language = args[0]
+        if len(args)==2:
+            text = args[1]
+        else:
+            text = ""
+        #log.debug("coderole '%s' text '%s'" % (language, text))
+        reference = code_formatter(language, text)
+        return [reference], []
+        
+
+      
     def code_block(name,arguments,options,content,lineno,content_offset,block_text,state,state_machine):
 
         """Create a code-block directive for docutils.
@@ -166,24 +206,11 @@
         Usage: .. code-block:: language
 
         If the language can be syntax highlighted it will be."""
-
-
-        
-        from trac.WikiFormatter import Formatter
-        
         language = arguments[0]
+        text = '\n'.join(content)        
+        reference = code_formatter(language, text)
+        return [reference]
 
-        code_processor = None
-        if  Formatter.builtin_processors.has_key(language):
-            code_processor = Formatter.builtin_processors[language]
-        else:
-            code_processor = Formatter.builtin_processors['default']
-
-
-        html = code_processor(hdf, '\n'.join(content), env)        
-        raw = nodes.raw('',html, format='html') #(self, rawsource='', text='', *children, **attributes):
-        return [raw]
-
     # These are documented at http://docutils.sourceforge.net/spec/howto/rst-directives.html.
     code_block.arguments = (
         1, # Number of required arguments.
@@ -199,6 +226,7 @@
     code_block.content = 1 # True if content is allowed.
     # Register the directive with docutils.
     rst.directives.register_directive('code-block',code_block)
+    rst.roles.register_local_role('code-block', code_role)
     
     
 
Index: trac/Mimeview.py
===================================================================
--- trac/Mimeview.py	(revision 938)
+++ trac/Mimeview.py	(working copy)
@@ -51,15 +51,15 @@
     'make':'text/x-makefile', 'mk':'text/x-makefile', 'Makefile':'text/x-makefile',
     'mail':'text/x-mail',
     'pas':'text/x-pascal',
-    'pl':'text/x-perl', 'pm':'text/x-perl', 'PL':'text/x-perl',
+    'pl':'text/x-perl', 'pm':'text/x-perl', 'PL':'text/x-perl', 'perl':'text/x-perl',
     'php':'text/x-php', 'php4':'text/x-php', 'php3':'text/x-php',
     'ps':'application/postscript',
     'psp':'text/x-psp',
-    'py':'text/x-python',
+    'py':'text/x-python', 'python':'text/x-python',
     'pyx':'text/x-pyrex',
     'nroff':'application/x-troff', 'roff':'application/x-troff', 'troff':'application/x-troff',
 
-    'rb':'text/x-ruby',
+    'rb':'text/x-ruby', 'ruby':'text/x-ruby',
     'rfc':'text/x-rfc',
     'scm':'text/x-scheme',
     'sh':'application/x-sh',
@@ -68,7 +68,7 @@
     'tex':'text/x-tex',
     'vba':'text/x-vba',
     'bas':'text/x-vba',
-    'v':'text/x-verilog',
+    'v':'text/x-verilog', 'verilog':'text/x-verilog',
     'vhd':'text/x-vhdl',
     'vrml':'model/vrml',
     'wrl':'model/vrml',
Index: trac/WikiFormatter.py
===================================================================
--- trac/WikiFormatter.py	(revision 938)
+++ trac/WikiFormatter.py	(working copy)
@@ -27,10 +27,81 @@
 import StringIO
 
 import util
+import Mimeview
 
-__all__ = ['Formatter', 'OneLinerFormatter', 'wiki_to_html', 'wiki_to_oneliner']
+__all__ = ['Formatter', 'OneLinerFormatter', 'wiki_to_html', 'wiki_to_oneliner', 'WikiProcessor']
 
 
+class WikiProcessor:
+
+    mime_type = ""
+
+    def __init__(self, env, name):
+        self.env = env
+        self.error = self.set_code_processor(name)
+    
+    def default_processor(hdf, text, env):
+        return '<pre class="wiki">' + util.escape(text) + '</pre>'
+    
+    def html_processor(hdf, text, env):
+        if Formatter._htmlproc_disallow_rule.search(text):
+            err = """\
+<div class="system-message">Error: HTML block contains disallowed tags.
+<pre>
+%s</pre>
+</div>""" % util.escape(text)
+            env.log.error(err)
+            return err
+        return text
+
+    def mime_processor(self, hdf, text, env):
+        return env.mimeview.display(text, self.mime_type)
+    
+    builtin_processors = { 'html': html_processor,
+                           'default': default_processor}
+
+    def process(self, hdf, text, inline=False):
+        text = self.code_processor(hdf, text, self.env)
+        if inline:
+            code_block_start = re.compile('^<div class="code-block">')
+            code_block_end = re.compile('</div>$')
+            text, nr = code_block_start.subn('<span class="code-block">', text, 1 )
+            if nr:
+                text, nr = code_block_end.subn('</span>', text, 1 )
+            return text
+        else:
+            return text
+    
+
+    def set_code_processor(self, name):
+        if  self.builtin_processors.has_key(name):
+            self.code_processor = self.builtin_processors[name]
+        else:
+            try:
+                self.code_processor = self.load_macro(name)
+            except Exception, e:
+                if Mimeview.MIME_MAP.has_key(name):
+                    name = Mimeview.MIME_MAP[name]
+                mimeviewer, exists = self.env.mimeview.get_viewer(name)
+                if exists != -1:
+                    self.mime_type = name
+                    self.code_processor = self.mime_processor
+                else:
+                    self.code_processor = self.builtin_processors['default']
+                    return 1
+        return 0
+    
+    def load_macro(self, name):
+        # Look in envdir/wiki-macros/ first
+        try:
+            module = imp.load_source(name, os.path.join(self.env.path, 'wiki-macros', name+'.py'))
+        except IOError:
+            # fall back to site-wide macros
+            macros = __import__('wikimacros.' + name, globals(),  locals(), [])
+            module = getattr(macros, name)
+        return module.execute
+
+
 class CommonFormatter:
     """This class contains the patterns common to both Formatter and
     OneLinerFormatter"""
@@ -240,7 +311,7 @@
     """
     _rules = [r"""(?P<svnimg>(source|repos):([^ ]+)\.(PNG|png|JPG|jpg|JPEG|jpeg|GIF|gif))"""] + \
              CommonFormatter._rules + \
-             [r"""(?P<macro>!?\[\[(?P<macroname>[a-zA-Z]+)(\((?P<macroargs>[^\)]*)\))?\]\])""",
+             [r"""(?P<macro>!?\[\[(?P<macroname>[\w/+-]+)(\]\]|\((?P<macroargs>.*?)\)\]\]))""",
               r"""(?P<heading>^\s*(?P<hdepth>=+)\s.*\s(?P=hdepth)\s*$)""",
               r"""(?P<list>^(?P<ldepth>\s+)(?:\*|[0-9]+\.) )""",
               r"""(?P<indent>^(?P<idepth>\s+)(?=\S))""",
@@ -250,8 +321,7 @@
               r"""(?P<table_cell>\|\|)"""]
 
     _compiled_rules = re.compile('(?:' + string.join(_rules, '|') + ')')
-    _processor_re = re.compile('#\!([a-zA-Z0-9/+-]+)')
-    mime_type = ""
+    _processor_re = re.compile('#\!([\w/+-]+)')
     
 
     # RE patterns used by other patterna
@@ -261,78 +331,15 @@
 
     _htmlproc_disallow_rule = re.compile('(?i)<(script|noscript|embed|object|iframe|frame|frameset|link|style|meta|param|doctype)')
 
-    def default_processor(hdf, text, env):
-        return '<pre class="wiki">' + util.escape(text) + '</pre>'
-    def asp_processor(hdf, text, env):
-        return env.mimeview.display(text, 'text/x-asp')
-    def c_processor(hdf, text, env):
-        return env.mimeview.display(text, 'text/x-csrc')
-    def css_processor(hdf, text, env):
-        return env.mimeview.display(text, 'text/css')
-    def java_processor(hdf, text, env):
-        return env.mimeview.display(text, 'text/x-java')
-    def cpp_processor(hdf, text, env):
-        return env.mimeview.display(text, 'text/x-c++src')
-    def perl_processor(hdf, text, env):
-        return env.mimeview.display(text, 'text/x-perl')
-    def php_processor(hdf, text, env):
-        return env.mimeview.display(text, 'text/x-php')
-    def python_processor(hdf, text, env):
-        return env.mimeview.display(text, 'text/x-python')
-    def ruby_processor(hdf, text, env):
-        return env.mimeview.display(text, 'text/x-ruby')
-    def sql_processor(hdf, text, env):
-        return env.mimeview.display(text, 'text/x-sql')
-    def xml_processor(hdf, text, env):
-        return env.mimeview.display(text, 'text/xml')
-    def verilog_processor(hdf, text, env):
-        return env.mimeview.display(text, 'text/x-verilog')
-    def html_processor(hdf, text, env):
-        if Formatter._htmlproc_disallow_rule.search(text):
-            err = """\
-<div class="system-message">Error: HTML block contains disallowed tags.
-<pre>
-%s</pre>
-</div>""" % util.escape(text)
-            env.log.error(err)
-            return err
-        return text
-    def mime_processor(self, hdf, text, env):
-        return env.mimeview.display(text, self.mime_type)
-
-    builtin_processors = { 'html': html_processor,
-                           'asp': asp_processor,
-                           'c': c_processor,
-                           'css': css_processor,
-                           'cpp': cpp_processor,
-                           'java': java_processor,
-                           'php': php_processor,
-                           'perl': perl_processor,
-                           'python': python_processor,
-                           'ruby': ruby_processor,
-                           'sql': sql_processor,
-                           'xml': xml_processor,
-                           'verilog': verilog_processor,
-                           'default': default_processor}
-
-    def load_macro(self, name):
-        # Look in envdir/wiki-macros/ first
-        try:
-            module = imp.load_source(name, os.path.join(self.env.path, 'wiki-macros', name+'.py'))
-        except IOError:
-            # fall back to site-wide macros
-            macros = __import__('wikimacros.' + name, globals(),  locals(), [])
-            module = getattr(macros, name)
-        return module.execute
-
     def _macro_formatter(self, match, fullmatch):
         name = fullmatch.group('macroname')
         if name in ['br', 'BR']:
             return '<br />'
         args = fullmatch.group('macroargs')
+        args = util.unescape(args)
         try:
-            macro = self.load_macro(name)
-            return macro(self.hdf, args, self.env)
+            macro = WikiProcessor(self.env, name)
+            return macro.process(self.hdf, args, True)
         except Exception, e:
             return '<div class="system-message">Macro %s(%s) failed: %s</div>' \
                    % (name, args, e)
@@ -474,39 +481,30 @@
             else:
                 self.code_text += line + os.linesep
                 if not self.code_processor:
-                    self.code_processor = Formatter.builtin_processors['default']
+                    self.code_processor =  WikiProcessor(self.env, 'default')
         elif line.strip() == '}}}':
             self.in_code_block -= 1
             if self.in_code_block == 0 and self.code_processor:
                 self.close_paragraph()
                 self.close_table()
-                self.out.write(self.code_processor(self.hdf, self.code_text, self.env))
+                self.out.write(self.code_processor.process(self.hdf, self.code_text))
             else:
                 self.code_text += line + os.linesep
         elif not self.code_processor:
             match = Formatter._processor_re.search(line)
             if match:
                 name = match.group(1)
-                if  Formatter.builtin_processors.has_key(name):
-                    self.code_processor = Formatter.builtin_processors[name]
-                else:
-                    try:
-                        self.code_processor = self.load_macro(name)
-                    except Exception, e:
-                        mimeviewer, exists = self.env.mimeview.get_viewer(name)
-                        if exists != -1:
-                            self.mime_type = name
-                            self.code_processor = self.mime_processor
-                        else:
-                            self.code_text += line + os.linesep
-                            self.code_processor = Formatter.builtin_processors['default']
-                            self.out.write('<div class="system-message">Failed to load processor macro %s: %s t %s</div>' % (name, line, e))
+                self.code_processor = WikiProcessor(self.env, name)
+                if self.code_processor.error:
+                    self.out.write("<div class='system-message'>Failed to load processor macro '%s': '%s' '%s'</div>" % (name, line, e))
+                    self.code_text += line + os.linesep
             else:
                 self.code_text += line + os.linesep 
-                self.code_processor = Formatter.builtin_processors['default']
+                self.code_processor =  WikiProcessor(self.env, 'default')           
         else:
             self.code_text += line + os.linesep
 
+
     def format(self, text, out):
         self.out = out
         self._open_tags = []
Index: trac/tests/wiki.py
===================================================================
--- trac/tests/wiki.py	(revision 938)
+++ trac/tests/wiki.py	(working copy)
@@ -4,6 +4,7 @@
 
 from Wiki import Formatter
 
+
 class WikiTestCase(unittest.TestCase):
     def __init__(self, input, correct):
         unittest.TestCase.__init__(self, 'test')
@@ -13,10 +14,12 @@
     def test(self):
         """Testing WikiFormatter"""
         import Href
+        import Mimeview
         class Environment:
             def __init__(self):
                 self.href = Href.Href('/')
                 self._wiki_pages = {}
+                self.mimeview = Mimeview.Mimeview(self)
         class Cursor:
             def execute(self, *kwargs): pass
             def fetchone(self): return []
@@ -28,7 +31,7 @@
         out = StringIO.StringIO()
         Formatter(None, Environment(), Connection()).format(self.input, out)
         if out.getvalue() != self.correct:
-            print "'%s' != '%s'" % (out.getvalue(), self.correct)
+            print "\n'%s' != \n'%s'" % (out.getvalue(), self.correct)
             assert self.correct == out.getvalue()
 
 def suite():
