Index: trac/attachment.py
===================================================================
--- trac/attachment.py	(revision 7596)
+++ trac/attachment.py	(working copy)
@@ -42,7 +42,7 @@
                             INavigationContributor
 from trac.web.href import Href
 from trac.wiki.api import IWikiSyntaxProvider
-from trac.wiki.formatter import format_to_oneliner
+from trac.wiki.formatter import format_to
 
 
 class InvalidAttachment(TracError):
@@ -464,7 +464,7 @@
             if 'ATTACHMENT_VIEW' in req.perm(attachment):
                 yield ('attachment', time, author, (attachment, descr), self)
 
-    def render_timeline_event(self, context, field, event):
+    def render_timeline_event(self, context, field, event, abbreviated=None):
         attachment, descr = event[3]
         if field == 'url':
             return self.get_resource_url(attachment, context.href)
@@ -474,8 +474,13 @@
             return tag(tag.em(os.path.basename(attachment.id)),
                        _(" attached to "), tag.em(name, title=title))
         elif field == 'description':
-            return format_to_oneliner(self.env, context(attachment.parent),
-                                      descr)
+            if abbreviated is None:
+                abbreviated = self.config['timeline'] \
+                        .getbool('abbreviated_messages')
+            flavor, options = (('html', {}), 
+                               ('oneliner', {'shorten': True}))[abbreviated]
+            return format_to(self.env, flavor, context(attachment.parent),
+                             descr, **options)
    
     def get_search_results(self, req, resource_realm, terms):
         """Return a search result generator suitable for ISearchSource.
Index: trac/ticket/web_ui.py
===================================================================
--- trac/ticket/web_ui.py	(revision 7596)
+++ trac/ticket/web_ui.py	(working copy)
@@ -125,6 +125,13 @@
         but keeps the old behavior for upgraded environments (i.e. 'no').
         (''since 0.11'').""")
 
+    def _must_preserve_newlines(self):
+        preserve_newlines = self.preserve_newlines
+        if preserve_newlines == 'default':
+            preserve_newlines = self.env.get_version(initial=True) >= 21 # 0.11
+        return preserve_newlines in _TRUE_VALUES
+    must_preserve_newlines = property(_must_preserve_newlines)
+
     # IContentConverter methods
 
     def get_supported_conversions(self):
@@ -322,7 +329,7 @@
                     req, ticket_realm, start, stop):
                     yield event
 
-    def render_timeline_event(self, context, field, event):
+    def render_timeline_event(self, context, field, event, abbreviated=None):
         ticket, verb, info, summary, status, resolution, type, \
                 description, comment, cid = event[3]
         if field == 'url':
@@ -339,16 +346,23 @@
             descr = message = ''
             if status == 'new':
                 message = description
-                flavor = self.timeline_newticket_formatter
             else:
                 descr = info
                 message = comment
+            flavor = 'html'
+            options = {'escape_newlines': self.must_preserve_newlines}
+            if abbreviated is None:
+                if status == 'new': 
+                    flavor = self.timeline_newticket_formatter
+                else:
+                    abbreviated = self.config['timeline'] \
+                        .getbool('abbreviated_messages')
+            if abbreviated:
                 flavor = 'oneliner'
-            if message:
-                if self.config['timeline'].getbool('abbreviated_messages'):
-                    message = shorten_line(message)
-                descr += format_to(self.env, flavor, context(resource=ticket),
-                                   message)
+            if flavor == 'oneliner': # may come from newticket_formatter
+                options = {'shorten': True}
+            descr += format_to(self.env, flavor, context(resource=ticket),
+                               message, **options)
             return descr
 
     # Internal methods
@@ -578,14 +592,10 @@
         return 'ticket.html', data, None
 
     def _prepare_data(self, req, ticket, absurls=False):
-        preserve_newlines = self.preserve_newlines
-        if preserve_newlines == 'default':
-            preserve_newlines = self.env.get_version(initial=True) >= 21 # 0.11
-        preserve_newlines = preserve_newlines in _TRUE_VALUES
         return {'ticket': ticket,
                 'context': Context.from_request(req, ticket.resource,
                                                 absurls=absurls),
-                'preserve_newlines': preserve_newlines}
+                'preserve_newlines': self.must_preserve_newlines}
 
     def _toggle_cc(self, req, cc):
         """Return an (action, recipient) tuple corresponding to a change
Index: trac/ticket/roadmap.py
===================================================================
--- trac/ticket/roadmap.py	(revision 7596)
+++ trac/ticket/roadmap.py	(working copy)
@@ -42,7 +42,7 @@
 from trac.web.chrome import add_link, add_stylesheet, add_warning, \
                             INavigationContributor
 from trac.wiki.api import IWikiSyntaxProvider
-from trac.wiki.formatter import format_to_html
+from trac.wiki.formatter import format_to
 
 class ITicketGroupStatsProvider(Interface):
     def get_ticket_group_stats(ticket_ids):
@@ -525,15 +525,20 @@
                 req, milestone_realm, start, stop):
                 yield event
                 
-    def render_timeline_event(self, context, field, event):
+    def render_timeline_event(self, context, field, event, abbreviated=None):
         milestone, description = event[3]
         if field == 'url':
             return context.href.milestone(milestone.id)
         elif field == 'title':
             return tag('Milestone ', tag.em(milestone.id), ' completed')
         elif field == 'description':
-            return format_to_html(self.env, context(resource=milestone),
-                                  shorten_line(description))
+            if abbreviated is None:
+                abbreviated = self.config['timeline'] \
+                        .getbool('abbreviated_messages')
+            flavor, options = (('html', {}), 
+                               ('oneliner', {'shorten': True}))[abbreviated]
+            return format_to(self.env, flavor, context(resource=milestone),
+                             description, **options)
 
     # IRequestHandler methods
 
Index: trac/versioncontrol/web_ui/changeset.py
===================================================================
--- trac/versioncontrol/web_ui/changeset.py	(revision 7596)
+++ trac/versioncontrol/web_ui/changeset.py	(working copy)
@@ -47,7 +47,7 @@
 from trac.web.chrome import add_ctxtnav, add_link, add_script, add_stylesheet, \
                             prevnext_nav, INavigationContributor, Chrome
 from trac.wiki import IWikiSyntaxProvider, WikiParser
-from trac.wiki.formatter import format_to_html
+from trac.wiki.formatter import format_to
 
 
 class IPropertyDiffRenderer(Interface):
@@ -813,7 +813,7 @@
                            (permitted_changesets, chgset.message or '',
                             show_location, show_files))
 
-    def render_timeline_event(self, context, field, event):
+    def render_timeline_event(self, context, field, event, abbreviated=None):
         changesets, message, show_location, show_files = event[3]
         rev_b, rev_a = changesets[0].rev, changesets[-1].rev
         
@@ -824,8 +824,10 @@
                 return context.href.log(rev=rev_b, stop_rev=rev_a)
             
         elif field == 'description':
-            if not self.timeline_long_messages:
-                message = shorten_line(message)
+            if abbreviated is None:
+                abbreviated = not self.timeline_long_messages
+            flavor, options = (('html', {'escape_newlines': True}), 
+                               ('oneliner', {'shorten': True}))[abbreviated]
             if self.wiki_format_messages:
                 markup = ''
             else:
@@ -861,7 +863,8 @@
                         files = files[:show_files] + [tag.li(u'\u2026')]
                     markup = tag(tag.ul(files, class_="changes"), markup)
             if message:
-                markup += format_to_html(self.env, context, message)
+                markup += format_to(self.env, flavor, context, message, 
+                                    **options)
             return markup
 
         if rev_a == rev_b:
Index: trac/wiki/web_ui.py
===================================================================
--- trac/wiki/web_ui.py	(revision 7596)
+++ trac/wiki/web_ui.py	(working copy)
@@ -41,7 +41,7 @@
                             INavigationContributor, ITemplateProvider
 from trac.web import IRequestHandler
 from trac.wiki.api import IWikiPageManipulator, WikiSystem
-from trac.wiki.formatter import format_to_oneliner
+from trac.wiki.formatter import format_to
 from trac.wiki.model import WikiPage
  
 class InvalidWikiPage(TracError):
@@ -592,7 +592,7 @@
                 req, wiki_realm, start, stop):
                 yield event
 
-    def render_timeline_event(self, context, field, event):
+    def render_timeline_event(self, context, field, event, abbreviated=None):
         wiki_page, comment = event[3]
         if field == 'url':
             return context.href.wiki(wiki_page.id, version=wiki_page.version)
@@ -600,10 +600,13 @@
             return tag(tag.em(get_resource_name(self.env, wiki_page)),
                        wiki_page.version > 1 and ' edited' or ' created')
         elif field == 'description':
-            if self.config['timeline'].getbool('abbreviated_messages'):
-                comment = shorten_line(comment)
-            markup = format_to_oneliner(self.env, context(resource=wiki_page),
-                                        comment)
+            if abbreviated is None:
+                abbreviated = self.config['timeline'] \
+                        .getbool('abbreviated_messages')
+            flavor, options = (('html', {}), 
+                               ('oneliner', {'shorten': True}))[abbreviated]
+            markup = format_to(self.env, flavor, context(resource=wiki_page),
+                               comment, **options)
             if wiki_page.version > 1:
                 diff_href = context.href.wiki(
                     wiki_page.id, version=wiki_page.version, action='diff')
Index: trac/timeline/api.py
===================================================================
--- trac/timeline/api.py	(revision 7596)
+++ trac/timeline/api.py	(working copy)
@@ -64,7 +64,7 @@
         `markup` are not context dependent.
         """
 
-    def render_timeline_event(context, field, event):
+    def render_timeline_event(context, field, event, abbreviated=None):
         """Display the title of the event in the given context.
 
         :param context: the rendering `Context` object that can be used for
@@ -73,6 +73,11 @@
                       be rendered: can be the 'title', the 'description' or
                       the 'url'
         :param event: the event tuple, as returned by `get_timeline_events`
+        :param abbreviated: when the flag is set to True, the renderer should 
+                            follow this hint in preference to its default way
+                            of deciding whether the content should be 
+                            abbreviated or not.
+
         """
 
 
Index: trac/timeline/web_ui.py
===================================================================
--- trac/timeline/web_ui.py	(revision 7596)
+++ trac/timeline/web_ui.py	(working copy)
@@ -30,6 +30,7 @@
 from trac.mimeview import Context
 from trac.perm import IPermissionRequestor
 from trac.timeline.api import ITimelineEventProvider
+from trac.util import arity
 from trac.util.compat import sorted
 from trac.util.datefmt import format_date, format_datetime, parse_date, \
                               to_timestamp, utc, pretty_timedelta
@@ -278,14 +279,19 @@
         if len(event) == 6: # 0.10 events
             kind, url, title, date, author, markup = event
             data = {'url': url, 'title': title, 'description': markup}
-            render = lambda field, context: data.get(field)
+            render = lambda field, context, abbreviated=None: data.get(field)
         else: # 0.11 events
             if len(event) == 5: # with special provider
                 kind, date, author, data, provider = event
             else:
                 kind, date, author, data = event
-            render = lambda field, context: provider.render_timeline_event(
-                context, field, event)
+            if arity(provider.render_timeline_event) == 2: # 0.11 renderers
+                render = lambda field, context, abbreviated=None: \
+                        provider.render_timeline_event(context, field, event)
+            else: # 0.11.2, optional `abbreviated=None` argument
+                render = lambda field, context, abbreviated=None: \
+                    provider.render_timeline_event(context, field, event,
+                                                   abbreviated)
         if isinstance(date, datetime):
             dateuid = to_timestamp(date)
         else:
Index: trac/timeline/templates/timeline.rss
===================================================================
--- trac/timeline/templates/timeline.rss	(revision 7596)
+++ trac/timeline/templates/timeline.rss	(working copy)
@@ -27,7 +27,7 @@
       </py:with>
       <guid isPermaLink="false">${abs_url}/${event.dateuid}</guid>
       <description>${
-        unicode(event.render('description', context))
+        unicode(event.render('description', context, abbreviated=False))
       }</description>
       <category>$event.kind</category>
     </item>

