From d2d0adc7765dfe904f0f7e97d85a2638c934a7d6 Mon Sep 17 00:00:00 2001
From: Julian Smart <julian@anthemion.co.uk>
Date: Thu, 26 Oct 2006 06:32:47 +0000
Subject: [PATCH] Added URL support to attribute objects and to wxRichTextCtrl,
 generating a wxTextUrlEvent as appropriate. Added outline list support and
 updated previews. Added alignment support for bullets. Added single right
 parenthesis support. Added XML stylesheet reading/writing. Changed
 SetBulletSymbol to SetBulletText so it can support bullet text more generally
 (e.g. for cached outline list numbering) Added wxRichTextRenderer to isolate
 e.g. bullet drawing and make it customisable. Added event handler support to
 wxRichTextBuffer. Updated documentation.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@42431 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/latex/wx/classes.tex                     |   1 +
 docs/latex/wx/richtextattr.tex                | 154 +++-
 docs/latex/wx/richtextbuffer.tex              |  70 ++
 docs/latex/wx/richtextctrl.tex                |  25 +
 docs/latex/wx/richtextliststyledefinition.tex |  85 +++
 docs/latex/wx/richtextoverview.tex            |   9 +-
 docs/latex/wx/richtextstylesheet.tex          |  30 +
 docs/latex/wx/textattrex.tex                  | 145 +++-
 include/wx/richtext/richtextbuffer.h          | 266 +++++--
 include/wx/richtext/richtextbulletspage.h     |  51 +-
 include/wx/richtext/richtextctrl.h            |  45 +-
 include/wx/richtext/richtextformatdlg.h       |  17 +
 include/wx/richtext/richtexthtml.h            |  69 +-
 include/wx/richtext/richtextliststylepage.h   |  15 +-
 include/wx/richtext/richtextstyles.h          |  14 +-
 include/wx/richtext/richtextxml.h             |   3 +
 src/richtext/richtextbuffer.cpp               | 703 +++++++++++++-----
 src/richtext/richtextbulletspage.cpp          | 269 +++++--
 src/richtext/richtextctrl.cpp                 | 110 ++-
 src/richtext/richtexthtml.cpp                 | 395 ++++++----
 src/richtext/richtextindentspage.cpp          |  12 +-
 src/richtext/richtextliststylepage.cpp        | 440 +++++++----
 src/richtext/richtextstyledlg.cpp             |   3 +
 src/richtext/richtextstyles.cpp               |  25 +-
 src/richtext/richtextxml.cpp                  | 270 ++++++-
 25 files changed, 2453 insertions(+), 773 deletions(-)
 create mode 100644 docs/latex/wx/richtextliststyledefinition.tex

diff --git a/docs/latex/wx/classes.tex b/docs/latex/wx/classes.tex
index 63dda27506..c72f796621 100644
--- a/docs/latex/wx/classes.tex
+++ b/docs/latex/wx/classes.tex
@@ -310,6 +310,7 @@
 \input richtextfilehandler.tex
 \input richtextformattingdialog.tex
 \input richtexthtmlhandler.tex
+\input richtextliststyledefinition.tex
 \input richtextparagraphstyledefinition.tex
 \input richtextrange.tex
 \input richtextstyledefinition.tex
diff --git a/docs/latex/wx/richtextattr.tex b/docs/latex/wx/richtextattr.tex
index 375451cf14..5a97fad846 100644
--- a/docs/latex/wx/richtextattr.tex
+++ b/docs/latex/wx/richtextattr.tex
@@ -69,9 +69,12 @@ for a text control.
 #define wxTEXT_ATTR_LINE_SPACING            0x00002000
 #define wxTEXT_ATTR_CHARACTER_STYLE_NAME    0x00004000
 #define wxTEXT_ATTR_PARAGRAPH_STYLE_NAME    0x00008000
-#define wxTEXT_ATTR_BULLET_STYLE            0x00010000
-#define wxTEXT_ATTR_BULLET_NUMBER           0x00020000
-#define wxTEXT_ATTR_BULLET_SYMBOL           0x00040000
+#define wxTEXT_ATTR_LIST_STYLE_NAME         0x00010000
+#define wxTEXT_ATTR_BULLET_STYLE            0x00020000
+#define wxTEXT_ATTR_BULLET_NUMBER           0x00040000
+#define wxTEXT_ATTR_BULLET_TEXT             0x00080000
+#define wxTEXT_ATTR_BULLET_NAME             0x00100000
+#define wxTEXT_ATTR_URL                     0x00200000
 \end{verbatim}
 }
 
@@ -79,16 +82,22 @@ The following styles can be passed to wxRichTextAttr::SetBulletStyle:
 
 {\small
 \begin{verbatim}
-#define wxTEXT_ATTR_BULLET_STYLE_NONE           0x0000
-#define wxTEXT_ATTR_BULLET_STYLE_ARABIC         0x0001
-#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER  0x0002
-#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER  0x0004
-#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER    0x0008
-#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER    0x0010
-#define wxTEXT_ATTR_BULLET_STYLE_SYMBOL         0x0020
-#define wxTEXT_ATTR_BULLET_STYLE_BITMAP         0x0040
-#define wxTEXT_ATTR_BULLET_STYLE_PARENTHESES    0x0080
-#define wxTEXT_ATTR_BULLET_STYLE_PERIOD         0x0100
+#define wxTEXT_ATTR_BULLET_STYLE_NONE               0x00000000
+#define wxTEXT_ATTR_BULLET_STYLE_ARABIC             0x00000001
+#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER      0x00000002
+#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER      0x00000004
+#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER        0x00000008
+#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER        0x00000010
+#define wxTEXT_ATTR_BULLET_STYLE_SYMBOL             0x00000020
+#define wxTEXT_ATTR_BULLET_STYLE_BITMAP             0x00000040
+#define wxTEXT_ATTR_BULLET_STYLE_PARENTHESES        0x00000080
+#define wxTEXT_ATTR_BULLET_STYLE_PERIOD             0x00000100
+#define wxTEXT_ATTR_BULLET_STYLE_STANDARD           0x00000200
+#define wxTEXT_ATTR_BULLET_STYLE_RIGHT_PARENTHESIS  0x00000400
+#define wxTEXT_ATTR_BULLET_STYLE_OUTLINE            0x00000800
+#define wxTEXT_ATTR_BULLET_STYLE_ALIGN_LEFT         0x00000000
+#define wxTEXT_ATTR_BULLET_STYLE_ALIGN_RIGHT        0x00001000
+#define wxTEXT_ATTR_BULLET_STYLE_ALIGN_CENTRE       0x00002000
 \end{verbatim}
 }
 
@@ -150,6 +159,24 @@ Returns the background colour.
 Returns a string containing the name of the font associated with the bullet symbol.
 Only valid for attributes with wxTEXT\_ATTR\_BULLET\_SYMBOL.
 
+\membersection{wxRichTextAttr::GetBulletName}\label{wxrichtextattrgetbulletname}
+
+\constfunc{const wxString\&}{GetBulletName}{\void}
+
+Returns the standard bullet name, applicable if the bullet style is wxTEXT\_ATTR\_BULLET\_STYLE\_STANDARD.
+Currently the following standard bullet names are supported:
+
+\begin{itemize}\itemsep=0pt
+\item {\tt standard/circle}
+\item {\tt standard/square}
+\item {\tt standard/diamond}
+\item {\tt standard/triangle}
+\end{itemize}
+
+If you wish your application to support further bullet graphics, you can derive a
+class from wxRichTextRenderer or wxRichTextStdRenderer, override {\tt DrawStandardBullet} and {\tt EnumerateStandardBulletNames}, and
+set an instance of the class using \helpref{wxRichTextBuffer::SetRenderer}{wxrichtextbuffersetrenderer}.
+
 \membersection{wxRichTextAttr::GetBulletNumber}\label{wxrichtextattrgetbulletnumber}
 
 \constfunc{int}{GetBulletNumber}{\void}
@@ -163,11 +190,11 @@ Returns the bullet number.
 Returns the bullet style.
 See \helpref{wxRichTextAttr::SetBulletStyle}{wxrichtextattrsetbulletstyle} for a list of available styles.
 
-\membersection{wxRichTextAttr::GetBulletSymbol}\label{wxrichtextattrgetbulletsymbol}
+\membersection{wxRichTextAttr::GetBulletText}\label{wxrichtextattrgetbullettext}
 
-\constfunc{wxChar}{GetBulletSymbol}{\void}
+\constfunc{const wxString\&}{GetBulletText}{\void}
 
-Returns the bullet symbol, a character.
+Returns the bullet text, which could be a symbol, or (for example) cached outline text.
 
 \membersection{wxRichTextAttr::GetCharacterStyleName}\label{wxrichtextattrgetcharacterstylename}
 
@@ -237,6 +264,12 @@ Returns the left sub-indent in tenths of a millimetre.
 Returns the line spacing value, one of wxTEXT\_ATTR\_LINE\_SPACING\_NORMAL,
 wxTEXT\_ATTR\_LINE\_SPACING\_HALF, and wxTEXT\_ATTR\_LINE\_SPACING\_TWICE.
 
+\membersection{wxRichTextAttr::GetListStyleName}\label{wxrichtextattrgetliststylename}
+
+\constfunc{const wxString\&}{GetListStyleName}{\void}
+
+Returns the name of the list style.
+
 \membersection{wxRichTextAttr::GetParagraphSpacingAfter}\label{wxrichtextattrgetparagraphspacingafter}
 
 \constfunc{int}{GetParagraphSpacingAfter}{\void}
@@ -274,6 +307,14 @@ is measured from the left margin and therefore each value must be larger than th
 
 Returns the text foreground colour.
 
+\membersection{wxRichTextAttr::GetURL}\label{wxrichtextattrgeturl}
+
+\constfunc{const wxString\&}{GetURL}{\void}
+
+Returns the URL for the content. Content with wxTEXT\_ATTR\_URL style
+causes wxRichTextCtrl to show a hand cursor over it, and wxRichTextCtrl generates
+a wxTextUrlEvent when the content is clicked.
+
 \membersection{wxRichTextAttr::HasAlignment}\label{wxrichtextattrhasalignment}
 
 \constfunc{bool}{HasAlignment}{\void}
@@ -286,6 +327,12 @@ Returns \true if the attribute object specifies alignment.
 
 Returns \true if the attribute object specifies a background colour.
 
+\membersection{wxRichTextAttr::HasBulletName}\label{wxrichtextattrhasbulletname}
+
+\constfunc{bool}{HasBulletName}{\void}
+
+Returns \true if the attribute object specifies a standard bullet name.
+
 \membersection{wxRichTextAttr::HasBulletNumber}\label{wxrichtextattrhasbulletnumber}
 
 \constfunc{bool}{HasBulletNumber}{\void}
@@ -298,11 +345,11 @@ Returns \true if the attribute object specifies a bullet number.
 
 Returns \true if the attribute object specifies a bullet style.
 
-\membersection{wxRichTextAttr::HasBulletSymbol}\label{wxrichtextattrhasbulletsymbol}
+\membersection{wxRichTextAttr::HasBulletText}\label{wxrichtextattrhasbullettext}
 
-\constfunc{bool}{HasBulletSymbol}{\void}
+\constfunc{bool}{HasBulletText}{\void}
 
-Returns \true if the attribute object specifies a bullet symbol.
+Returns \true if the attribute object specifies bullet text (usually specifying a symbol).
 
 \membersection{wxRichTextAttr::HasCharacterStyleName}\label{wxrichtextattrhascharacterstylename}
 
@@ -346,6 +393,12 @@ Returns \true if the attribute object specifies a left indent.
 
 Returns \true if the attribute object specifies line spacing.
 
+\membersection{wxRichTextAttr::HasListStyleName}\label{wxrichtextattrhasliststylename}
+
+\constfunc{bool}{HasListStyleName}{\void}
+
+Returns \true if the attribute object specifies a list style name.
+
 \membersection{wxRichTextAttr::HasParagraphSpacingAfter}\label{wxrichtextattrhasparagraphspacingafter}
 
 \constfunc{bool}{HasParagraphSpacingAfter}{\void}
@@ -460,6 +513,14 @@ Sets the background colour.
 Sets the name of the font associated with the bullet symbol.
 Only valid for attributes with wxTEXT\_ATTR\_BULLET\_SYMBOL.
 
+\membersection{wxRichTextAttr::SetBulletName}\label{wxrichtextattrsetbulletname}
+
+\func{void}{SetBulletName}{\param{const wxString\& }{name}}
+
+Sets the standard bullet name, applicable if the bullet style is wxTEXT\_ATTR\_BULLET\_STYLE\_STANDARD.
+See \helpref{wxRichTextAttr::GetBulletName}{wxrichtextattrgetbulletname} for a list
+of supported names, and how to expand the range of supported types.
+
 \membersection{wxRichTextAttr::SetBulletNumber}\label{wxrichtextattrsetbulletnumber}
 
 \func{void}{SetBulletNumber}{\param{int }{n}}
@@ -474,24 +535,30 @@ Sets the bullet style. The following styles can be passed:
 
 {\small
 \begin{verbatim}
-#define wxTEXT_ATTR_BULLET_STYLE_NONE           0x0000
-#define wxTEXT_ATTR_BULLET_STYLE_ARABIC         0x0001
-#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER  0x0002
-#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER  0x0004
-#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER    0x0008
-#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER    0x0010
-#define wxTEXT_ATTR_BULLET_STYLE_SYMBOL         0x0020
-#define wxTEXT_ATTR_BULLET_STYLE_BITMAP         0x0040
-#define wxTEXT_ATTR_BULLET_STYLE_PARENTHESES    0x0080
-#define wxTEXT_ATTR_BULLET_STYLE_PERIOD         0x0100
+#define wxTEXT_ATTR_BULLET_STYLE_NONE               0x00000000
+#define wxTEXT_ATTR_BULLET_STYLE_ARABIC             0x00000001
+#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER      0x00000002
+#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER      0x00000004
+#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER        0x00000008
+#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER        0x00000010
+#define wxTEXT_ATTR_BULLET_STYLE_SYMBOL             0x00000020
+#define wxTEXT_ATTR_BULLET_STYLE_BITMAP             0x00000040
+#define wxTEXT_ATTR_BULLET_STYLE_PARENTHESES        0x00000080
+#define wxTEXT_ATTR_BULLET_STYLE_PERIOD             0x00000100
+#define wxTEXT_ATTR_BULLET_STYLE_STANDARD           0x00000200
+#define wxTEXT_ATTR_BULLET_STYLE_RIGHT_PARENTHESIS  0x00000400
+#define wxTEXT_ATTR_BULLET_STYLE_OUTLINE            0x00000800
+#define wxTEXT_ATTR_BULLET_STYLE_ALIGN_LEFT         0x00000000
+#define wxTEXT_ATTR_BULLET_STYLE_ALIGN_RIGHT        0x00001000
+#define wxTEXT_ATTR_BULLET_STYLE_ALIGN_CENTRE       0x00002000
 \end{verbatim}
 }
 
-\membersection{wxRichTextAttr::SetBulletSymbol}\label{wxrichtextattrsetbulletsymbol}
+\membersection{wxRichTextAttr::SetBulletText}\label{wxrichtextattrsetbullettext}
 
-\func{void}{SetBulletSymbol}{\param{wxChar }{symbol}}
+\func{void}{SetBulletText}{\param{const wxString& }{text}}
 
-Sets the paragraph symbol.
+Sets the bullet text, which could be a symbol, or (for example) cached outline text.
 
 \membersection{wxRichTextAttr::SetCharacterStyleName}\label{wxrichtextattrsetcharacterstylename}
 
@@ -532,9 +599,12 @@ flags can be passed in a bitlist:
 #define wxTEXT_ATTR_LINE_SPACING            0x00002000
 #define wxTEXT_ATTR_CHARACTER_STYLE_NAME    0x00004000
 #define wxTEXT_ATTR_PARAGRAPH_STYLE_NAME    0x00008000
-#define wxTEXT_ATTR_BULLET_STYLE            0x00010000
-#define wxTEXT_ATTR_BULLET_NUMBER           0x00020000
-#define wxTEXT_ATTR_BULLET_SYMBOL           0x00040000
+#define wxTEXT_ATTR_LIST_STYLE_NAME         0x00010000
+#define wxTEXT_ATTR_BULLET_STYLE            0x00020000
+#define wxTEXT_ATTR_BULLET_NUMBER           0x00040000
+#define wxTEXT_ATTR_BULLET_TEXT             0x00080000
+#define wxTEXT_ATTR_BULLET_NAME             0x00100000
+#define wxTEXT_ATTR_URL                     0x00200000
 \end{verbatim}
 }
 
@@ -600,6 +670,12 @@ defined for convenience:
 \end{verbatim}
 }
 
+\membersection{wxRichTextAttr::SetListStyleName}\label{wxrichtextattrsetliststylename}
+
+\func{void}{SetListStyleName}{\param{const wxString\& }{name}}
+
+Sets the list style name.
+
 \membersection{wxRichTextAttr::SetParagraphSpacingAfter}\label{wxrichtextattrsetparagraphspacingafter}
 
 \func{void}{SetParagraphSpacingAfter}{\param{int }{spacing}}
@@ -637,6 +713,14 @@ Each stop is measured from the left margin and therefore each value must be larg
 
 Sets the text foreground colout.
 
+\membersection{wxRichTextAttr::SetURL}\label{wxrichtextattrseturl}
+
+\func{void}{SetURL}{\param{const wxString\& }{url}}
+
+Sets the URL for the content. Sets the wxTEXT\_ATTR\_URL style; content with this style
+causes wxRichTextCtrl to show a hand cursor over it, and wxRichTextCtrl generates
+a wxTextUrlEvent when the content is clicked.
+
 \membersection{wxRichTextAttr::operator=}\label{wxrichtextattroperatorassign}
 
 \func{void operator}{operator=}{\param{const wxTextAttrEx\& }{attr}}
diff --git a/docs/latex/wx/richtextbuffer.tex b/docs/latex/wx/richtextbuffer.tex
index c177b3f5e5..0ae9c7581a 100644
--- a/docs/latex/wx/richtextbuffer.tex
+++ b/docs/latex/wx/richtextbuffer.tex
@@ -34,6 +34,18 @@ Default constructors.
 
 Destructor.
 
+\membersection{wxRichTextBuffer::AddEventHandler}\label{wxrichtextbufferaddeventhandler}
+
+\func{bool}{AddEventHandler}{\param{wxEvtHandler* }{handler}}
+
+Adds an event handler to the buffer's list of handlers. A buffer associated with
+a contol has the control as the only event handler, but the application is free
+to add more if further notification is required. All handlers are notified
+of an event originating from the buffer, such as the replacement of a style sheet
+during loading. The buffer never deletes any of the event handlers, unless 
+\helpref{wxRichTextBuffer::RemoveEventHandler}{wxrichtextbufferremoveeventhandler} is
+called with \true as the second argument.
+
 \membersection{wxRichTextBuffer::AddHandler}\label{wxrichtextbufferaddhandler}
 
 \func{void}{AddHandler}{\param{wxRichTextFileHandler* }{handler}}
@@ -127,6 +139,12 @@ defined for convenience:
 \end{verbatim}
 }
 
+\membersection{wxRichTextBuffer::BeginListStyle}\label{wxrichtextbufferbeginliststyle}
+
+\func{bool}{BeginListStyle}{\param{const wxString\&}{ listStyle}, \param{int}{ level=1}, \param{int}{ number=1}}
+
+Begins using a specified list style. Optionally, you can also pass a level and a number.
+
 \membersection{wxRichTextBuffer::BeginNumberedBullet}\label{wxrichtextbufferbeginnumberedbullet}
 
 \func{bool}{BeginNumberedBullet}{\param{int }{bulletNumber}, \param{int }{leftIndent}, \param{int }{leftSubIndent}, \param{int }{bulletStyle = wxTEXT\_ATTR\_BULLET\_STYLE\_ARABIC|wxTEXT\_ATTR\_BULLET\_STYLE\_PERIOD}}
@@ -194,6 +212,13 @@ differently by each command. If not dealt with by a command implementation, then
 it will be implemented automatically by not storing the command in the undo history
 when the action is submitted to the command processor.
 
+\membersection{wxRichTextBuffer::BeginStandardBullet}\label{wxrichtextbufferbeginstandardbullet}
+
+\func{bool}{BeginStandardBullet}{\param{const wxString\&}{ bulletName}, \param{int }{leftIndent}, \param{int }{leftSubIndent}, \param{int }{bulletStyle = wxTEXT\_ATTR\_BULLET\_STYLE\_STANDARD}}
+
+Begins applying a standard bullet, using one of the standard bullet names (currently {\tt standard/circle} or {\tt standard/square}.
+See \helpref{BeginNumberedBullet}{wxrichtextbufferbeginnumberedbullet} for an explanation of how indentation is used to render the bulleted paragraph.
+
 \membersection{wxRichTextBuffer::BeginSymbolBullet}\label{wxrichtextbufferbeginsymbolbullet}
 
 \func{bool}{BeginSymbolBullet}{\param{wxChar }{symbol}, \param{int }{leftIndent}, \param{int }{leftSubIndent}, \param{int }{bulletStyle = wxTEXT\_ATTR\_BULLET\_STYLE\_SYMBOL}}
@@ -213,6 +238,13 @@ Begins using the specified text foreground colour.
 
 Begins using underline.
 
+\membersection{wxRichTextBuffer::BeginURL}\label{wxrichtextbufferbeginurl}
+
+\func{bool}{BeginURL}{\param{const wxString\&}{ url}, \param{const wxString\&}{ characterStyle = wxEmptyString}}
+
+Begins applying wxTEXT\_ATTR\_URL to the content. Pass a URL and optionally, a character style to apply,
+since it is common to mark a URL with a familiar style such as blue text with underlining.
+
 \membersection{wxRichTextBuffer::CanPasteFromClipboard}\label{wxrichtextbuffercanpastefromclipboard}
 
 \constfunc{bool}{CanPasteFromClipboard}{\void}
@@ -329,6 +361,12 @@ Ends using a left indent.
 
 Ends using a line spacing.
 
+\membersection{wxRichTextBuffer::EndListStyle}\label{wxrichtextbufferendliststyle}
+
+\func{bool}{EndListStyle}{\void}
+
+Ends using a specified list style.
+
 \membersection{wxRichTextBuffer::EndNumberedBullet}\label{wxrichtextbufferendnumberedbullet}
 
 \func{bool}{EndNumberedBullet}{\void}
@@ -371,6 +409,12 @@ Ends suppressing undo/redo commands.
 
 Ends using a symbol bullet.
 
+\membersection{wxRichTextBuffer::EndStandardBullet}\label{wxrichtextbufferendstandardbullet}
+
+\func{bool}{EndStandardBullet}{\void}
+
+Ends using a standard bullet.
+
 \membersection{wxRichTextBuffer::EndTextColour}\label{wxrichtextbufferendtextcolour}
 
 \func{bool}{EndTextColour}{\void}
@@ -383,6 +427,12 @@ Ends using a text foreground colour.
 
 Ends using underline.
 
+\membersection{wxRichTextBuffer::EndURL}\label{wxrichtextbufferendurl}
+
+\func{bool}{EndURL}{\void}
+
+Ends applying a URL.
+
 \membersection{wxRichTextBuffer::FindHandler}\label{wxrichtextbufferfindhandler}
 
 \func{wxRichTextFileHandler*}{FindHandler}{\param{int }{imageType}}
@@ -446,6 +496,12 @@ used to determine the type to pass to \helpref{LoadFile}{wxrichtextbuffergetextw
 
 Returns the list of file handlers.
 
+\membersection{wxRichTextBuffer::GetRenderer}\label{wxrichtextbuffergetrenderer}
+
+\func{static wxRichTextRenderer*}{GetRenderer}{\void}
+
+Returns the object to be used to render certain aspects of the content, such as bullets.
+
 \membersection{wxRichTextBuffer::GetStyle}\label{wxrichtextbuffergetstyle}
 
 \func{bool}{GetStyle}{\param{long }{position}, \param{wxRichTextAttr\& }{style}}
@@ -596,6 +652,12 @@ Marks the buffer as modified or unmodified.
 
 Pastes the clipboard content to the buffer at the given position.
 
+\membersection{wxRichTextBuffer::RemoveEventHandler}\label{wxrichtextbufferremoveeventhandler}
+
+\func{bool}{RemoveEventHandler}{\param{wxEvtHandler* }{handler}, \param{bool}{ deleteHandler = false}}
+
+Removes an event handler from the buffer's list of handlers, deleting the object if {\it deleteHandler} is \true.
+
 \membersection{wxRichTextBuffer::RemoveHandler}\label{wxrichtextbufferremovehandler}
 
 \func{bool}{RemoveHandler}{\param{const wxString\& }{name}}
@@ -638,6 +700,14 @@ style to bold will cause subsequently inserted text to be bold).
 
 This is not cumulative - setting the default style will replace the previous default style.
 
+\membersection{wxRichTextBuffer::SetRenderer}\label{wxrichtextbuffersetrenderer}
+
+\func{static void}{SetRenderer}{\param{wxRichTextRenderer* }{renderer}}
+
+Sets {\it renderer} as the object to be used to render certain aspects of the content, such as bullets.
+You can override default rendering by deriving a new class from wxRichTextRenderer or wxRichTextStdRenderer,
+overriding one or more virtual functions, and setting an instance of the class using this function.
+
 \membersection{wxRichTextBuffer::SetStyle}\label{wxrichtextbuffersetstyle}
 
 \func{bool}{SetStyle}{\param{const wxRichTextRange\& }{range}, \param{const wxRichTextAttr\& }{style}, \param{int }{flags $=$ wxRICHTEXT\_SETSTYLE\_WITH\_UNDO}}
diff --git a/docs/latex/wx/richtextctrl.tex b/docs/latex/wx/richtextctrl.tex
index 62d1834713..d11e95794c 100644
--- a/docs/latex/wx/richtextctrl.tex
+++ b/docs/latex/wx/richtextctrl.tex
@@ -171,6 +171,12 @@ defined for convenience:
 \end{verbatim}
 }
 
+\membersection{wxRichTextCtrl::BeginListStyle}\label{wxrichtextctrlbeginliststyle}
+
+\func{bool}{BeginListStyle}{\param{const wxString\&}{ listStyle}, \param{int}{ level=1}, \param{int}{ number=1}}
+
+Begins using a specified list style. Optionally, you can also pass a level and a number.
+
 \membersection{wxRichTextCtrl::BeginNumberedBullet}\label{wxrichtextctrlbeginnumberedbullet}
 
 \func{bool}{BeginNumberedBullet}{\param{int }{bulletNumber}, \param{int }{leftIndent}, \param{int }{leftSubIndent}, \param{int }{bulletStyle = wxTEXT\_ATTR\_BULLET\_STYLE\_ARABIC|wxTEXT\_ATTR\_BULLET\_STYLE\_PERIOD}}
@@ -254,6 +260,13 @@ Begins using this colour.
 
 Begins using underlining.
 
+\membersection{wxRichTextCtrl::BeginURL}\label{wxrichtextctrlbeginurl}
+
+\func{bool}{BeginURL}{\param{const wxString\&}{ url}, \param{const wxString\&}{ characterStyle = wxEmptyString}}
+
+Begins applying wxTEXT\_ATTR\_URL to the content. Pass a URL and optionally, a character style to apply,
+since it is common to mark a URL with a familiar style such as blue text with underlining.
+
 \membersection{wxRichTextCtrl::CanCopy}\label{wxrichtextctrlcancopy}
 
 \constfunc{bool}{CanCopy}{\void}
@@ -407,6 +420,12 @@ Ends left indent.
 
 Ends line spacing.
 
+\membersection{wxRichTextCtrl::EndListStyle}\label{wxrichtextctrlendliststyle}
+
+\func{bool}{EndListStyle}{\void}
+
+Ends using a specified list style.
+
 \membersection{wxRichTextCtrl::EndNumberedBullet}\label{wxrichtextctrlendnumberedbullet}
 
 \func{bool}{EndNumberedBullet}{\void}
@@ -461,6 +480,12 @@ Ends applying a text colour.
 
 End applying underlining.
 
+\membersection{wxRichTextCtrl::EndURL}\label{wxrichtextctrlendurl}
+
+\func{bool}{EndURL}{\void}
+
+Ends applying a URL.
+
 \membersection{wxRichTextCtrl::ExtendSelection}\label{wxrichtextctrlextendselection}
 
 \func{bool}{ExtendSelection}{\param{long }{oldPosition}, \param{long }{newPosition}, \param{int }{flags}}
diff --git a/docs/latex/wx/richtextliststyledefinition.tex b/docs/latex/wx/richtextliststyledefinition.tex
new file mode 100644
index 0000000000..e74ea594b1
--- /dev/null
+++ b/docs/latex/wx/richtextliststyledefinition.tex
@@ -0,0 +1,85 @@
+\section{\class{wxRichTextListStyleDefinition}}\label{wxrichtextliststyledefinition}
+
+This class represents a list style definition, usually added to a \helpref{wxRichTextStyleSheet}{wxrichtextstylesheet}.
+
+The class inherits paragraph attributes from wxRichTextStyleParagraphDefinition, and adds 10 further attribute objects, one for each level of a list.
+When applying a list style to a paragraph, the list style's base and appropriate level attributes are merged with the
+paragraph's existing attributes.
+
+You can apply a list style to one or more paragraphs using \helpref{wxRichTextCtrl::SetListStyle}{wxrichtextctrlsetliststyle}. You
+can also use the functions \helpref{wxRichTextCtrl::NumberList}{wxrichtextctrlnumberlist}, \helpref{wxRichTextCtrl::PromoteList}{wxrichtextctrlpromotelist} and 
+\helpref{wxRichTextCtrl::ClearListStyle}{wxrichtextctrlclearliststyle}. As usual, there are wxRichTextBuffer versions of these functions
+so that you can apply them directly to a buffer without requiring a control.
+
+\wxheading{Derived from}
+
+\helpref{wxRichTextStyleParagraphDefinition}{wxrichtextstyleparagraphdefinition}
+
+\wxheading{Include files}
+
+<wx/richtext/richtextstyles.h>
+
+\wxheading{Data structures}
+
+\latexignore{\rtfignore{\wxheading{Members}}}
+
+\membersection{wxRichTextListStyleDefinition::wxRichTextListStyleDefinition}\label{wxrichtextliststyledefinitionwxrichtextliststyledefinition}
+
+\func{}{wxRichTextListStyleDefinition}{\param{const wxString\& }{name = wxEmptyString}}
+
+Constructor.
+
+\membersection{wxRichTextListStyleDefinition::\destruct{wxRichTextListStyleDefinition}}\label{wxrichtextliststyledefinitiondtor}
+
+\func{}{\destruct{wxRichTextListStyleDefinition}}{\void}
+
+Destructor.
+
+\membersection{wxRichTextListStyleDefinition::CombineWithParagraphStyle}\label{wxrichtextliststyledefinitioncombinewithparagraphstyle}
+
+\func{wxRichTextAttr}{CombineWithParagraphStyle}{\param{int }{indent}, \param{const wxRichTextAttr\&}{ paraStyle}}
+
+This function combines the given paragraph style with the list style's base attributes and level style matching the given indent, returning the combined attributes.
+
+\membersection{wxRichTextListStyleDefinition::FindLevelForIndent}\label{wxrichtextliststyledefinitionfindlevelforindent}
+
+\constfunc{int}{FindLevelForIndent}{\param{int }{indent}}
+
+This function finds the level (from 0 to 9) whose indentation attribute mostly closely matches {\it indent} (expressed in tenths of a millimetre).
+
+\membersection{wxRichTextListStyleDefinition::GetCombinedStyle}\label{wxrichtextliststyledefinitioncombinewithparagraphstyle}
+
+\constfunc{wxRichTextAttr}{GetCombinedStyle}{\param{int }{indent}}
+
+This function combines the list style's base attributes and the level style matching the given indent, returning the combined attributes.
+
+\membersection{wxRichTextListStyleDefinition::GetLevelAttributes}\label{wxrichtextliststyledefinitiongetlevelattributes}
+
+\constfunc{const wxRichTextAttr*}{GetLevelAttributes}{\param{int }{level}}
+
+Returns the style for the given level. {\it level} is a number between 0 and 9.
+
+\membersection{wxRichTextListStyleDefinition::GetLevelCount}\label{wxrichtextliststyledefinitiongetlevelcount}
+
+\constfunc{int}{GetLevelCount}{\void}
+
+Returns the number of levels. This is hard-wired to 10.
+
+Returns the style for the given level. {\it level} is a number between 0 and 9.
+
+\membersection{wxRichTextListStyleDefinition::IsNumbered}\label{wxrichtextliststyledefinitionisnumbered}
+
+\constfunc{int}{IsNumbered}{\param{int}{ level}}
+
+Returns \true if the given level has numbered list attributes.
+
+\membersection{wxRichTextListStyleDefinition::SetLevelAttributes}\label{wxrichtextliststyledefinitionsetlevelattributes}
+
+\func{void}{SetLevelAttributes}{\param{int }{level}, \param{const wxRichTextAttr\&}{ attr}}
+
+\func{void}{SetLevelAttributes}{\param{int }{level}, \param{int}{ leftIndent}, \param{int}{ leftSubIndent}, \param{int}{ bulletStyle}, \param{const wxString\&}{ bulletSymbol = wxEmptyString}}
+
+Sets the style for the given level. {\it level} is a number between 0 and 9.
+
+The first and most flexible form uses a wxRichTextAttr object, while the second form is for convenient setting of the most commonly-used attributes.
+
diff --git a/docs/latex/wx/richtextoverview.tex b/docs/latex/wx/richtextoverview.tex
index 97c7254a9c..59f406500a 100644
--- a/docs/latex/wx/richtextoverview.tex
+++ b/docs/latex/wx/richtextoverview.tex
@@ -4,6 +4,7 @@ Classes: \helpref{wxRichTextCtrl}{wxrichtextctrl}, \helpref{wxRichTextBuffer}{wx
 \helpref{wxRichTextAttr}{wxrichtextattr}, \helpref{wxTextAttrEx}{wxtextattrex}, 
 \helpref{wxRichTextCharacterStyleDefinition}{wxrichtextcharacterstyledefinition}, 
 \helpref{wxRichTextParagraphStyleDefinition}{wxrichtextparagraphstyledefinition}, 
+\helpref{wxRichTextListStyleDefinition}{wxrichtextliststyledefinition}, 
 \helpref{wxRichTextStyleSheet}{wxrichtextstylesheet}, 
 \helpref{wxRichTextStyleComboCtrl}{wxrichtextstylecomboctrl}, 
 \helpref{wxRichTextStyleListBox}{wxrichtextstylelistbox}, 
@@ -285,7 +286,7 @@ of styles that you can tailor or use as-is, and this means that you can set a he
 instead of marking text in bold, specifying a large font size, and applying a certain
 paragraph spacing and alignment for every such heading. Similarly,
 wxWidgets provides a class called \helpref{wxRichTextStyleSheet}{wxrichtextstylesheet} which manages style definitions
-(\helpref{wxRichTextParagraphStyleDefinition}{wxrichtextparagraphstyledefinition} and \helpref{wxRichTextCharacterStyleDefinition}{wxrichtextcharacterstyledefinition}).
+(\helpref{wxRichTextParagraphStyleDefinition}{wxrichtextparagraphstyledefinition}, \helpref{wxRichTextListStyleDefinition}{wxrichtextliststyledefinition} and \helpref{wxRichTextCharacterStyleDefinition}{wxrichtextcharacterstyledefinition}).
 Once you have added definitions to a style sheet and associated it with a wxRichTextCtrl,
 you can apply a named definition to a range of text. The classes \helpref{wxRichTextStyleComboCtrl}{wxrichtextstylecomboctrl}\rtfsp
 and \helpref{wxRichTextStyleListBox}{wxrichtextstylelistbox} can be used to present the user with a list
@@ -295,7 +296,7 @@ You can reapply a style sheet to the contents of the control, by calling \helpre
 This is useful if the style definitions have changed, and you want the content to reflect this.
 It relies on the fact that when you apply a named style, the style definition name is recorded in the
 content. So ApplyStyleSheet works by finding the paragraph attributes with style names and re-applying the definition's
-attributes to the paragraph. Currently, this works with paragraph style definitions only.
+attributes to the paragraph. Currently, this works with paragraph and list style definitions only.
 
 \subsection{wxRichTextCtrl dialogs}\label{wxrichtextctrldialogs}
 
@@ -386,12 +387,8 @@ This is a list of some of the features that have yet to be implemented. Help wit
 \item Floating images, with content wrapping around them
 \item A ruler control
 \item Standard editing toolbars
-\item Automatic list numbering
 \item Tables
 \item Text frames
-\item Add ability to show images in wxHTML output (currently uses embedded data suitable only for real browsers)
-\item More complete stylesheet viewer, plus style sheet editing dialogs
-\item Ability to read and write style sheets
 \end{itemize}
 
 There are also things that could be done to take advantage of the underlying text capabilities of the platform;
diff --git a/docs/latex/wx/richtextstylesheet.tex b/docs/latex/wx/richtextstylesheet.tex
index dc62390022..33f89516f7 100644
--- a/docs/latex/wx/richtextstylesheet.tex
+++ b/docs/latex/wx/richtextstylesheet.tex
@@ -37,6 +37,12 @@ Destructor.
 
 Adds a definition to the character style list.
 
+\membersection{wxRichTextStyleSheet::AddListStyle}\label{wxrichtextstylesheetaddliststyle}
+
+\func{bool}{AddListStyle}{\param{wxRichTextListStyleDefinition* }{def}}
+
+Adds a definition to the list style list.
+
 \membersection{wxRichTextStyleSheet::AddParagraphStyle}\label{wxrichtextstylesheetaddparagraphstyle}
 
 \func{bool}{AddParagraphStyle}{\param{wxRichTextParagraphStyleDefinition* }{def}}
@@ -55,6 +61,12 @@ Deletes all styles.
 
 Finds a character definition by name.
 
+\membersection{wxRichTextStyleSheet::FindListStyle}\label{wxrichtextstylesheetfindliststyle}
+
+\constfunc{wxRichTextListStyleDefinition*}{FindListStyle}{\param{const wxString\& }{name}}
+
+Finds a list definition by name.
+
 \membersection{wxRichTextStyleSheet::FindParagraphStyle}\label{wxrichtextstylesheetfindparagraphstyle}
 
 \constfunc{wxRichTextParagraphStyleDefinition*}{FindParagraphStyle}{\param{const wxString\& }{name}}
@@ -73,6 +85,18 @@ Returns the {\it n}th character style.
 
 Returns the number of character styles.
 
+\membersection{wxRichTextStyleSheet::GetListStyle}\label{wxrichtextstylesheetgetliststyle}
+
+\constfunc{wxRichTextListStyleDefinition*}{GetListStyle}{\param{size\_t }{n}}
+
+Returns the {\it n}th list style.
+
+\membersection{wxRichTextStyleSheet::GetListStyleCount}\label{wxrichtextstylesheetgetliststylecount}
+
+\constfunc{size\_t}{GetListStyleCount}{\void}
+
+Returns the number of list styles.
+
 \membersection{wxRichTextStyleSheet::GetParagraphStyle}\label{wxrichtextstylesheetgetparagraphstyle}
 
 \constfunc{wxRichTextParagraphStyleDefinition*}{GetParagraphStyle}{\param{size\_t }{n}}
@@ -97,6 +121,12 @@ Initialises the style sheet.
 
 Removes a character style.
 
+\membersection{wxRichTextStyleSheet::RemoveListStyle}\label{wxrichtextstylesheetremoveliststyle}
+
+\func{bool}{RemoveListStyle}{\param{wxRichTextStyleDefinition* }{def}, \param{bool }{deleteStyle = false}}
+
+Removes a list style.
+
 \membersection{wxRichTextStyleSheet::RemoveParagraphStyle}\label{wxrichtextstylesheetremoveparagraphstyle}
 
 \func{bool}{RemoveParagraphStyle}{\param{wxRichTextStyleDefinition* }{def}, \param{bool }{deleteStyle = false}}
diff --git a/docs/latex/wx/textattrex.tex b/docs/latex/wx/textattrex.tex
index 5eea7fe272..1a8d6b153c 100644
--- a/docs/latex/wx/textattrex.tex
+++ b/docs/latex/wx/textattrex.tex
@@ -75,9 +75,12 @@ for a text control.
 #define wxTEXT_ATTR_LINE_SPACING            0x00002000
 #define wxTEXT_ATTR_CHARACTER_STYLE_NAME    0x00004000
 #define wxTEXT_ATTR_PARAGRAPH_STYLE_NAME    0x00008000
-#define wxTEXT_ATTR_BULLET_STYLE            0x00010000
-#define wxTEXT_ATTR_BULLET_NUMBER           0x00020000
-#define wxTEXT_ATTR_BULLET_SYMBOL           0x00040000
+#define wxTEXT_ATTR_LIST_STYLE_NAME         0x00010000
+#define wxTEXT_ATTR_BULLET_STYLE            0x00020000
+#define wxTEXT_ATTR_BULLET_NUMBER           0x00040000
+#define wxTEXT_ATTR_BULLET_TEXT             0x00080000
+#define wxTEXT_ATTR_BULLET_NAME             0x00100000
+#define wxTEXT_ATTR_URL                     0x00200000
 \end{verbatim}
 }
 
@@ -85,16 +88,22 @@ The following styles can be passed to wxRichTextAttr::SetBulletStyle:
 
 {\small
 \begin{verbatim}
-#define wxTEXT_ATTR_BULLET_STYLE_NONE           0x0000
-#define wxTEXT_ATTR_BULLET_STYLE_ARABIC         0x0001
-#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER  0x0002
-#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER  0x0004
-#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER    0x0008
-#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER    0x0010
-#define wxTEXT_ATTR_BULLET_STYLE_SYMBOL         0x0020
-#define wxTEXT_ATTR_BULLET_STYLE_BITMAP         0x0040
-#define wxTEXT_ATTR_BULLET_STYLE_PARENTHESES    0x0080
-#define wxTEXT_ATTR_BULLET_STYLE_PERIOD         0x0100
+#define wxTEXT_ATTR_BULLET_STYLE_NONE               0x00000000
+#define wxTEXT_ATTR_BULLET_STYLE_ARABIC             0x00000001
+#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER      0x00000002
+#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER      0x00000004
+#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER        0x00000008
+#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER        0x00000010
+#define wxTEXT_ATTR_BULLET_STYLE_SYMBOL             0x00000020
+#define wxTEXT_ATTR_BULLET_STYLE_BITMAP             0x00000040
+#define wxTEXT_ATTR_BULLET_STYLE_PARENTHESES        0x00000080
+#define wxTEXT_ATTR_BULLET_STYLE_PERIOD             0x00000100
+#define wxTEXT_ATTR_BULLET_STYLE_STANDARD           0x00000200
+#define wxTEXT_ATTR_BULLET_STYLE_RIGHT_PARENTHESIS  0x00000400
+#define wxTEXT_ATTR_BULLET_STYLE_OUTLINE            0x00000800
+#define wxTEXT_ATTR_BULLET_STYLE_ALIGN_LEFT         0x00000000
+#define wxTEXT_ATTR_BULLET_STYLE_ALIGN_RIGHT        0x00001000
+#define wxTEXT_ATTR_BULLET_STYLE_ALIGN_CENTRE       0x00002000
 \end{verbatim}
 }
 
@@ -131,6 +140,24 @@ Constructors.
 Returns a string containing the name of the font associated with the bullet symbol.
 Only valid for attributes with wxTEXT\_ATTR\_BULLET\_SYMBOL.
 
+\membersection{wxTextAttrEx::GetBulletName}\label{wxtextattrexgetbulletname}
+
+\constfunc{const wxString\&}{GetBulletName}{\void}
+
+Returns the standard bullet name, applicable if the bullet style is wxTEXT\_ATTR\_BULLET\_STYLE\_STANDARD.
+Currently the following standard bullet names are supported:
+
+\begin{itemize}\itemsep=0pt
+\item {\tt standard/circle}
+\item {\tt standard/square}
+\item {\tt standard/diamond}
+\item {\tt standard/triangle}
+\end{itemize}
+
+If you wish your application to support further bullet graphics, you can derive a
+class from wxRichTextRenderer or wxRichTextStdRenderer, override {\tt DrawStandardBullet} and {\tt EnumerateStandardBulletNames}, and
+set an instance of the class using \helpref{wxRichTextBuffer::SetRenderer}{wxrichtextbuffersetrenderer}.
+
 \membersection{wxTextAttrEx::GetBulletNumber}\label{wxtextattrexgetbulletnumber}
 
 \constfunc{int}{GetBulletNumber}{\void}
@@ -144,11 +171,11 @@ Returns the bullet number.
 Returns the bullet style.
 See \helpref{wxTextAttrEx::SetBulletStyle}{wxtextattrexsetbulletstyle} for a list of available styles.
 
-\membersection{wxTextAttrEx::GetBulletSymbol}\label{wxtextattrexgetbulletsymbol}
+\membersection{wxTextAttrEx::GetBulletText}\label{wxrichtextattrgetbullettext}
 
-\constfunc{wxChar}{GetBulletSymbol}{\void}
+\constfunc{const wxString\&}{GetBulletText}{\void}
 
-Returns the bullet symbol, a character.
+Returns the bullet text, which could be a symbol, or (for example) cached outline text.
 
 \membersection{wxTextAttrEx::GetCharacterStyleName}\label{wxtextattrexgetcharacterstylename}
 
@@ -163,6 +190,12 @@ Returns the name of the character style.
 Returns the line spacing value, one of wxTEXT\_ATTR\_LINE\_SPACING\_NORMAL,
 wxTEXT\_ATTR\_LINE\_SPACING\_HALF, and wxTEXT\_ATTR\_LINE\_SPACING\_TWICE.
 
+\membersection{wxTextAttrEx::GetListStyleName}\label{wxtextattrexgetliststylename}
+
+\constfunc{const wxString\&}{GetListStyleName}{\void}
+
+Returns the name of the list style.
+
 \membersection{wxTextAttrEx::GetParagraphSpacingAfter}\label{wxtextattrexgetparagraphspacingafter}
 
 \constfunc{int}{GetParagraphSpacingAfter}{\void}
@@ -181,6 +214,20 @@ Returns the space in tenths of a millimeter before the paragraph.
 
 Returns the name of the paragraph style.
 
+\membersection{wxTextAttrEx::GetURL}\label{wxtextattrexgeturl}
+
+\constfunc{const wxString\&}{GetURL}{\void}
+
+Returns the URL for the content. Content with wxTEXT\_ATTR\_URL style
+causes wxRichTextCtrl to show a hand cursor over it, and wxRichTextCtrl generates
+a wxTextUrlEvent when the content is clicked.
+
+\membersection{wxTextAttrEx::HasBulletName}\label{wxtextattrexhasbulletname}
+
+\constfunc{bool}{HasBulletName}{\void}
+
+Returns \true if the attribute object specifies a standard bullet name.
+
 \membersection{wxTextAttrEx::HasBulletNumber}\label{wxtextattrexhasbulletnumber}
 
 \constfunc{bool}{HasBulletNumber}{\void}
@@ -193,11 +240,11 @@ Returns \true if the attribute object specifies a bullet number.
 
 Returns \true if the attribute object specifies a bullet style.
 
-\membersection{wxTextAttrEx::HasBulletSymbol}\label{wxtextattrexhasbulletsymbol}
+\membersection{wxTextAttrEx::HasBulletText}\label{wxtextattrexhasbullettext}
 
-\constfunc{bool}{HasBulletSymbol}{\void}
+\constfunc{bool}{HasBulletText}{\void}
 
-Returns \true if the attribute object specifies a bullet symbol.
+Returns \true if the attribute object specifies bullet text (usually containing a symbol).
 
 \membersection{wxTextAttrEx::HasCharacterStyleName}\label{wxtextattrexhascharacterstylename}
 
@@ -211,6 +258,12 @@ Returns \true if the attribute object specifies a character style name.
 
 Returns \true if the attribute object specifies line spacing.
 
+\membersection{wxTextAttrEx::HasListStyleName}\label{wxtextattrexhasliststylename}
+
+\constfunc{bool}{HasListStyleName}{\void}
+
+Returns \true if the attribute object specifies a list style name.
+
 \membersection{wxTextAttrEx::HasParagraphSpacingAfter}\label{wxtextattrexhasparagraphspacingafter}
 
 \constfunc{bool}{HasParagraphSpacingAfter}{\void}
@@ -269,6 +322,14 @@ Only valid for attributes with wxTEXT\_ATTR\_BULLET\_SYMBOL.
 
 Sets the bullet number.
 
+\membersection{wxTextAttrEx::SetBulletName}\label{wxtextattrexsetbulletname}
+
+\func{void}{SetBulletName}{\param{const wxString\& }{name}}
+
+Sets the standard bullet name, applicable if the bullet style is wxTEXT\_ATTR\_BULLET\_STYLE\_STANDARD.
+See \helpref{wxTextAttrEx::GetBulletName}{wxtextattrexgetbulletname} for a list
+of supported names, and how to expand the range of supported types.
+
 \membersection{wxTextAttrEx::SetBulletStyle}\label{wxtextattrexsetbulletstyle}
 
 \func{void}{SetBulletStyle}{\param{int }{style}}
@@ -277,24 +338,30 @@ Sets the bullet style. The following styles can be passed:
 
 {\small
 \begin{verbatim}
-#define wxTEXT_ATTR_BULLET_STYLE_NONE           0x0000
-#define wxTEXT_ATTR_BULLET_STYLE_ARABIC         0x0001
-#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER  0x0002
-#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER  0x0004
-#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER    0x0008
-#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER    0x0010
-#define wxTEXT_ATTR_BULLET_STYLE_SYMBOL         0x0020
-#define wxTEXT_ATTR_BULLET_STYLE_BITMAP         0x0040
-#define wxTEXT_ATTR_BULLET_STYLE_PARENTHESES    0x0080
-#define wxTEXT_ATTR_BULLET_STYLE_PERIOD         0x0100
+#define wxTEXT_ATTR_BULLET_STYLE_NONE               0x00000000
+#define wxTEXT_ATTR_BULLET_STYLE_ARABIC             0x00000001
+#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER      0x00000002
+#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER      0x00000004
+#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER        0x00000008
+#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER        0x00000010
+#define wxTEXT_ATTR_BULLET_STYLE_SYMBOL             0x00000020
+#define wxTEXT_ATTR_BULLET_STYLE_BITMAP             0x00000040
+#define wxTEXT_ATTR_BULLET_STYLE_PARENTHESES        0x00000080
+#define wxTEXT_ATTR_BULLET_STYLE_PERIOD             0x00000100
+#define wxTEXT_ATTR_BULLET_STYLE_STANDARD           0x00000200
+#define wxTEXT_ATTR_BULLET_STYLE_RIGHT_PARENTHESIS  0x00000400
+#define wxTEXT_ATTR_BULLET_STYLE_OUTLINE            0x00000800
+#define wxTEXT_ATTR_BULLET_STYLE_ALIGN_LEFT         0x00000000
+#define wxTEXT_ATTR_BULLET_STYLE_ALIGN_RIGHT        0x00001000
+#define wxTEXT_ATTR_BULLET_STYLE_ALIGN_CENTRE       0x00002000
 \end{verbatim}
 }
 
-\membersection{wxTextAttrEx::SetBulletSymbol}\label{wxtextattrexsetbulletsymbol}
+\membersection{wxTextAttrEx::SetBulletText}\label{wxtextattrexsetbullettext}
 
-\func{void}{SetBulletSymbol}{\param{wxChar }{symbol}}
+\func{void}{SetBulletText}{\param{const wxString\& }{text}}
 
-Sets the paragraph symbol.
+Sets the bullet text, which could be a symbol, or (for example) cached outline text.
 
 \membersection{wxTextAttrEx::SetCharacterStyleName}\label{wxtextattrexsetcharacterstylename}
 
@@ -318,6 +385,12 @@ defined for convenience:
 \end{verbatim}
 }
 
+\membersection{wxTextAttrEx::SetListStyleName}\label{wxtextattrexsetliststylename}
+
+\func{void}{SetListStyleName}{\param{const wxString\& }{name}}
+
+Sets the list style name.
+
 \membersection{wxTextAttrEx::SetParagraphSpacingAfter}\label{wxtextattrexsetparagraphspacingafter}
 
 \func{void}{SetParagraphSpacingAfter}{\param{int }{spacing}}
@@ -336,6 +409,14 @@ Sets the spacing before a paragraph, in tenths of a millimetre.
 
 Sets the name of the paragraph style.
 
+\membersection{wxTextAttrEx::SetURL}\label{wxtextattrexseturl}
+
+\func{void}{SetURL}{\param{const wxString\& }{url}}
+
+Sets the URL for the content. Sets the wxTEXT\_ATTR\_URL style; content with this style
+causes wxRichTextCtrl to show a hand cursor over it, and wxRichTextCtrl generates
+a wxTextUrlEvent when the content is clicked.
+
 \membersection{wxTextAttrEx::operator=}\label{wxtextattrexoperatorassign}
 
 \func{void operator}{operator=}{\param{const wxTextAttr\& }{attr}}
diff --git a/include/wx/richtext/richtextbuffer.h b/include/wx/richtext/richtextbuffer.h
index d299f6be2a..a91ea90363 100644
--- a/include/wx/richtext/richtextbuffer.h
+++ b/include/wx/richtext/richtextbuffer.h
@@ -99,6 +99,8 @@ class WXDLLIMPEXP_RICHTEXT wxRichTextFileHandler;
 class WXDLLIMPEXP_RICHTEXT wxRichTextStyleSheet;
 class WXDLLIMPEXP_RICHTEXT wxTextAttrEx;
 class WXDLLIMPEXP_RICHTEXT wxRichTextListStyleDefinition;
+class WXDLLIMPEXP_RICHTEXT wxRichTextEvent;
+class WXDLLIMPEXP_RICHTEXT wxRichTextRenderer;
 
 /*!
  * Flags determining the available space, passed to Layout
@@ -183,24 +185,31 @@ class WXDLLIMPEXP_RICHTEXT wxRichTextListStyleDefinition;
 #define wxTEXT_ATTR_LIST_STYLE_NAME         0x00010000
 #define wxTEXT_ATTR_BULLET_STYLE            0x00020000
 #define wxTEXT_ATTR_BULLET_NUMBER           0x00040000
-#define wxTEXT_ATTR_BULLET_SYMBOL           0x00080000
+#define wxTEXT_ATTR_BULLET_TEXT             0x00080000
 #define wxTEXT_ATTR_BULLET_NAME             0x00100000
+#define wxTEXT_ATTR_URL                     0x00200000
 
 /*!
  * Styles for wxTextAttrEx::SetBulletStyle
  */
 
-#define wxTEXT_ATTR_BULLET_STYLE_NONE           0x0000
-#define wxTEXT_ATTR_BULLET_STYLE_ARABIC         0x0001
-#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER  0x0002
-#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER  0x0004
-#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER    0x0008
-#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER    0x0010
-#define wxTEXT_ATTR_BULLET_STYLE_SYMBOL         0x0020
-#define wxTEXT_ATTR_BULLET_STYLE_BITMAP         0x0040
-#define wxTEXT_ATTR_BULLET_STYLE_PARENTHESES    0x0080
-#define wxTEXT_ATTR_BULLET_STYLE_PERIOD         0x0100
-#define wxTEXT_ATTR_BULLET_STYLE_STANDARD       0x0200
+#define wxTEXT_ATTR_BULLET_STYLE_NONE               0x00000000
+#define wxTEXT_ATTR_BULLET_STYLE_ARABIC             0x00000001
+#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER      0x00000002
+#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER      0x00000004
+#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER        0x00000008
+#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER        0x00000010
+#define wxTEXT_ATTR_BULLET_STYLE_SYMBOL             0x00000020
+#define wxTEXT_ATTR_BULLET_STYLE_BITMAP             0x00000040
+#define wxTEXT_ATTR_BULLET_STYLE_PARENTHESES        0x00000080
+#define wxTEXT_ATTR_BULLET_STYLE_PERIOD             0x00000100
+#define wxTEXT_ATTR_BULLET_STYLE_STANDARD           0x00000200
+#define wxTEXT_ATTR_BULLET_STYLE_RIGHT_PARENTHESIS  0x00000400
+#define wxTEXT_ATTR_BULLET_STYLE_OUTLINE            0x00000800
+
+#define wxTEXT_ATTR_BULLET_STYLE_ALIGN_LEFT         0x00000000
+#define wxTEXT_ATTR_BULLET_STYLE_ALIGN_RIGHT        0x00001000
+#define wxTEXT_ATTR_BULLET_STYLE_ALIGN_CENTRE       0x00002000
 
 /*!
  * Line spacing values
@@ -210,6 +219,19 @@ class WXDLLIMPEXP_RICHTEXT wxRichTextListStyleDefinition;
 #define wxTEXT_ATTR_LINE_SPACING_HALF           15
 #define wxTEXT_ATTR_LINE_SPACING_TWICE          20
 
+/*!
+ * Character and paragraph combined styles
+ */
+
+#define wxTEXT_ATTR_CHARACTER (wxTEXT_ATTR_FONT | wxTEXT_ATTR_BACKGROUND_COLOUR | wxTEXT_ATTR_TEXT_COLOUR | wxTEXT_ATTR_CHARACTER_STYLE_NAME | wxTEXT_ATTR_URL)
+
+#define wxTEXT_ATTR_PARAGRAPH (wxTEXT_ATTR_ALIGNMENT|wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT|wxTEXT_ATTR_TABS|\
+    wxTEXT_ATTR_PARA_SPACING_BEFORE|wxTEXT_ATTR_PARA_SPACING_AFTER|wxTEXT_ATTR_LINE_SPACING|\
+    wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER|wxTEXT_ATTR_BULLET_TEXT|wxTEXT_ATTR_BULLET_NAME|\
+    wxTEXT_ATTR_PARAGRAPH_STYLE_NAME|wxTEXT_ATTR_LIST_STYLE_NAME)
+
+#define wxTEXT_ATTR_ALL (wxTEXT_ATTR_CHARACTER|wxTEXT_ATTR_PARAGRAPH)
+
 /*!
  * wxRichTextRange class declaration
  * This stores beginning and end positions for a range of data.
@@ -289,6 +311,9 @@ public:
     // Initialise this object
     void Init();
 
+    // Copy
+    void Copy(const wxTextAttrEx& attr);
+
     // Assignment from a wxTextAttrEx object
     void operator= (const wxTextAttrEx& attr);
 
@@ -307,9 +332,10 @@ public:
     void SetLineSpacing(int spacing) { m_lineSpacing = spacing; SetFlags(GetFlags() | wxTEXT_ATTR_LINE_SPACING); }
     void SetBulletStyle(int style) { m_bulletStyle = style; SetFlags(GetFlags() | wxTEXT_ATTR_BULLET_STYLE); }
     void SetBulletNumber(int n) { m_bulletNumber = n; SetFlags(GetFlags() | wxTEXT_ATTR_BULLET_NUMBER); }
-    void SetBulletSymbol(wxChar symbol) { m_bulletSymbol = symbol; SetFlags(GetFlags() | wxTEXT_ATTR_BULLET_SYMBOL); }
+    void SetBulletText(const wxString& text) { m_bulletText = text; SetFlags(GetFlags() | wxTEXT_ATTR_BULLET_TEXT); }
     void SetBulletName(const wxString& name) { m_bulletName = name; SetFlags(GetFlags() | wxTEXT_ATTR_BULLET_NAME); }
     void SetBulletFont(const wxString& bulletFont) { m_bulletFont = bulletFont; }
+    void SetURL(const wxString& url) { m_urlTarget = url; SetFlags(GetFlags() | wxTEXT_ATTR_URL); }
 
     const wxString& GetCharacterStyleName() const { return m_characterStyleName; }
     const wxString& GetParagraphStyleName() const { return m_paragraphStyleName; }
@@ -319,9 +345,10 @@ public:
     int GetLineSpacing() const { return m_lineSpacing; }
     int GetBulletStyle() const { return m_bulletStyle; }
     int GetBulletNumber() const { return m_bulletNumber; }
-    wxChar GetBulletSymbol() const { return m_bulletSymbol; }
+    const wxString& GetBulletText() const { return m_bulletText; }
     const wxString& GetBulletName() const { return m_bulletName; }
     const wxString& GetBulletFont() const { return m_bulletFont; }
+    const wxString& GetURL() const { return m_urlTarget; }
 
     bool HasWeight() const { return (GetFlags() & wxTEXT_ATTR_FONT_WEIGHT) != 0; }
     bool HasSize() const { return (GetFlags() & wxTEXT_ATTR_FONT_SIZE) != 0; }
@@ -337,14 +364,13 @@ public:
     bool HasListStyleName() const { return HasFlag(wxTEXT_ATTR_LIST_STYLE_NAME) || !m_listStyleName.IsEmpty(); }
     bool HasBulletStyle() const { return HasFlag(wxTEXT_ATTR_BULLET_STYLE); }
     bool HasBulletNumber() const { return HasFlag(wxTEXT_ATTR_BULLET_NUMBER); }
-    bool HasBulletSymbol() const { return HasFlag(wxTEXT_ATTR_BULLET_SYMBOL); }
+    bool HasBulletText() const { return HasFlag(wxTEXT_ATTR_BULLET_TEXT); }
     bool HasBulletName() const { return HasFlag(wxTEXT_ATTR_BULLET_NAME); }
+    bool HasURL() const { return HasFlag(wxTEXT_ATTR_URL); }
 
     // Is this a character style?
-    bool IsCharacterStyle() const { return (0 != (GetFlags() & (wxTEXT_ATTR_FONT | wxTEXT_ATTR_BACKGROUND_COLOUR | wxTEXT_ATTR_TEXT_COLOUR))); }
-    bool IsParagraphStyle() const { return (0 != (GetFlags() & (wxTEXT_ATTR_ALIGNMENT|wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT|wxTEXT_ATTR_TABS|
-                            wxTEXT_ATTR_PARA_SPACING_BEFORE|wxTEXT_ATTR_PARA_SPACING_AFTER|wxTEXT_ATTR_LINE_SPACING|
-                            wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER|wxTEXT_ATTR_BULLET_NAME))); }
+    bool IsCharacterStyle() const { return (0 != (GetFlags() & wxTEXT_ATTR_CHARACTER)); }
+    bool IsParagraphStyle() const { return (0 != (GetFlags() & wxTEXT_ATTR_PARAGRAPH)); }
 
     // returns false if we have any attributes set, true otherwise
     bool IsDefault() const
@@ -353,7 +379,7 @@ public:
                !HasTabs() && !HasLeftIndent() && !HasRightIndent() &&
                !HasParagraphSpacingAfter() && !HasParagraphSpacingBefore() && !HasLineSpacing() &&
                !HasCharacterStyleName() && !HasParagraphStyleName() && !HasListStyleName() &&
-               !HasBulletNumber() && !HasBulletStyle() && !HasBulletSymbol() && !HasBulletName();
+               !HasBulletNumber() && !HasBulletStyle() && !HasBulletText() && !HasBulletName() && !HasURL();
     }
 
     // return the attribute having the valid font and colours: it uses the
@@ -370,9 +396,10 @@ private:
     int                 m_lineSpacing;
     int                 m_bulletStyle;
     int                 m_bulletNumber;
-    wxChar              m_bulletSymbol;
+    wxString            m_bulletText;
     wxString            m_bulletFont;
     wxString            m_bulletName;
+    wxString            m_urlTarget;
 
     // Character style
     wxString            m_characterStyleName;
@@ -394,6 +421,7 @@ class WXDLLIMPEXP_RICHTEXT wxRichTextAttr
 public:
     // ctors
     wxRichTextAttr(const wxTextAttrEx& attr);
+    wxRichTextAttr(const wxRichTextAttr& attr);
     wxRichTextAttr() { Init(); }
     wxRichTextAttr(const wxColour& colText,
                const wxColour& colBack = wxNullColour,
@@ -402,6 +430,9 @@ public:
     // Initialise this object.
     void Init();
 
+    // Copy
+    void Copy(const wxRichTextAttr& attr);
+
     // Assignment from a wxRichTextAttr object.
     void operator= (const wxRichTextAttr& attr);
 
@@ -447,9 +478,10 @@ public:
     void SetLineSpacing(int spacing) { m_lineSpacing = spacing; m_flags |= wxTEXT_ATTR_LINE_SPACING; }
     void SetBulletStyle(int style) { m_bulletStyle = style; m_flags |= wxTEXT_ATTR_BULLET_STYLE; }
     void SetBulletNumber(int n) { m_bulletNumber = n; m_flags |= wxTEXT_ATTR_BULLET_NUMBER; }
-    void SetBulletSymbol(wxChar symbol) { m_bulletSymbol = symbol; m_flags |= wxTEXT_ATTR_BULLET_NUMBER; }
+    void SetBulletText(const wxString& text) { m_bulletText = text; m_flags |= wxTEXT_ATTR_BULLET_TEXT; }
     void SetBulletFont(const wxString& bulletFont) { m_bulletFont = bulletFont; }
-    void SetBulletName(const wxString& name) { m_bulletName = name; }
+    void SetBulletName(const wxString& name) { m_bulletName = name; m_flags |= wxTEXT_ATTR_BULLET_NAME; }
+    void SetURL(const wxString& url) { m_urlTarget = url; m_flags |= wxTEXT_ATTR_URL; }
 
     const wxColour& GetTextColour() const { return m_colText; }
     const wxColour& GetBackgroundColour() const { return m_colBack; }
@@ -474,9 +506,10 @@ public:
     int GetLineSpacing() const { return m_lineSpacing; }
     int GetBulletStyle() const { return m_bulletStyle; }
     int GetBulletNumber() const { return m_bulletNumber; }
-    wxChar GetBulletSymbol() const { return m_bulletSymbol; }
+    const wxString& GetBulletText() const { return m_bulletText; }
     const wxString& GetBulletFont() const { return m_bulletFont; }
     const wxString& GetBulletName() const { return m_bulletName; }
+    const wxString& GetURL() const { return m_urlTarget; }
 
     // accessors
     bool HasTextColour() const { return m_colText.Ok() && HasFlag(wxTEXT_ATTR_TEXT_COLOUR) ; }
@@ -500,16 +533,15 @@ public:
     bool HasListStyleName() const { return HasFlag(wxTEXT_ATTR_LIST_STYLE_NAME) || !m_listStyleName.IsEmpty(); }
     bool HasBulletStyle() const { return (m_flags & wxTEXT_ATTR_BULLET_STYLE) != 0; }
     bool HasBulletNumber() const { return (m_flags & wxTEXT_ATTR_BULLET_NUMBER) != 0; }
-    bool HasBulletSymbol() const { return (m_flags & wxTEXT_ATTR_BULLET_SYMBOL) != 0; }
+    bool HasBulletText() const { return (m_flags & wxTEXT_ATTR_BULLET_TEXT) != 0; }
     bool HasBulletName() const { return (m_flags & wxTEXT_ATTR_BULLET_NAME) != 0; }
+    bool HasURL() const { return HasFlag(wxTEXT_ATTR_URL); }
 
     bool HasFlag(long flag) const { return (m_flags & flag) != 0; }
 
     // Is this a character style?
-    bool IsCharacterStyle() const { return (0 != (GetFlags() & (wxTEXT_ATTR_FONT | wxTEXT_ATTR_BACKGROUND_COLOUR | wxTEXT_ATTR_TEXT_COLOUR))); }
-    bool IsParagraphStyle() const { return (0 != (GetFlags() & (wxTEXT_ATTR_ALIGNMENT|wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT|wxTEXT_ATTR_TABS|
-                            wxTEXT_ATTR_PARA_SPACING_BEFORE|wxTEXT_ATTR_PARA_SPACING_AFTER|wxTEXT_ATTR_LINE_SPACING|
-                            wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER|wxTEXT_ATTR_BULLET_NAME))); }
+    bool IsCharacterStyle() const { return (0 != (GetFlags() & wxTEXT_ATTR_CHARACTER)); }
+    bool IsParagraphStyle() const { return (0 != (GetFlags() & wxTEXT_ATTR_PARAGRAPH)); }
 
     // returns false if we have any attributes set, true otherwise
     bool IsDefault() const
@@ -518,7 +550,7 @@ public:
                !HasTabs() && !HasLeftIndent() && !HasRightIndent() &&
                !HasParagraphSpacingAfter() && !HasParagraphSpacingBefore() && !HasLineSpacing() &&
                !HasCharacterStyleName() && !HasParagraphStyleName() && !HasListStyleName() &&
-               !HasBulletNumber() && !HasBulletStyle() && !HasBulletSymbol() && !HasBulletName();
+               !HasBulletNumber() && !HasBulletStyle() && !HasBulletText() && !HasBulletName() && !HasURL();
     }
 
     // return the attribute having the valid font and colours: it uses the
@@ -544,9 +576,10 @@ private:
     int                 m_lineSpacing;
     int                 m_bulletStyle;
     int                 m_bulletNumber;
-    wxChar              m_bulletSymbol;
+    wxString            m_bulletText;
     wxString            m_bulletFont;
     wxString            m_bulletName;
+    wxString            m_urlTarget;
 
     // Character styles
     wxColour            m_colText,
@@ -567,15 +600,6 @@ private:
     wxString            m_listStyleName;
 };
 
-#define wxTEXT_ATTR_CHARACTER (wxTEXT_ATTR_FONT | wxTEXT_ATTR_BACKGROUND_COLOUR | wxTEXT_ATTR_TEXT_COLOUR | wxTEXT_ATTR_CHARACTER_STYLE_NAME)
-
-#define wxTEXT_ATTR_PARAGRAPH (wxTEXT_ATTR_ALIGNMENT|wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT|wxTEXT_ATTR_TABS|\
-    wxTEXT_ATTR_PARA_SPACING_BEFORE|wxTEXT_ATTR_PARA_SPACING_AFTER|wxTEXT_ATTR_LINE_SPACING|\
-    wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER|wxTEXT_ATTR_BULLET_SYMBOL|wxTEXT_ATTR_BULLET_NAME|\
-    wxTEXT_ATTR_PARAGRAPH_STYLE_NAME|wxTEXT_ATTR_LIST_STYLE_NAME)
-
-#define wxTEXT_ATTR_ALL (wxTEXT_ATTR_CHARACTER|wxTEXT_ATTR_PARAGRAPH)
-
 /*!
  * wxRichTextObject class declaration
  * This is the base for drawable objects.
@@ -704,7 +728,7 @@ public:
     void Dereference();
 
     /// Convert units in tends of a millimetre to device units
-    int ConvertTenthsMMToPixels(wxDC& dc, int units);
+    static int ConvertTenthsMMToPixels(wxDC& dc, int units);
 
 protected:
     wxSize                  m_size;
@@ -1016,6 +1040,9 @@ public:
     /// def/defName can be NULL/empty to indicate that the existing list style should be used.
     virtual bool DoNumberList(const wxRichTextRange& range, const wxRichTextRange& promotionRange, int promoteBy, wxRichTextListStyleDefinition* def, int flags = wxRICHTEXT_SETSTYLE_WITH_UNDO, int startFrom = 1, int specifiedLevel = -1);
 
+    /// Fills in the attributes for numbering a paragraph after previousParagraph.
+    virtual bool FindNextParagraphNumber(wxRichTextParagraph* previousParagraph, wxRichTextAttr& attr) const;
+
     /// Test if this whole range has character attributes of the specified kind. If any
     /// of the attributes are different within the range, the test fails. You
     /// can use this to implement, for example, bold button updating. style must have
@@ -1418,9 +1445,12 @@ public:
     bool Ok() const { return IsOk(); }
     bool IsOk() const { return GetData() != NULL; }
 
+    // Gets the extension for the block's type
+    wxString GetExtension() const;
+
 /// Implementation
 
-    /// Allocate and read from stream as a block of memory
+    // Allocate and read from stream as a block of memory
     static unsigned char* ReadBlock(wxInputStream& stream, size_t size);
     static unsigned char* ReadBlock(const wxString& filename, size_t size);
 
@@ -1530,6 +1560,9 @@ public:
     void SetStyleSheet(wxRichTextStyleSheet* styleSheet) { m_styleSheet = styleSheet; }
     virtual wxRichTextStyleSheet* GetStyleSheet() const { return m_styleSheet; }
 
+    /// Set style sheet and notify of the change
+    bool SetStyleSheetAndNotify(wxRichTextStyleSheet* sheet);
+
     /// Push style sheet to top of stack
     bool PushStyleSheet(wxRichTextStyleSheet* styleSheet);
 
@@ -1559,6 +1592,12 @@ public:
     /// Save to a stream
     virtual bool SaveFile(wxOutputStream& stream, int type = wxRICHTEXT_TYPE_ANY);
 
+    /// Set the handler flags, controlling loading and saving
+    void SetHandlerFlags(int flags) { m_handlerFlags = flags; }
+
+    /// Get the handler flags, controlling loading and saving
+    int GetHandlerFlags() const { return m_handlerFlags; }
+
     /// Convenience function to add a paragraph of text
     virtual wxRichTextRange AddParagraph(const wxString& text, wxTextAttrEx* paraStyle = NULL) { Modify(); return wxRichTextParagraphLayoutBox::AddParagraph(text, paraStyle); }
 
@@ -1688,7 +1727,7 @@ public:
     bool EndNumberedBullet() { return EndStyle(); }
 
     /// Begin symbol bullet
-    bool BeginSymbolBullet(wxChar symbol, int leftIndent, int leftSubIndent, int bulletStyle = wxTEXT_ATTR_BULLET_STYLE_SYMBOL);
+    bool BeginSymbolBullet(const wxString& symbol, int leftIndent, int leftSubIndent, int bulletStyle = wxTEXT_ATTR_BULLET_STYLE_SYMBOL);
 
     /// End symbol bullet
     bool EndSymbolBullet() { return EndStyle(); }
@@ -1717,6 +1756,27 @@ public:
     /// End named character style
     bool EndListStyle() { return EndStyle(); }
 
+    /// Begin URL
+    bool BeginURL(const wxString& url, const wxString& characterStyle = wxEmptyString);
+
+    /// End URL
+    bool EndURL() { return EndStyle(); }
+
+// Event handling
+
+    /// Add an event handler
+    bool AddEventHandler(wxEvtHandler* handler);
+
+    /// Remove an event handler
+    bool RemoveEventHandler(wxEvtHandler* handler, bool deleteHandler = false);
+
+    /// Clear event handlers
+    void ClearEventHandlers();
+
+    /// Send event to event handlers. If sendToAll is true, will send to all event handlers,
+    /// otherwise will stop at the first successful one.
+    bool SendEvent(wxEvent& event, bool sendToAll = true);
+
 // Implementation
 
     /// Copy
@@ -1788,6 +1848,19 @@ public:
     /// Initialise the standard handlers
     static void InitStandardHandlers();
 
+    /// Get renderer
+    static wxRichTextRenderer* GetRenderer() { return sm_renderer; }
+
+    /// Set renderer, deleting old one
+    static void SetRenderer(wxRichTextRenderer* renderer);
+
+    /// Minimum margin between bullet and paragraph in 10ths of a mm
+    static int GetBulletRightMargin() { return sm_bulletRightMargin; }
+    static void SetBulletRightMargin(int margin) { sm_bulletRightMargin = margin; }
+
+    /// Factor to multiply by character height to get a reasonable bullet size
+    static float GetBulletProportion() { return sm_bulletProportion; }
+    static void SetBulletProportion(float prop) { sm_bulletProportion = prop; }
 protected:
 
     /// Command processor
@@ -1811,11 +1884,26 @@ protected:
     /// Style sheet, if any
     wxRichTextStyleSheet*   m_styleSheet;
 
+    /// List of event handlers that will be notified of events
+    wxList                  m_eventHandlers;
+
     /// Stack of attributes for convenience functions
     wxList                  m_attributeStack;
 
+    /// Flags to be passed to handlers
+    int                     m_handlerFlags;
+
     /// File handlers
     static wxList           sm_handlers;
+
+    /// Renderer
+    static wxRichTextRenderer* sm_renderer;
+
+    /// Minimum margin between bullet and paragraph in 10ths of a mm
+    static int              sm_bulletRightMargin;
+
+    /// Factor to multiply by character height to get a reasonable bullet size
+    static float            sm_bulletProportion;
 };
 
 /*!
@@ -1927,6 +2015,22 @@ protected:
     wxRichTextCommandId             m_cmdId;
 };
 
+/*!
+ * Handler flags
+ */
+
+// Include style sheet when loading and saving
+#define wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET       0x0001
+
+// Save images to memory file system in HTML handler
+#define wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_MEMORY    0x0010
+
+// Save images to files in HTML handler
+#define wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_FILES     0x0020
+
+// Save images as inline base64 data in HTML handler
+#define wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_BASE64    0x0040
+
 /*!
  * wxRichTextFileHandler
  * Base class for file handlers
@@ -1937,7 +2041,7 @@ class WXDLLIMPEXP_RICHTEXT wxRichTextFileHandler: public wxObject
     DECLARE_CLASS(wxRichTextFileHandler)
 public:
     wxRichTextFileHandler(const wxString& name = wxEmptyString, const wxString& ext = wxEmptyString, int type = 0)
-        : m_name(name), m_extension(ext), m_type(type), m_visible(true)
+        : m_name(name), m_extension(ext), m_type(type), m_visible(true), m_flags(0)
         { }
 
 #if wxUSE_STREAMS
@@ -1975,6 +2079,10 @@ public:
     void SetType(int type) { m_type = type; }
     int GetType() const { return m_type; }
 
+    /// Flags controlling how loading and saving is done
+    void SetFlags(int flags) { m_flags = flags; }
+    int GetFlags() const { return m_flags; }
+
     /// Encoding to use when saving a file. If empty, a suitable encoding is chosen
     void SetEncoding(const wxString& encoding) { m_encoding = encoding; }
     const wxString& GetEncoding() const { return m_encoding; }
@@ -1990,6 +2098,7 @@ protected:
     wxString  m_encoding;
     wxString  m_extension;
     int       m_type;
+    int       m_flags;
     bool      m_visible;
 };
 
@@ -2027,7 +2136,7 @@ protected:
  * The data object for a wxRichTextBuffer
  */
 
-class wxRichTextBufferDataObject: public wxDataObjectSimple
+class WXDLLIMPEXP_RICHTEXT wxRichTextBufferDataObject: public wxDataObjectSimple
 {
 public:
     // ctor doesn't copy the pointer, so it shouldn't go away while this object
@@ -2063,6 +2172,51 @@ private:
 
 #endif
 
+/*!
+ * wxRichTextRenderer isolates common drawing functionality
+ */
+
+class WXDLLIMPEXP_RICHTEXT wxRichTextRenderer: public wxObject
+{
+public:
+    wxRichTextRenderer() {}
+    virtual ~wxRichTextRenderer() {}
+
+    /// Draw a standard bullet, as specified by the value of GetBulletName
+    virtual bool DrawStandardBullet(wxRichTextParagraph* paragraph, wxDC& dc, const wxTextAttrEx& attr, const wxRect& rect) = 0;
+
+    /// Draw a bullet that can be described by text, such as numbered or symbol bullets
+    virtual bool DrawTextBullet(wxRichTextParagraph* paragraph, wxDC& dc, const wxTextAttrEx& attr, const wxRect& rect, const wxString& text) = 0;
+
+    /// Draw a bitmap bullet, where the bullet bitmap is specified by the value of GetBulletName
+    virtual bool DrawBitmapBullet(wxRichTextParagraph* paragraph, wxDC& dc, const wxTextAttrEx& attr, const wxRect& rect) = 0;
+
+    /// Enumerate the standard bullet names currently supported
+    virtual bool EnumerateStandardBulletNames(wxArrayString& bulletNames) = 0;
+};
+
+/*!
+ * wxRichTextStdRenderer: standard renderer
+ */
+
+class WXDLLIMPEXP_RICHTEXT wxRichTextStdRenderer: public wxRichTextRenderer
+{
+public:
+    wxRichTextStdRenderer() {}
+
+    /// Draw a standard bullet, as specified by the value of GetBulletName
+    virtual bool DrawStandardBullet(wxRichTextParagraph* paragraph, wxDC& dc, const wxTextAttrEx& attr, const wxRect& rect);
+
+    /// Draw a bullet that can be described by text, such as numbered or symbol bullets
+    virtual bool DrawTextBullet(wxRichTextParagraph* paragraph, wxDC& dc, const wxTextAttrEx& attr, const wxRect& rect, const wxString& text);
+
+    /// Draw a bitmap bullet, where the bullet bitmap is specified by the value of GetBulletName
+    virtual bool DrawBitmapBullet(wxRichTextParagraph* paragraph, wxDC& dc, const wxTextAttrEx& attr, const wxRect& rect);
+
+    /// Enumerate the standard bullet names currently supported
+    virtual bool EnumerateStandardBulletNames(wxArrayString& bulletNames);
+};
+
 /*!
  * Utilities
  *
@@ -2074,28 +2228,27 @@ inline bool wxRichTextHasStyle(int flags, int style)
 }
 
 /// Compare two attribute objects
-bool wxTextAttrEq(const wxTextAttrEx& attr1, const wxTextAttrEx& attr2);
-bool wxTextAttrEq(const wxTextAttr& attr1, const wxRichTextAttr& attr2);
+WXDLLIMPEXP_RICHTEXT bool wxTextAttrEq(const wxTextAttrEx& attr1, const wxTextAttrEx& attr2);
+WXDLLIMPEXP_RICHTEXT bool wxTextAttrEq(const wxTextAttr& attr1, const wxRichTextAttr& attr2);
 
 /// Compare two attribute objects, but take into account the flags
 /// specifying attributes of interest.
-bool wxTextAttrEqPartial(const wxTextAttrEx& attr1, const wxTextAttrEx& attr2, int flags);
-bool wxTextAttrEqPartial(const wxTextAttrEx& attr1, const wxRichTextAttr& attr2, int flags);
+WXDLLIMPEXP_RICHTEXT bool wxTextAttrEqPartial(const wxTextAttrEx& attr1, const wxTextAttrEx& attr2, int flags);
+WXDLLIMPEXP_RICHTEXT bool wxTextAttrEqPartial(const wxTextAttrEx& attr1, const wxRichTextAttr& attr2, int flags);
 
 /// Apply one style to another
-bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxTextAttrEx& style);
-bool wxRichTextApplyStyle(wxRichTextAttr& destStyle, const wxTextAttrEx& style);
-bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style, wxRichTextAttr* compareWith = NULL);
+WXDLLIMPEXP_RICHTEXT bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxTextAttrEx& style);
+WXDLLIMPEXP_RICHTEXT bool wxRichTextApplyStyle(wxRichTextAttr& destStyle, const wxTextAttrEx& style);
+WXDLLIMPEXP_RICHTEXT bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style, wxRichTextAttr* compareWith = NULL);
 
 /// Compare tabs
-bool wxRichTextTabsEq(const wxArrayInt& tabs1, const wxArrayInt& tabs2);
+WXDLLIMPEXP_RICHTEXT bool wxRichTextTabsEq(const wxArrayInt& tabs1, const wxArrayInt& tabs2);
 
 /// Set the font without changing the font attributes
-void wxSetFontPreservingStyles(wxTextAttr& attr, const wxFont& font);
+WXDLLIMPEXP_RICHTEXT void wxSetFontPreservingStyles(wxTextAttr& attr, const wxFont& font);
 
 /// Convert a decimal to Roman numerals
-wxString wxRichTextDecimalToRoman(long n);
-
+WXDLLIMPEXP_RICHTEXT wxString wxRichTextDecimalToRoman(long n);
 
 WXDLLIMPEXP_RICHTEXT void wxRichTextModuleInit();
 
@@ -2104,3 +2257,4 @@ WXDLLIMPEXP_RICHTEXT void wxRichTextModuleInit();
 
 #endif
     // _WX_RICHTEXTBUFFER_H_
+
diff --git a/include/wx/richtext/richtextbulletspage.h b/include/wx/richtext/richtextbulletspage.h
index f6fb9a475b..63cfbd3f5e 100644
--- a/include/wx/richtext/richtextbulletspage.h
+++ b/include/wx/richtext/richtextbulletspage.h
@@ -17,8 +17,8 @@
  */
 
 ////@begin includes
-#include "wx/spinctrl.h"
 #include "wx/statline.h"
+#include "wx/spinctrl.h"
 ////@end includes
 
 /*!
@@ -101,23 +101,14 @@ public:
     /// wxEVT_UPDATE_UI event handler for ID_RICHTEXTBULLETSPAGE_PARENTHESESCTRL
     void OnParenthesesctrlUpdate( wxUpdateUIEvent& event );
 
-    /// wxEVT_UPDATE_UI event handler for ID_RICHTEXTBULLETSPAGE_NUMBERSTATIC
-    void OnNumberstaticUpdate( wxUpdateUIEvent& event );
+    /// wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_RICHTEXTBULLETSPAGE_RIGHTPARENTHESISCTRL
+    void OnRightParenthesisCtrlClick( wxCommandEvent& event );
 
-    /// wxEVT_COMMAND_SPINCTRL_UPDATED event handler for ID_RICHTEXTBULLETSPAGE_NUMBERCTRL
-    void OnNumberctrlUpdated( wxSpinEvent& event );
+    /// wxEVT_UPDATE_UI event handler for ID_RICHTEXTBULLETSPAGE_RIGHTPARENTHESISCTRL
+    void OnRightParenthesisCtrlUpdate( wxUpdateUIEvent& event );
 
-    /// wxEVT_SCROLL_LINEUP event handler for ID_RICHTEXTBULLETSPAGE_NUMBERCTRL
-    void OnNumberctrlUp( wxSpinEvent& event );
-
-    /// wxEVT_SCROLL_LINEDOWN event handler for ID_RICHTEXTBULLETSPAGE_NUMBERCTRL
-    void OnNumberctrlDown( wxSpinEvent& event );
-
-    /// wxEVT_COMMAND_TEXT_UPDATED event handler for ID_RICHTEXTBULLETSPAGE_NUMBERCTRL
-    void OnNumberctrlTextUpdated( wxCommandEvent& event );
-
-    /// wxEVT_UPDATE_UI event handler for ID_RICHTEXTBULLETSPAGE_NUMBERCTRL
-    void OnNumberctrlUpdate( wxUpdateUIEvent& event );
+    /// wxEVT_COMMAND_COMBOBOX_SELECTED event handler for ID_RICHTEXTBULLETSPAGE_BULLETALIGNMENTCTRL
+    void OnBulletAlignmentCtrlSelected( wxCommandEvent& event );
 
     /// wxEVT_UPDATE_UI event handler for ID_RICHTEXTBULLETSPAGE_SYMBOLSTATIC
     void OnSymbolstaticUpdate( wxUpdateUIEvent& event );
@@ -158,6 +149,24 @@ public:
     /// wxEVT_UPDATE_UI event handler for ID_RICHTEXTBULLETSPAGE_NAMECTRL
     void OnNamectrlUIUpdate( wxUpdateUIEvent& event );
 
+    /// wxEVT_UPDATE_UI event handler for ID_RICHTEXTBULLETSPAGE_NUMBERSTATIC
+    void OnNumberstaticUpdate( wxUpdateUIEvent& event );
+
+    /// wxEVT_COMMAND_SPINCTRL_UPDATED event handler for ID_RICHTEXTBULLETSPAGE_NUMBERCTRL
+    void OnNumberctrlUpdated( wxSpinEvent& event );
+
+    /// wxEVT_SCROLL_LINEUP event handler for ID_RICHTEXTBULLETSPAGE_NUMBERCTRL
+    void OnNumberctrlUp( wxSpinEvent& event );
+
+    /// wxEVT_SCROLL_LINEDOWN event handler for ID_RICHTEXTBULLETSPAGE_NUMBERCTRL
+    void OnNumberctrlDown( wxSpinEvent& event );
+
+    /// wxEVT_COMMAND_TEXT_UPDATED event handler for ID_RICHTEXTBULLETSPAGE_NUMBERCTRL
+    void OnNumberctrlTextUpdated( wxCommandEvent& event );
+
+    /// wxEVT_UPDATE_UI event handler for ID_RICHTEXTBULLETSPAGE_NUMBERCTRL
+    void OnNumberctrlUpdate( wxUpdateUIEvent& event );
+
 ////@end wxRichTextBulletsPage event handler declarations
 
 ////@begin wxRichTextBulletsPage member function declarations
@@ -176,10 +185,12 @@ public:
     wxListBox* m_styleListBox;
     wxCheckBox* m_periodCtrl;
     wxCheckBox* m_parenthesesCtrl;
-    wxSpinCtrl* m_numberCtrl;
+    wxCheckBox* m_rightParenthesisCtrl;
+    wxComboBox* m_bulletAlignmentCtrl;
     wxComboBox* m_symbolCtrl;
     wxComboBox* m_symbolFontCtrl;
     wxComboBox* m_bulletNameCtrl;
+    wxSpinCtrl* m_numberCtrl;
     wxRichTextCtrl* m_previewCtrl;
     /// Control identifiers
     enum {
@@ -187,14 +198,16 @@ public:
         ID_RICHTEXTBULLETSPAGE_STYLELISTBOX = 10305,
         ID_RICHTEXTBULLETSPAGE_PERIODCTRL = 10313,
         ID_RICHTEXTBULLETSPAGE_PARENTHESESCTRL = 10311,
-        ID_RICHTEXTBULLETSPAGE_NUMBERSTATIC = 10302,
-        ID_RICHTEXTBULLETSPAGE_NUMBERCTRL = 10310,
+        ID_RICHTEXTBULLETSPAGE_RIGHTPARENTHESISCTRL = 10306,
+        ID_RICHTEXTBULLETSPAGE_BULLETALIGNMENTCTRL = 10315,
         ID_RICHTEXTBULLETSPAGE_SYMBOLSTATIC = 10301,
         ID_RICHTEXTBULLETSPAGE_SYMBOLCTRL = 10307,
         ID_RICHTEXTBULLETSPAGE_CHOOSE_SYMBOL = 10308,
         ID_RICHTEXTBULLETSPAGE_SYMBOLFONTCTRL = 10309,
         ID_RICHTEXTBULLETSPAGE_NAMESTATIC = 10303,
         ID_RICHTEXTBULLETSPAGE_NAMECTRL = 10304,
+        ID_RICHTEXTBULLETSPAGE_NUMBERSTATIC = 10302,
+        ID_RICHTEXTBULLETSPAGE_NUMBERCTRL = 10310,
         ID_RICHTEXTBULLETSPAGE_PREVIEW_CTRL = 10314
     };
 ////@end wxRichTextBulletsPage member variables
diff --git a/include/wx/richtext/richtextctrl.h b/include/wx/richtext/richtextctrl.h
index 15c1d3791a..fa3a217538 100644
--- a/include/wx/richtext/richtextctrl.h
+++ b/include/wx/richtext/richtextctrl.h
@@ -154,6 +154,12 @@ public:
     virtual bool DoLoadFile(const wxString& file, int fileType);
     virtual bool DoSaveFile(const wxString& file = wxEmptyString, int fileType = wxRICHTEXT_TYPE_ANY);
 
+    /// Set the handler flags, controlling loading and saving
+    void SetHandlerFlags(int flags) { GetBuffer().SetHandlerFlags(flags); }
+
+    /// Get the handler flags, controlling loading and saving
+    int GetHandlerFlags() const { return GetBuffer().GetHandlerFlags(); }
+
     // sets/clears the dirty flag
     virtual void MarkDirty();
     virtual void DiscardEdits();
@@ -378,7 +384,7 @@ public:
     bool EndNumberedBullet() { return GetBuffer().EndNumberedBullet(); }
 
     /// Begin symbol bullet
-    bool BeginSymbolBullet(wxChar symbol, int leftIndent, int leftSubIndent, int bulletStyle = wxTEXT_ATTR_BULLET_STYLE_SYMBOL)
+    bool BeginSymbolBullet(const wxString& symbol, int leftIndent, int leftSubIndent, int bulletStyle = wxTEXT_ATTR_BULLET_STYLE_SYMBOL)
     { return GetBuffer().BeginSymbolBullet(symbol, leftIndent, leftSubIndent, bulletStyle); }
 
     /// End symbol bullet
@@ -409,6 +415,12 @@ public:
     /// End named character style
     bool EndListStyle() { return GetBuffer().EndListStyle(); }
 
+    /// Begin URL
+    bool BeginURL(const wxString& url, const wxString& characterStyle = wxEmptyString) { return GetBuffer().BeginURL(url, characterStyle); }
+
+    /// End URL
+    bool EndURL() { return GetBuffer().EndURL(); }
+
     /// Sets the default style to the style under the cursor
     bool SetDefaultStyleToCursorStyle();
 
@@ -817,6 +829,10 @@ private:
     /// Threshold for doing delayed layout
     long                    m_delayedLayoutThreshold;
 
+    /// Cursors
+    wxCursor                m_textCursor;
+    wxCursor                m_urlCursor;
+
     static wxArrayString    sm_availableFontNames;
 };
 
@@ -829,12 +845,13 @@ class WXDLLIMPEXP_RICHTEXT wxRichTextEvent : public wxNotifyEvent
 public:
     wxRichTextEvent(wxEventType commandType = wxEVT_NULL, int winid = 0)
         : wxNotifyEvent(commandType, winid),
-        m_itemIndex(-1), m_flags(0)
+        m_itemIndex(-1), m_flags(0), m_oldStyleSheet(NULL), m_newStyleSheet(NULL)
         { }
 
     wxRichTextEvent(const wxRichTextEvent& event)
         : wxNotifyEvent(event),
-        m_itemIndex(event.m_itemIndex), m_flags(event.m_flags)
+        m_itemIndex(event.m_itemIndex), m_flags(event.m_flags),
+        m_oldStyleSheet(event.m_oldStyleSheet), m_newStyleSheet(event.m_newStyleSheet)
         { }
 
     int GetIndex() const { return m_itemIndex; }
@@ -843,11 +860,19 @@ public:
     int GetFlags() const { return m_flags; }
     void SetFlags(int flags) { m_flags = flags; }
 
+    wxRichTextStyleSheet* GetOldStyleSheet() const { return m_oldStyleSheet; }
+    void SetOldStyleSheet(wxRichTextStyleSheet* sheet) { m_oldStyleSheet = sheet; }
+
+    wxRichTextStyleSheet* GetNewStyleSheet() const { return m_newStyleSheet; }
+    void SetNewStyleSheet(wxRichTextStyleSheet* sheet) { m_newStyleSheet = sheet; }
+
     virtual wxEvent *Clone() const { return new wxRichTextEvent(*this); }
 
 protected:
-    int                 m_itemIndex;
-    int                 m_flags;
+    int                     m_itemIndex;
+    int                     m_flags;
+    wxRichTextStyleSheet*   m_oldStyleSheet;
+    wxRichTextStyleSheet*   m_newStyleSheet;
 
 private:
     DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxRichTextEvent)
@@ -865,6 +890,11 @@ BEGIN_DECLARE_EVENT_TYPES()
     DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_RICHTEXT, wxEVT_COMMAND_RICHTEXT_MIDDLE_CLICK, 2604)
     DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_RICHTEXT, wxEVT_COMMAND_RICHTEXT_LEFT_DCLICK, 2605)
     DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_RICHTEXT, wxEVT_COMMAND_RICHTEXT_RETURN, 2606)
+
+    DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_RICHTEXT, wxEVT_COMMAND_RICHTEXT_STYLESHEET_CHANGING, 2607)
+    DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_RICHTEXT, wxEVT_COMMAND_RICHTEXT_STYLESHEET_CHANGED, 2608)
+    DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_RICHTEXT, wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACING, 2609)
+    DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_RICHTEXT, wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACED, 2610)
 END_DECLARE_EVENT_TYPES()
 
 typedef void (wxEvtHandler::*wxRichTextEventFunction)(wxRichTextEvent&);
@@ -877,6 +907,11 @@ typedef void (wxEvtHandler::*wxRichTextEventFunction)(wxRichTextEvent&);
 #define EVT_RICHTEXT_LEFT_DCLICK(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_RICHTEXT_LEFT_DCLICK, id, -1, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxRichTextEventFunction, & fn ), NULL ),
 #define EVT_RICHTEXT_RETURN(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_RICHTEXT_RETURN, id, -1, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxRichTextEventFunction, & fn ), NULL ),
 
+#define EVT_RICHTEXT_STYLESHEET_CHANGING(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_RICHTEXT_STYLESHEET_CHANGING, id, -1, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxRichTextEventFunction, & fn ), NULL ),
+#define EVT_RICHTEXT_STYLESHEET_CHANGED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_RICHTEXT_STYLESHEET_CHANGED, id, -1, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxRichTextEventFunction, & fn ), NULL ),
+#define EVT_RICHTEXT_STYLESHEET_REPLACING(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACING, id, -1, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxRichTextEventFunction, & fn ), NULL ),
+#define EVT_RICHTEXT_STYLESHEET_REPLACED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACED, id, -1, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxRichTextEventFunction, & fn ), NULL ),
+
 #endif
     // wxUSE_RICHTEXT
 
diff --git a/include/wx/richtext/richtextformatdlg.h b/include/wx/richtext/richtextformatdlg.h
index 279231699e..af41de9086 100644
--- a/include/wx/richtext/richtextformatdlg.h
+++ b/include/wx/richtext/richtextformatdlg.h
@@ -46,6 +46,23 @@ class WXDLLIMPEXP_CORE wxImageList;
 
 #define wxRICHTEXT_FORMAT_HELP_BUTTON       0x0100
 
+/*!
+ * Indices for bullet styles in list control
+ */
+
+enum {
+    wxRICHTEXT_BULLETINDEX_NONE = 0,
+    wxRICHTEXT_BULLETINDEX_ARABIC,
+    wxRICHTEXT_BULLETINDEX_UPPER_CASE,
+    wxRICHTEXT_BULLETINDEX_LOWER_CASE,
+    wxRICHTEXT_BULLETINDEX_UPPER_CASE_ROMAN,
+    wxRICHTEXT_BULLETINDEX_LOWER_CASE_ROMAN,
+    wxRICHTEXT_BULLETINDEX_OUTLINE,
+    wxRICHTEXT_BULLETINDEX_SYMBOL,
+    wxRICHTEXT_BULLETINDEX_BITMAP,
+    wxRICHTEXT_BULLETINDEX_STANDARD
+};
+
 /*!
  * Shorthand for common combinations of pages
  */
diff --git a/include/wx/richtext/richtexthtml.h b/include/wx/richtext/richtexthtml.h
index 1ec4973f75..20c86ed60a 100644
--- a/include/wx/richtext/richtexthtml.h
+++ b/include/wx/richtext/richtexthtml.h
@@ -27,7 +27,7 @@ class WXDLLIMPEXP_RICHTEXT wxRichTextHTMLHandler: public wxRichTextFileHandler
     DECLARE_CLASS(wxRichTextHTMLHandler)
 public:
     wxRichTextHTMLHandler(const wxString& name = wxT("HTML"), const wxString& ext = wxT("html"), int type = wxRICHTEXT_TYPE_HTML)
-        : wxRichTextFileHandler(name, ext, type)
+        : wxRichTextFileHandler(name, ext, type), m_indent(0), m_font(false), m_list(false), m_is_ul(false)
         { }
 
     /// Can we save using this handler?
@@ -39,12 +39,38 @@ public:
     /// Can we handle this filename (if using files)? By default, checks the extension.
     virtual bool CanHandle(const wxString& filename) const;
 
+// Accessors and operations unique to this handler
+
+    /// Set and get the list of image locations generated by the last operation
+    void SetTemporaryImageLocations(const wxArrayString& locations) { m_imageLocations = locations; }
+    const wxArrayString& GetTemporaryImageLocations() const { return m_imageLocations; }
+
+    /// Clear the image locations generated by the last operation
+    void ClearTemporaryImageLocations() { m_imageLocations.Clear(); }
+
+    /// Delete the in-memory or temporary files generated by the last operation
+    bool DeleteTemporaryImages();
+
+    /// Delete the in-memory or temporary files generated by the last operation. This is a static
+    /// function that can be used to delete the saved locations from an earlier operation,
+    /// for example after the user has viewed the HTML file.
+    static bool DeleteTemporaryImages(int flags, const wxArrayString& imageLocations);
+
+    /// Reset the file counter, in case, for example, the same names are required each time
+    static void SetFileCounter(int counter) { sm_fileCounter = counter; }
+
+    /// Set and get the directory for storing temporary files. If empty, the system
+    /// temporary directory will be used.
+    void SetTempDir(const wxString& tempDir) { m_tempDir = tempDir; }
+    const wxString& GetTempDir() const { return m_tempDir; }
+
 protected:
 
+// Implementation
+
 #if wxUSE_STREAMS
     virtual bool DoLoadFile(wxRichTextBuffer *buffer, wxInputStream& stream);
     virtual bool DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream& stream);
-#endif
 
     /// Output character formatting
     virtual void BeginCharacterFormatting(const wxTextAttrEx& currentStyle, const wxTextAttrEx& thisStyle, const wxTextAttrEx& paraStyle, wxOutputStream& stream );
@@ -53,51 +79,62 @@ protected:
     /// Output paragraph formatting
     virtual void OutputParagraphFormatting(const wxTextAttrEx& WXUNUSED(currentStyle), const wxTextAttrEx& thisStyle, wxOutputStream& stream/*, bool start*/);
 
-    /// Converts an image to its base64 equivalent
-    void Image_to_Base64(wxRichTextImage* image, wxOutputStream& stream);
+    /// Writes an image to its base64 equivalent, or to the memory filesystem, or to a file
+    void WriteImage(wxRichTextImage* image, wxOutputStream& stream);
 
     /// Builds required indentation
-    void Indent( const wxTextAttrEx& thisStyle, wxTextOutputStream& str );
+    void Indent(const wxTextAttrEx& thisStyle, wxTextOutputStream& str);
 
     /// Left indent
-    void LIndent( const wxTextAttrEx& thisStyle, wxTextOutputStream& str );
+    void LIndent(const wxTextAttrEx& thisStyle, wxTextOutputStream& str);
 
     /// Converts from pt to size property compatible height
-    long Pt_To_Size(long size);
+    long PtToSize(long size);
 
     /// Typical base64 encoder
-    wxChar* b64enc( unsigned char* input, size_t in_len );
+    wxChar* b64enc(unsigned char* input, size_t in_len);
 
     /// Gets the mime type of the given wxBITMAP_TYPE
     const wxChar* GetMimeType(int imageType);
 
     /// Gets the html equivalent of the specified value
-    wxString GetAlignment( const wxTextAttrEx& thisStyle );
+    wxString GetAlignment(const wxTextAttrEx& thisStyle);
 
     /// Generates &nbsp; array for indentations
     wxString SymbolicIndent(long indent);
 
     /// Finds the html equivalent of the specified bullet
-    void TypeOfList( const wxTextAttrEx& thisStyle, wxString& tag );
+    void TypeOfList(const wxTextAttrEx& thisStyle, wxString& tag);
 
     /// Closes existings or Opens new tables for navigation to an item's horizontal position.
-    void NavigateToListPosition( const wxTextAttrEx& thisStyle, wxTextOutputStream& str );
+    void NavigateToListPosition(const wxTextAttrEx& thisStyle, wxTextOutputStream& str);
+#endif
+
+// Data members
 
     /// Indentation values of the table tags
-    wxArrayInt m_indents;
+    wxArrayInt      m_indents;
 
     /// Horizontal position of the current table
-    long m_indent;
+    long            m_indent;
 
     /// Is there any opened font tag
-    bool m_font;
+    bool            m_font;
 
     /// Is there any opened ul/ol tag
-    bool m_list;
+    bool            m_list;
 
     /// type of list, ul or ol?
-    bool m_is_ul;
+    bool            m_is_ul;
+
+    /// A list of the image files or in-memory images created by the last operation.
+    wxArrayString   m_imageLocations;
+
+    /// A location for the temporary files
+    wxString        m_tempDir;
 
+    /// A counter for generating filenames
+    static int      sm_fileCounter;
 };
 
 #endif
diff --git a/include/wx/richtext/richtextliststylepage.h b/include/wx/richtext/richtextliststylepage.h
index 0da975f787..5354ddef43 100644
--- a/include/wx/richtext/richtextliststylepage.h
+++ b/include/wx/richtext/richtextliststylepage.h
@@ -65,7 +65,7 @@ public:
     virtual bool TransferDataToWindow();
 
     /// Get attributes for selected level
-    wxTextAttrEx* GetAttributesForSelection();
+    wxRichTextAttr* GetAttributesForSelection();
 
     /// Update for symbol-related controls
     void OnSymbolUpdate( wxUpdateUIEvent& event );
@@ -117,6 +117,15 @@ public:
     /// wxEVT_UPDATE_UI event handler for ID_RICHTEXTLISTSTYLEPAGE_PARENTHESESCTRL
     void OnParenthesesctrlUpdate( wxUpdateUIEvent& event );
 
+    /// wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_RICHTEXTLISTSTYLEPAGE_RIGHTPARENTHESISCTRL
+    void OnRightParenthesisCtrlClick( wxCommandEvent& event );
+
+    /// wxEVT_UPDATE_UI event handler for ID_RICHTEXTLISTSTYLEPAGE_RIGHTPARENTHESISCTRL
+    void OnRightParenthesisCtrlUpdate( wxUpdateUIEvent& event );
+
+    /// wxEVT_COMMAND_COMBOBOX_SELECTED event handler for ID_RICHTEXTLISTSTYLEPAGE_BULLETALIGNMENTCTRL
+    void OnBulletAlignmentCtrlSelected( wxCommandEvent& event );
+
     /// wxEVT_UPDATE_UI event handler for ID_RICHTEXTLISTSTYLEPAGE_SYMBOLSTATIC
     void OnSymbolstaticUpdate( wxUpdateUIEvent& event );
 
@@ -208,6 +217,8 @@ public:
     wxListBox* m_styleListBox;
     wxCheckBox* m_periodCtrl;
     wxCheckBox* m_parenthesesCtrl;
+    wxCheckBox* m_rightParenthesisCtrl;
+    wxComboBox* m_bulletAlignmentCtrl;
     wxComboBox* m_symbolCtrl;
     wxComboBox* m_symbolFontCtrl;
     wxComboBox* m_bulletNameCtrl;
@@ -233,6 +244,8 @@ public:
         ID_RICHTEXTLISTSTYLEPAGE_STYLELISTBOX = 10620,
         ID_RICHTEXTLISTSTYLEPAGE_PERIODCTRL = 10627,
         ID_RICHTEXTLISTSTYLEPAGE_PARENTHESESCTRL = 10626,
+        ID_RICHTEXTLISTSTYLEPAGE_RIGHTPARENTHESISCTRL = 10602,
+        ID_RICHTEXTLISTSTYLEPAGE_BULLETALIGNMENTCTRL = 10603,
         ID_RICHTEXTLISTSTYLEPAGE_SYMBOLSTATIC = 10621,
         ID_RICHTEXTBULLETSPAGE_SYMBOLCTRL = 10622,
         ID_RICHTEXTBULLETSPAGE_CHOOSE_SYMBOL = 10623,
diff --git a/include/wx/richtext/richtextstyles.h b/include/wx/richtext/richtextstyles.h
index a5be1ee278..bce0f3399f 100644
--- a/include/wx/richtext/richtextstyles.h
+++ b/include/wx/richtext/richtextstyles.h
@@ -198,9 +198,9 @@ public:
     virtual wxRichTextStyleDefinition* Clone() const { return new wxRichTextListStyleDefinition(*this); }
 
     /// Sets/gets the attributes for the given level
-    void SetLevelAttributes(int i, const wxTextAttrEx& attr);
-    wxTextAttrEx* GetLevelAttributes(int i);
-    const wxTextAttrEx* GetLevelAttributes(int i) const;
+    void SetLevelAttributes(int i, const wxRichTextAttr& attr);
+    wxRichTextAttr* GetLevelAttributes(int i);
+    const wxRichTextAttr* GetLevelAttributes(int i) const;
 
     /// Convenience function for setting the major attributes for a list level specification
     void SetAttributes(int i, int leftIndent, int leftSubIndent, int bulletStyle, const wxString& bulletSymbol = wxEmptyString);
@@ -210,15 +210,15 @@ public:
 
     /// Combine the base and list style with a paragraph style, using the given indent (from which
     /// an appropriate level is found)
-    wxTextAttrEx CombineWithParagraphStyle(int indent, const wxTextAttrEx& paraStyle);
+    wxRichTextAttr CombineWithParagraphStyle(int indent, const wxRichTextAttr& paraStyle);
 
     /// Combine the base and list style, using the given indent (from which
     /// an appropriate level is found)
-    wxTextAttrEx GetCombinedStyle(int indent);
+    wxRichTextAttr GetCombinedStyle(int indent);
 
     /// Combine the base and list style, using the given level from which
     /// an appropriate level is found)
-    wxTextAttrEx GetCombinedStyleForLevel(int level);
+    wxRichTextAttr GetCombinedStyleForLevel(int level);
 
     /// Gets the number of available levels
     int GetLevelCount() const { return 10; }
@@ -229,7 +229,7 @@ public:
 protected:
 
     /// The styles for each level (up to 10)
-    wxTextAttrEx m_levelStyles[10];
+    wxRichTextAttr m_levelStyles[10];
 };
 
 /*!
diff --git a/include/wx/richtext/richtextxml.h b/include/wx/richtext/richtextxml.h
index 791e37e798..ef282fc67e 100644
--- a/include/wx/richtext/richtextxml.h
+++ b/include/wx/richtext/richtextxml.h
@@ -17,6 +17,7 @@
  */
 
 #include "wx/richtext/richtextbuffer.h"
+#include "wx/richtext/richtextstyles.h"
 
 #if wxUSE_RICHTEXT && wxUSE_XML
 
@@ -37,9 +38,11 @@ public:
 #if wxUSE_STREAMS
     /// Recursively export an object
     bool ExportXML(wxOutputStream& stream, wxMBConv* convMem, wxMBConv* convFile, wxRichTextObject& obj, int level);
+    bool ExportStyleDefinition(wxOutputStream& stream, wxMBConv* convMem, wxMBConv* convFile, wxRichTextStyleDefinition* def, int level);
 
     /// Recursively import an object
     bool ImportXML(wxRichTextBuffer* buffer, wxXmlNode* node);
+    bool ImportStyleDefinition(wxRichTextStyleSheet* sheet, wxXmlNode* node);
 
     /// Create style parameters
     wxString CreateStyle(const wxTextAttrEx& attr, bool isPara = false);
diff --git a/src/richtext/richtextbuffer.cpp b/src/richtext/richtextbuffer.cpp
index f1ed9eacf1..d250a15a0e 100644
--- a/src/richtext/richtextbuffer.cpp
+++ b/src/richtext/richtextbuffer.cpp
@@ -2153,20 +2153,20 @@ bool wxRichTextParagraphLayoutBox::CollectStyle(wxTextAttrEx& currentStyle, cons
             currentStyle.SetBulletNumber(style.GetBulletNumber());
     }
 
-    if (style.HasBulletSymbol() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_BULLET_SYMBOL))
+    if (style.HasBulletText() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_BULLET_TEXT))
     {
-        if (currentStyle.HasBulletSymbol())
+        if (currentStyle.HasBulletText())
         {
-            if (currentStyle.HasBulletSymbol() != style.HasBulletSymbol())
+            if (currentStyle.HasBulletText() != style.HasBulletText())
             {
                 // Clash of style - mark as such
-                multipleStyleAttributes |= wxTEXT_ATTR_BULLET_SYMBOL;
-                currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_BULLET_SYMBOL);
+                multipleStyleAttributes |= wxTEXT_ATTR_BULLET_TEXT;
+                currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_BULLET_TEXT);
             }
         }
         else
         {
-            currentStyle.SetBulletSymbol(style.GetBulletSymbol());
+            currentStyle.SetBulletText(style.GetBulletText());
             currentStyle.SetBulletFont(style.GetBulletFont());
         }
     }
@@ -2188,6 +2188,23 @@ bool wxRichTextParagraphLayoutBox::CollectStyle(wxTextAttrEx& currentStyle, cons
         }
     }
 
+    if (style.HasURL() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_URL))
+    {
+        if (currentStyle.HasURL())
+        {
+            if (currentStyle.HasURL() != style.HasURL())
+            {
+                // Clash of style - mark as such
+                multipleStyleAttributes |= wxTEXT_ATTR_URL;
+                currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_URL);
+            }
+        }
+        else
+        {
+            currentStyle.SetURL(style.GetURL());
+        }
+    }
+
     return true;
 }
 
@@ -2581,7 +2598,7 @@ bool wxRichTextParagraphLayoutBox::SetListStyle(const wxRichTextRange& range, wx
                     wxTextAttrEx listStyle(def->GetCombinedStyleForLevel(thisLevel));
                     wxRichTextApplyStyle(newPara->GetAttributes(), listStyle);
 
-                    // Now we need to check numbering
+                    // Now we need to do numbering
                     if (renumber)
                     {
                         newPara->GetAttributes().SetBulletNumber(n);
@@ -2596,9 +2613,10 @@ bool wxRichTextParagraphLayoutBox::SetListStyle(const wxRichTextRange& range, wx
 
                     newPara->GetAttributes().SetListStyleName(wxEmptyString);
                     newPara->GetAttributes().SetLeftIndent(0, 0);
+                    newPara->GetAttributes().SetBulletText(wxEmptyString);
 
                     // Eliminate the main list-related attributes
-                    newPara->GetAttributes().SetFlags(newPara->GetAttributes().GetFlags() & ~wxTEXT_ATTR_LEFT_INDENT & ~wxTEXT_ATTR_BULLET_STYLE & ~wxTEXT_ATTR_BULLET_NUMBER & ~wxTEXT_ATTR_BULLET_SYMBOL & wxTEXT_ATTR_LIST_STYLE_NAME);
+                    newPara->GetAttributes().SetFlags(newPara->GetAttributes().GetFlags() & ~wxTEXT_ATTR_LEFT_INDENT & ~wxTEXT_ATTR_BULLET_STYLE & ~wxTEXT_ATTR_BULLET_NUMBER & ~wxTEXT_ATTR_BULLET_TEXT & wxTEXT_ATTR_LIST_STYLE_NAME);
 
                     wxRichTextStyleSheet* styleSheet = GetStyleSheet();
                     if (styleSheet && !newPara->GetAttributes().GetParagraphStyleName().IsEmpty())
@@ -2670,9 +2688,9 @@ bool wxRichTextParagraphLayoutBox::DoNumberList(const wxRichTextRange& range, co
     for (i = 0; i < maxLevels; i++)
     {
         if (startFrom != -1)
-            levels[i] = startFrom;
+            levels[i] = startFrom-1;
         else if (renumber) // start again
-            levels[i] = 1;
+            levels[i] = 0;
         else
             levels[i] = -1; // start from the number we found, if any
     }
@@ -2736,9 +2754,8 @@ bool wxRichTextParagraphLayoutBox::DoNumberList(const wxRichTextRange& range, co
                     int thisIndent = newPara->GetAttributes().GetLeftIndent();
                     int thisLevel = defToUse->FindLevelForIndent(thisIndent);
 
-                    // If the paragraph doesn't have an indent, or we've specified a level to apply to all,
-                    // change the level.
-                    if (thisIndent == 0 || specifiedLevel != -1)
+                    // If we've specified a level to apply to all, change the level.
+                    if (specifiedLevel != -1)
                         thisLevel = specifiedLevel;
 
                     // Do promotion if specified
@@ -2769,7 +2786,7 @@ bool wxRichTextParagraphLayoutBox::DoNumberList(const wxRichTextRange& range, co
                     {
                         for (i = currentLevel+1; i <= thisLevel; i++)
                         {
-                            levels[i] = 1;
+                            levels[i] = 0;
                         }
                         currentLevel = thisLevel;
                     }
@@ -2786,10 +2803,25 @@ bool wxRichTextParagraphLayoutBox::DoNumberList(const wxRichTextRange& range, co
                         else
                             levels[currentLevel] = 1;
                     }
+                    else
+                    {
+                        levels[currentLevel] ++;
+                    }
 
                     newPara->GetAttributes().SetBulletNumber(levels[currentLevel]);
 
-                    levels[currentLevel] ++;
+                    // Create the bullet text if an outline list
+                    if (listStyle.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_OUTLINE)
+                    {
+                        wxString text;
+                        for (i = 0; i <= currentLevel; i++)
+                        {
+                            if (!text.IsEmpty())
+                                text += wxT(".");
+                            text += wxString::Format(wxT("%d"), levels[i]);
+                        }
+                        newPara->GetAttributes().SetBulletText(text);
+                    }
                 }
             }
         }
@@ -2846,6 +2878,68 @@ bool wxRichTextParagraphLayoutBox::PromoteList(int promoteBy, const wxRichTextRa
     return false;
 }
 
+/// Fills in the attributes for numbering a paragraph after previousParagraph. It also finds the
+/// position of the paragraph that it had to start looking from.
+bool wxRichTextParagraphLayoutBox::FindNextParagraphNumber(wxRichTextParagraph* previousParagraph, wxRichTextAttr& attr) const
+{
+#if 0
+    wxRichTextObjectList::compatibility_iterator node = m_children.Find(previousParagraph);
+    
+    if (!node)
+        return false;
+#endif
+    
+    if (!previousParagraph->GetAttributes().HasFlag(wxTEXT_ATTR_BULLET_STYLE) || previousParagraph->GetAttributes().GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_NONE)
+        return false;
+    
+    wxRichTextStyleSheet* sheet = GetStyleSheet();
+    if (sheet && !previousParagraph->GetAttributes().GetListStyleName().IsEmpty())
+    {
+        wxRichTextListStyleDefinition* def = sheet->FindListStyle(previousParagraph->GetAttributes().GetListStyleName());
+        if (def)
+        {
+            // int thisIndent = previousParagraph->GetAttributes().GetLeftIndent();
+            // int thisLevel = def->FindLevelForIndent(thisIndent);
+            
+            bool isOutline = (previousParagraph->GetAttributes().GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_OUTLINE) != 0;
+
+            attr.SetFlags(previousParagraph->GetAttributes().GetFlags() & (wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER|wxTEXT_ATTR_BULLET_TEXT|wxTEXT_ATTR_BULLET_NAME));
+            if (previousParagraph->GetAttributes().HasBulletName())
+                attr.SetBulletName(previousParagraph->GetAttributes().GetBulletName());
+            attr.SetBulletStyle(previousParagraph->GetAttributes().GetBulletStyle());
+            attr.SetListStyleName(previousParagraph->GetAttributes().GetListStyleName());
+            
+            int nextNumber = previousParagraph->GetAttributes().GetBulletNumber() + 1;
+            attr.SetBulletNumber(nextNumber);
+            
+            if (isOutline)
+            {
+                wxString text = previousParagraph->GetAttributes().GetBulletText();
+                if (!text.IsEmpty())
+                {
+                    int pos = text.Find(wxT('.'), true);
+                    if (pos != wxNOT_FOUND)
+                    {
+                        text = text.Mid(0, text.Length() - pos - 1);
+                    }
+                    else
+                        text = wxEmptyString;
+                    if (!text.IsEmpty())
+                        text += wxT(".");
+                    text += wxString::Format(wxT("%d"), nextNumber);
+                    attr.SetBulletText(text);
+                }
+            }
+            
+            return true;
+        }
+        else
+            return false;
+    }
+    else
+        return false;
+}
+
 /*!
  * wxRichTextParagraph
  * This object represents a single paragraph (or in a straight text editor, a line).
@@ -2897,24 +2991,20 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range),
             int spaceBeforePara = ConvertTenthsMMToPixels(dc, attr.GetParagraphSpacingBefore());
             int leftIndent = ConvertTenthsMMToPixels(dc, attr.GetLeftIndent());
 
-            if (attr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_BITMAP)
+            wxTextAttrEx bulletAttr(GetCombinedAttributes());
+
+            // Get line height from first line, if any
+            wxRichTextLine* line = m_cachedLines.GetFirst() ? (wxRichTextLine* ) m_cachedLines.GetFirst()->GetData() : (wxRichTextLine*) NULL;
+
+            wxPoint linePos;
+            int lineHeight wxDUMMY_INITIALIZE(0);
+            if (line)
             {
-                // TODO
+                lineHeight = line->GetSize().y;
+                linePos = line->GetPosition() + GetPosition();
             }
-            else if (attr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_STANDARD)                
+            else
             {
-                wxTextAttrEx bulletAttr(GetCombinedAttributes());
-                if (bulletAttr.GetTextColour().Ok())
-                {
-                    dc.SetPen(wxPen(bulletAttr.GetTextColour()));
-                    dc.SetBrush(wxBrush(bulletAttr.GetTextColour()));
-                }
-                else
-                {
-                    dc.SetPen(*wxBLACK_PEN);
-                    dc.SetBrush(*wxBLACK_BRUSH);
-                }
-
                 wxFont font;
                 if (bulletAttr.GetFont().Ok())
                     font = bulletAttr.GetFont();
@@ -2923,92 +3013,29 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range),
 
                 dc.SetFont(font);
 
-                // Get line height from first line, if any
-                wxRichTextLine* line = m_cachedLines.GetFirst() ? (wxRichTextLine* ) m_cachedLines.GetFirst()->GetData() : (wxRichTextLine*) NULL;
-
-                wxPoint linePos;
-                int lineHeight wxDUMMY_INITIALIZE(0);
-                if (line)
-                {
-                    lineHeight = line->GetSize().y;
-                    linePos = line->GetPosition() + GetPosition();
-                }
-                else
-                {
-                    lineHeight = dc.GetCharHeight();
-                    linePos = GetPosition();
-                    linePos.y += spaceBeforePara;
-                }
+                lineHeight = dc.GetCharHeight();
+                linePos = GetPosition();
+                linePos.y += spaceBeforePara;
+            }
 
-                int charHeight = dc.GetCharHeight();
-                
-                int bulletWidth = wxMax(2, (charHeight/3 + 1));
-                int bulletHeight = bulletWidth;
+            wxRect bulletRect(GetPosition().x + leftIndent, linePos.y, linePos.x - (GetPosition().x + leftIndent), lineHeight);
 
-                int x = GetPosition().x + leftIndent;
-                int y = linePos.y + (lineHeight - charHeight/2) - bulletHeight/2;
-                
-                if (bulletAttr.GetBulletName() == wxT("standard/square"))
-                {
-                    dc.DrawRectangle(x, y, bulletWidth, bulletHeight);
-                }
-                else // "standard/round", and catch-all
-                {
-                    dc.DrawEllipse(x, y, bulletWidth, bulletHeight);
-                }                
+            if (attr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_BITMAP)
+            {
+                if (wxRichTextBuffer::GetRenderer())
+                    wxRichTextBuffer::GetRenderer()->DrawBitmapBullet(this, dc, bulletAttr, bulletRect);
+            }
+            else if (attr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_STANDARD)                
+            {                
+                if (wxRichTextBuffer::GetRenderer())
+                    wxRichTextBuffer::GetRenderer()->DrawStandardBullet(this, dc, bulletAttr, bulletRect);
             }
             else
             {
                 wxString bulletText = GetBulletText();
-                if (!bulletText.empty())
-                {
-                    // Get the combined font, or if a font is specified for a symbol bullet,
-                    // create the font
-
-                    wxTextAttrEx bulletAttr(GetCombinedAttributes());
-                    wxFont font;
-                    if ((attr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_SYMBOL) && !attr.GetBulletFont().IsEmpty() && bulletAttr.GetFont().Ok())
-                    {
-                        font = (*wxTheFontList->FindOrCreateFont(bulletAttr.GetFont().GetPointSize(), bulletAttr.GetFont().GetFamily(),
-                                                bulletAttr.GetFont().GetStyle(), bulletAttr.GetFont().GetWeight(), bulletAttr.GetFont().GetUnderlined(),
-                                                attr.GetBulletFont()));
-                    }
-                    else if (bulletAttr.GetFont().Ok())
-                        font = bulletAttr.GetFont();
-                    else
-                        font = (*wxNORMAL_FONT);
-
-                    dc.SetFont(font);
-
-                    if (bulletAttr.GetTextColour().Ok())
-                        dc.SetTextForeground(bulletAttr.GetTextColour());
-
-                    dc.SetBackgroundMode(wxTRANSPARENT);
-
-                    // Get line height from first line, if any
-                    wxRichTextLine* line = m_cachedLines.GetFirst() ? (wxRichTextLine* ) m_cachedLines.GetFirst()->GetData() : (wxRichTextLine*) NULL;
-
-                    wxPoint linePos;
-                    int lineHeight wxDUMMY_INITIALIZE(0);
-                    if (line)
-                    {
-                        lineHeight = line->GetSize().y;
-                        linePos = line->GetPosition() + GetPosition();
-                    }
-                    else
-                    {
-                        lineHeight = dc.GetCharHeight();
-                        linePos = GetPosition();
-                        linePos.y += spaceBeforePara;
-                    }
-
-                    int charHeight = dc.GetCharHeight();
-
-                    int x = GetPosition().x + leftIndent;
-                    int y = linePos.y + (lineHeight - charHeight);
-
-                    dc.DrawText(bulletText, x, y);
-                }
+                
+                if (!bulletText.empty() && wxRichTextBuffer::GetRenderer())
+                    wxRichTextBuffer::GetRenderer()->DrawTextBullet(this, dc, bulletAttr, bulletRect, bulletText);
             }
         }
     }
@@ -3852,7 +3879,7 @@ wxString wxRichTextParagraph::GetBulletText()
     int number = GetAttributes().GetBulletNumber();
 
     wxString text;
-    if (GetAttributes().GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ARABIC)
+    if ((GetAttributes().GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ARABIC) || (GetAttributes().GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_OUTLINE))
     {
         text.Printf(wxT("%d"), number);
     }
@@ -3877,13 +3904,28 @@ wxString wxRichTextParagraph::GetBulletText()
     }
     else if (GetAttributes().GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_SYMBOL)
     {
-        text = GetAttributes().GetBulletSymbol();
+        text = GetAttributes().GetBulletText();
+    }
+    
+    if (GetAttributes().GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_OUTLINE)
+    {
+        // The outline style relies on the text being computed statically,
+        // since it depends on other levels points (e.g. 1.2.1.1). So normally the bullet text
+        // should be stored in the attributes; if not, just use the number for this
+        // level, as previously computed.
+        if (!GetAttributes().GetBulletText().IsEmpty())
+            text = GetAttributes().GetBulletText();
     }
 
     if (GetAttributes().GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_PARENTHESES)
     {
         text = wxT("(") + text + wxT(")");
     }
+    else if (GetAttributes().GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_RIGHT_PARENTHESIS)
+    {
+        text = text + wxT(")");
+    }
+
     if (GetAttributes().GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_PERIOD)
     {
         text += wxT(".");
@@ -4453,7 +4495,10 @@ void wxRichTextPlainText::Dump(wxTextOutputStream& stream)
 
 IMPLEMENT_DYNAMIC_CLASS(wxRichTextBuffer, wxRichTextParagraphLayoutBox)
 
-wxList wxRichTextBuffer::sm_handlers;
+wxList                  wxRichTextBuffer::sm_handlers;
+wxRichTextRenderer*     wxRichTextBuffer::sm_renderer = NULL;
+int                     wxRichTextBuffer::sm_bulletRightMargin = 20;
+float                   wxRichTextBuffer::sm_bulletProportion = (float) 0.3;
 
 /// Initialisation
 void wxRichTextBuffer::Init()
@@ -4464,6 +4509,7 @@ void wxRichTextBuffer::Init()
     m_batchedCommandDepth = 0;
     m_batchedCommand = NULL;
     m_suppressUndo = 0;
+    m_handlerFlags = 0;
 }
 
 /// Initialisation
@@ -4473,6 +4519,7 @@ wxRichTextBuffer::~wxRichTextBuffer()
     delete m_batchedCommand;
 
     ClearStyleStack();
+    ClearEventHandlers();
 }
 
 void wxRichTextBuffer::Clear()
@@ -4703,24 +4750,52 @@ wxRichTextAttr wxRichTextBuffer::GetStyleForNewParagraph(long pos, bool caretPos
     wxRichTextParagraph* para = GetParagraphAtPosition(pos, caretPosition);
     if (para)
     {
+        wxRichTextAttr attr;
+        bool foundAttributes = false;
+        
+        // Look for a matching paragraph style
         if (!para->GetAttributes().GetParagraphStyleName().IsEmpty() && GetStyleSheet())
         {
             wxRichTextParagraphStyleDefinition* paraDef = GetStyleSheet()->FindParagraphStyle(para->GetAttributes().GetParagraphStyleName());
-            if (paraDef && !paraDef->GetNextStyle().IsEmpty())
+            if (paraDef)
             {
-                wxRichTextParagraphStyleDefinition* nextParaDef = GetStyleSheet()->FindParagraphStyle(paraDef->GetNextStyle());
-                if (nextParaDef)
-                    return nextParaDef->GetStyle();
+                if (!paraDef->GetNextStyle().IsEmpty())
+                {
+                    wxRichTextParagraphStyleDefinition* nextParaDef = GetStyleSheet()->FindParagraphStyle(paraDef->GetNextStyle());
+                    if (nextParaDef)
+                    {
+                        foundAttributes = true;
+                        attr = nextParaDef->GetStyle();
+                    }
+                }
+                
+                // If we didn't find the 'next style', use this style instead.
+                if (!foundAttributes)
+                {
+                    foundAttributes = true;
+                    attr = paraDef->GetStyle();
+                }
             }
         }
-        wxRichTextAttr attr(para->GetAttributes());
-        int flags = attr.GetFlags();
+        if (!foundAttributes)
+        {
+            attr = para->GetAttributes();
+            int flags = attr.GetFlags();
 
-        // Eliminate character styles
-        flags &= ( (~ wxTEXT_ATTR_FONT) |
+            // Eliminate character styles
+            flags &= ( (~ wxTEXT_ATTR_FONT) |
                     (~ wxTEXT_ATTR_TEXT_COLOUR) |
                     (~ wxTEXT_ATTR_BACKGROUND_COLOUR) );
-        attr.SetFlags(flags);
+            attr.SetFlags(flags);
+        }
+        
+        // Now see if we need to number the paragraph.
+        if (attr.HasBulletStyle())
+        {
+            wxRichTextAttr numberingAttr;
+            if (FindNextParagraphNumber(para, numberingAttr))
+                wxRichTextApplyStyle(attr, numberingAttr);
+        }
 
         return attr;
     }
@@ -5025,13 +5100,13 @@ bool wxRichTextBuffer::BeginNumberedBullet(int bulletNumber, int leftIndent, int
 }
 
 /// Begin symbol bullet
-bool wxRichTextBuffer::BeginSymbolBullet(wxChar symbol, int leftIndent, int leftSubIndent, int bulletStyle)
+bool wxRichTextBuffer::BeginSymbolBullet(const wxString& symbol, int leftIndent, int leftSubIndent, int bulletStyle)
 {
     wxTextAttrEx attr;
     attr.SetFlags(wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_LEFT_INDENT);
     attr.SetBulletStyle(bulletStyle);
     attr.SetLeftIndent(leftIndent, leftSubIndent);
-    attr.SetBulletSymbol(symbol);
+    attr.SetBulletText(symbol);
 
     return BeginStyle(attr);
 }
@@ -5098,6 +5173,24 @@ bool wxRichTextBuffer::BeginListStyle(const wxString& listStyle, int level, int
     return false;
 }
 
+/// Begin URL
+bool wxRichTextBuffer::BeginURL(const wxString& url, const wxString& characterStyle)
+{
+    wxTextAttrEx attr;
+
+    if (!characterStyle.IsEmpty() && GetStyleSheet())
+    {
+        wxRichTextCharacterStyleDefinition* def = GetStyleSheet()->FindCharacterStyle(characterStyle);
+        if (def)
+        {
+            def->GetStyle().CopyTo(attr);
+        }
+    }
+    attr.SetURL(url);
+
+    return BeginStyle(attr);
+}
+
 /// Adds a handler to the end
 void wxRichTextBuffer::AddHandler(wxRichTextFileHandler *handler)
 {
@@ -5249,14 +5342,12 @@ wxString wxRichTextBuffer::GetExtWildcard(bool combine, bool save, wxArrayInt* t
 
 /// Load a file
 bool wxRichTextBuffer::LoadFile(const wxString& filename, int type)
-
-
 {
     wxRichTextFileHandler* handler = FindHandlerFilenameOrType(filename, type);
     if (handler)
     {
         SetDefaultStyle(wxTextAttrEx());
-
+        handler->SetFlags(GetHandlerFlags());
         bool success = handler->LoadFile(this, filename);
         Invalidate(wxRICHTEXT_ALL);
         return success;
@@ -5270,7 +5361,10 @@ bool wxRichTextBuffer::SaveFile(const wxString& filename, int type)
 {
     wxRichTextFileHandler* handler = FindHandlerFilenameOrType(filename, type);
     if (handler)
+    {
+        handler->SetFlags(GetHandlerFlags());
         return handler->SaveFile(this, filename);
+    }
     else
         return false;
 }
@@ -5282,6 +5376,7 @@ bool wxRichTextBuffer::LoadFile(wxInputStream& stream, int type)
     if (handler)
     {
         SetDefaultStyle(wxTextAttrEx());
+        handler->SetFlags(GetHandlerFlags());
         bool success = handler->LoadFile(this, stream);
         Invalidate(wxRICHTEXT_ALL);
         return success;
@@ -5295,7 +5390,10 @@ bool wxRichTextBuffer::SaveFile(wxOutputStream& stream, int type)
 {
     wxRichTextFileHandler* handler = FindHandler(type);
     if (handler)
+    {
+        handler->SetFlags(GetHandlerFlags());
         return handler->SaveFile(this, stream);
+    }
     else
         return false;
 }
@@ -5441,6 +5539,234 @@ void wxRichTextBuffer::Dump()
     wxLogDebug(text);
 }
 
+/// Add an event handler
+bool wxRichTextBuffer::AddEventHandler(wxEvtHandler* handler)
+{
+    m_eventHandlers.Append(handler);
+    return true;
+}
+
+/// Remove an event handler
+bool wxRichTextBuffer::RemoveEventHandler(wxEvtHandler* handler, bool deleteHandler)
+{
+    wxList::compatibility_iterator node = m_eventHandlers.Find(handler);
+    if (node)
+    {
+        m_eventHandlers.Erase(node);
+        if (deleteHandler)
+            delete handler;
+        
+        return true;
+    }
+    else
+        return false;
+}
+
+/// Clear event handlers
+void wxRichTextBuffer::ClearEventHandlers()
+{
+    m_eventHandlers.Clear();
+}
+
+/// Send event to event handlers. If sendToAll is true, will send to all event handlers,
+/// otherwise will stop at the first successful one.
+bool wxRichTextBuffer::SendEvent(wxEvent& event, bool sendToAll)
+{
+    bool success = false;
+    for (wxList::compatibility_iterator node = m_eventHandlers.GetFirst(); node; node = node->GetNext())
+    {
+        wxEvtHandler* handler = (wxEvtHandler*) node->GetData();
+        if (handler->ProcessEvent(event))
+        {
+            success = true;
+            if (!sendToAll)
+                return true;
+        }
+    }
+    return success;
+}
+
+/// Set style sheet and notify of the change
+bool wxRichTextBuffer::SetStyleSheetAndNotify(wxRichTextStyleSheet* sheet)
+{
+    wxRichTextStyleSheet* oldSheet = GetStyleSheet();
+    
+    wxWindowID id = wxID_ANY;
+    if (GetRichTextCtrl())
+        id = GetRichTextCtrl()->GetId();
+    
+    wxRichTextEvent event(wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACING, id);
+    event.SetEventObject(GetRichTextCtrl());
+    event.SetOldStyleSheet(oldSheet);
+    event.SetNewStyleSheet(sheet);
+    event.Allow();
+    
+    if (SendEvent(event) && !event.IsAllowed())
+    {
+        if (sheet != oldSheet)
+            delete sheet;
+
+        return false;
+    }
+
+    if (oldSheet && oldSheet != sheet)
+        delete oldSheet;
+
+    SetStyleSheet(sheet);
+
+    event.SetEventType(wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACED);
+    event.SetOldStyleSheet(NULL);
+    event.Allow();
+
+    return SendEvent(event);
+}
+
+/// Set renderer, deleting old one
+void wxRichTextBuffer::SetRenderer(wxRichTextRenderer* renderer)
+{
+    if (sm_renderer)
+        delete sm_renderer;
+    sm_renderer = renderer;
+}
+
+bool wxRichTextStdRenderer::DrawStandardBullet(wxRichTextParagraph* WXUNUSED(paragraph), wxDC& dc, const wxTextAttrEx& bulletAttr, const wxRect& rect)
+{
+    if (bulletAttr.GetTextColour().Ok())
+    {
+        dc.SetPen(wxPen(bulletAttr.GetTextColour()));
+        dc.SetBrush(wxBrush(bulletAttr.GetTextColour()));
+    }
+    else
+    {
+        dc.SetPen(*wxBLACK_PEN);
+        dc.SetBrush(*wxBLACK_BRUSH);
+    }
+
+    wxFont font;
+    if (bulletAttr.GetFont().Ok())
+        font = bulletAttr.GetFont();
+    else
+        font = (*wxNORMAL_FONT);
+
+    dc.SetFont(font);
+
+    int charHeight = dc.GetCharHeight();
+                
+    int bulletWidth = (int) (((float) charHeight) * wxRichTextBuffer::GetBulletProportion());
+    int bulletHeight = bulletWidth;
+
+    int x = rect.x;
+    
+    // Calculate the top position of the character (as opposed to the whole line height)
+    int y = rect.y + (rect.height - charHeight);
+    
+    // Calculate where the bullet should be positioned
+    y = y + (charHeight+1)/2 - (bulletHeight+1)/2;
+                
+    // The margin between a bullet and text.
+    int margin = wxRichTextObject::ConvertTenthsMMToPixels(dc, wxRichTextBuffer::GetBulletRightMargin());
+                
+    if (bulletAttr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ALIGN_RIGHT)
+        x = rect.x + rect.width - bulletWidth - margin;
+    else if (bulletAttr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ALIGN_CENTRE)
+        x = x + (rect.width)/2 - bulletWidth/2;
+                
+    if (bulletAttr.GetBulletName() == wxT("standard/square"))
+    {
+        dc.DrawRectangle(x, y, bulletWidth, bulletHeight);
+    }
+    else if (bulletAttr.GetBulletName() == wxT("standard/diamond"))
+    {
+        wxPoint pts[5];
+        pts[0].x = x;                   pts[0].y = y + bulletHeight/2;
+        pts[1].x = x + bulletWidth/2;   pts[1].y = y;
+        pts[2].x = x + bulletWidth;     pts[2].y = y + bulletHeight/2;
+        pts[3].x = x + bulletWidth/2;   pts[3].y = y + bulletHeight;
+                    
+        dc.DrawPolygon(4, pts);
+    }
+    else if (bulletAttr.GetBulletName() == wxT("standard/triangle"))
+    {
+        wxPoint pts[3];
+        pts[0].x = x;                   pts[0].y = y;
+        pts[1].x = x + bulletWidth;     pts[1].y = y + bulletHeight/2;
+        pts[2].x = x;                   pts[2].y = y + bulletHeight;
+                    
+        dc.DrawPolygon(3, pts);
+    }
+    else // "standard/circle", and catch-all
+    {
+        dc.DrawEllipse(x, y, bulletWidth, bulletHeight);
+    }                
+ 
+    return true;
+}
+
+bool wxRichTextStdRenderer::DrawTextBullet(wxRichTextParagraph* WXUNUSED(paragraph), wxDC& dc, const wxTextAttrEx& attr, const wxRect& rect, const wxString& text)
+{
+    if (!text.empty())
+    {
+        wxFont font;
+        if ((attr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_SYMBOL) && !attr.GetBulletFont().IsEmpty() && attr.GetFont().Ok())
+        {
+            font = (*wxTheFontList->FindOrCreateFont(attr.GetFont().GetPointSize(), attr.GetFont().GetFamily(),
+                        attr.GetFont().GetStyle(), attr.GetFont().GetWeight(), attr.GetFont().GetUnderlined(),
+                        attr.GetBulletFont()));
+        }
+        else if (attr.GetFont().Ok())
+            font = attr.GetFont();
+        else
+            font = (*wxNORMAL_FONT);
+
+        dc.SetFont(font);
+
+        if (attr.GetTextColour().Ok())
+            dc.SetTextForeground(attr.GetTextColour());
+
+        dc.SetBackgroundMode(wxTRANSPARENT);
+
+        int charHeight = dc.GetCharHeight();
+        wxCoord tw, th;
+        dc.GetTextExtent(text, & tw, & th);
+
+        int x = rect.x;
+
+        // Calculate the top position of the character (as opposed to the whole line height)
+        int y = rect.y + (rect.height - charHeight);    
+
+        // The margin between a bullet and text.
+        int margin = wxRichTextObject::ConvertTenthsMMToPixels(dc, wxRichTextBuffer::GetBulletRightMargin());
+                
+        if (attr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ALIGN_RIGHT)
+            x = (rect.x + rect.width) - tw - margin;
+        else if (attr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ALIGN_CENTRE)
+            x = x + (rect.width)/2 - tw/2;
+
+        dc.DrawText(text, x, y);
+        
+        return true;
+    }
+    else
+        return false;
+}
+
+bool wxRichTextStdRenderer::DrawBitmapBullet(wxRichTextParagraph* WXUNUSED(paragraph), wxDC& WXUNUSED(dc), const wxTextAttrEx& WXUNUSED(attr), const wxRect& WXUNUSED(rect))
+{
+    // Currently unimplemented. The intention is to store bitmaps by name in a media store associated
+    // with the buffer. The store will allow retrieval from memory, disk or other means.
+    return false;
+}
+
+/// Enumerate the standard bullet names currently supported
+bool wxRichTextStdRenderer::EnumerateStandardBulletNames(wxArrayString& bulletNames)
+{
+    bulletNames.Add(wxT("standard/circle"));
+    bulletNames.Add(wxT("standard/square"));
+    bulletNames.Add(wxT("standard/diamond"));
+    bulletNames.Add(wxT("standard/triangle"));
+
+    return true;
+}
 
 /*
  * Module to initialise and clean up handlers
@@ -5453,6 +5779,7 @@ public:
     wxRichTextModule() {}
     bool OnInit()
     {
+        wxRichTextBuffer::SetRenderer(new wxRichTextStdRenderer);
         wxRichTextBuffer::InitStandardHandlers();
         wxRichTextParagraph::InitDefaultTabs();
         return true;
@@ -5463,6 +5790,7 @@ public:
         wxRichTextDecimalToRoman(-1);
         wxRichTextParagraph::ClearDefaultTabs();
         wxRichTextCtrl::ClearAvailableFontNames();
+        wxRichTextBuffer::SetRenderer(NULL);
     };
 };
 
@@ -5862,7 +6190,7 @@ bool wxTextAttrEq(const wxTextAttrEx& attr1, const wxRichTextAttr& attr2)
         attr1.GetParagraphSpacingBefore() == attr2.GetParagraphSpacingBefore() &&
         attr1.GetBulletStyle() == attr2.GetBulletStyle() &&
         attr1.GetBulletNumber() == attr2.GetBulletNumber() &&
-        attr1.GetBulletSymbol() == attr2.GetBulletSymbol() &&
+        attr1.GetBulletText() == attr2.GetBulletText() &&
         attr1.GetBulletName() == attr2.GetBulletName() &&
         attr1.GetBulletFont() == attr2.GetBulletFont() &&
         attr1.GetCharacterStyleName() == attr2.GetCharacterStyleName() &&
@@ -5943,8 +6271,8 @@ bool wxTextAttrEqPartial(const wxTextAttrEx& attr1, const wxTextAttrEx& attr2, i
         (attr1.GetBulletNumber() != attr2.GetBulletNumber()))
          return false;
 
-    if ((flags & wxTEXT_ATTR_BULLET_SYMBOL) &&
-        (attr1.GetBulletSymbol() != attr2.GetBulletSymbol()) &&
+    if ((flags & wxTEXT_ATTR_BULLET_TEXT) &&
+        (attr1.GetBulletText() != attr2.GetBulletText()) &&
         (attr1.GetBulletFont() != attr2.GetBulletFont()))
          return false;
 
@@ -6033,8 +6361,8 @@ bool wxTextAttrEqPartial(const wxTextAttrEx& attr1, const wxRichTextAttr& attr2,
         (attr1.GetBulletNumber() != attr2.GetBulletNumber()))
          return false;
 
-    if ((flags & wxTEXT_ATTR_BULLET_SYMBOL) &&
-        (attr1.GetBulletSymbol() != attr2.GetBulletSymbol()) &&
+    if ((flags & wxTEXT_ATTR_BULLET_TEXT) &&
+        (attr1.GetBulletText() != attr2.GetBulletText()) &&
         (attr1.GetBulletFont() != attr2.GetBulletFont()))
          return false;
 
@@ -6154,9 +6482,9 @@ bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxTextAttrEx& style)
     if (style.HasBulletStyle())
         destStyle.SetBulletStyle(style.GetBulletStyle());
 
-    if (style.HasBulletSymbol())
+    if (style.HasBulletText())
     {
-        destStyle.SetBulletSymbol(style.GetBulletSymbol());
+        destStyle.SetBulletText(style.GetBulletText());
         destStyle.SetBulletFont(style.GetBulletFont());
     }
 
@@ -6166,6 +6494,9 @@ bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxTextAttrEx& style)
     if (style.HasBulletNumber())
         destStyle.SetBulletNumber(style.GetBulletNumber());
 
+    if (style.HasURL())
+        destStyle.SetURL(style.GetURL());
+
     return true;
 }
 
@@ -6345,11 +6676,11 @@ bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style,
             destStyle.SetBulletStyle(style.GetBulletStyle());
     }
 
-    if (style.HasBulletSymbol())
+    if (style.HasBulletText())
     {
-        if (!(compareWith && compareWith->HasBulletSymbol() && compareWith->GetBulletSymbol() == style.GetBulletSymbol()))
+        if (!(compareWith && compareWith->HasBulletText() && compareWith->GetBulletText() == style.GetBulletText()))
         {
-            destStyle.SetBulletSymbol(style.GetBulletSymbol());
+            destStyle.SetBulletText(style.GetBulletText());
             destStyle.SetBulletFont(style.GetBulletFont());
         }
     }
@@ -6366,6 +6697,12 @@ bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style,
             destStyle.SetBulletName(style.GetBulletName());
     }
 
+    if (style.HasURL())
+    {
+        if (!(compareWith && compareWith->HasURL() && compareWith->GetURL() == style.GetURL()))
+            destStyle.SetURL(style.GetURL());
+    }
+
     return true;
 }
 
@@ -6429,7 +6766,6 @@ wxString wxRichTextDecimalToRoman(long n)
     return roman;
 }
 
-
 /*!
  * wxRichTextAttr stores attributes without a wxFont object, so is a much more
  * efficient way to query styles.
@@ -6455,6 +6791,11 @@ wxRichTextAttr::wxRichTextAttr(const wxTextAttrEx& attr)
     (*this) = attr;
 }
 
+wxRichTextAttr::wxRichTextAttr(const wxRichTextAttr& attr)
+{
+    Copy(attr);
+}
+
 // operations
 void wxRichTextAttr::Init()
 {
@@ -6474,11 +6815,10 @@ void wxRichTextAttr::Init()
     m_lineSpacing = 0;
     m_bulletStyle = wxTEXT_ATTR_BULLET_STYLE_NONE;
     m_bulletNumber = 0;
-    m_bulletSymbol = wxT('*');
 }
 
-// operators
-void wxRichTextAttr::operator= (const wxRichTextAttr& attr)
+// Copy
+void wxRichTextAttr::Copy(const wxRichTextAttr& attr)
 {
     m_colText = attr.m_colText;
     m_colBack = attr.m_colBack;
@@ -6503,9 +6843,17 @@ void wxRichTextAttr::operator= (const wxRichTextAttr& attr)
     m_listStyleName = attr.m_listStyleName;
     m_bulletStyle = attr.m_bulletStyle;
     m_bulletNumber = attr.m_bulletNumber;
-    m_bulletSymbol = attr.m_bulletSymbol;
+    m_bulletText = attr.m_bulletText;
     m_bulletFont = attr.m_bulletFont;
     m_bulletName = attr.m_bulletName;
+
+    m_urlTarget = attr.m_urlTarget;
+}
+
+// operators
+void wxRichTextAttr::operator= (const wxRichTextAttr& attr)
+{    
+    Copy(attr);
 }
 
 // operators
@@ -6528,10 +6876,12 @@ void wxRichTextAttr::operator= (const wxTextAttrEx& attr)
     m_listStyleName = attr.GetListStyleName();
     m_bulletStyle = attr.GetBulletStyle();
     m_bulletNumber = attr.GetBulletNumber();
-    m_bulletSymbol = attr.GetBulletSymbol();
+    m_bulletText = attr.GetBulletText();
     m_bulletName = attr.GetBulletName();
     m_bulletFont = attr.GetBulletFont();
 
+    m_urlTarget = attr.GetURL();
+
     if (attr.GetFont().Ok())
         GetFontAttributes(attr.GetFont());
 }
@@ -6566,7 +6916,7 @@ bool wxRichTextAttr::operator== (const wxRichTextAttr& attr) const
             GetListStyleName() == attr.GetListStyleName() &&
 
             GetBulletStyle() == attr.GetBulletStyle() &&
-            GetBulletSymbol() == attr.GetBulletSymbol() &&
+            GetBulletText() == attr.GetBulletText() &&
             GetBulletNumber() == attr.GetBulletNumber() &&
             GetBulletFont() == attr.GetBulletFont() &&
             GetBulletName() == attr.GetBulletName() &&
@@ -6575,7 +6925,9 @@ bool wxRichTextAttr::operator== (const wxRichTextAttr& attr) const
             m_fontStyle == attr.m_fontStyle &&
             m_fontWeight == attr.m_fontWeight &&
             m_fontUnderlined == attr.m_fontUnderlined &&
-            m_fontFaceName == attr.m_fontFaceName;
+            m_fontFaceName == attr.m_fontFaceName &&
+            
+            m_urlTarget == attr.m_urlTarget;
 }
 
 // Copy to a wxTextAttr
@@ -6594,13 +6946,15 @@ void wxRichTextAttr::CopyTo(wxTextAttrEx& attr) const
     attr.SetLineSpacing(m_lineSpacing);
     attr.SetBulletStyle(m_bulletStyle);
     attr.SetBulletNumber(m_bulletNumber);
-    attr.SetBulletSymbol(m_bulletSymbol);
+    attr.SetBulletText(m_bulletText);
     attr.SetBulletName(m_bulletName);
     attr.SetBulletFont(m_bulletFont);
     attr.SetCharacterStyleName(m_characterStyleName);
     attr.SetParagraphStyleName(m_paragraphStyleName);
     attr.SetListStyleName(m_listStyleName);
 
+    attr.SetURL(m_urlTarget);
+
     attr.SetFlags(GetFlags()); // Important: set after SetFont and others, since they set flags
 }
 
@@ -6717,12 +7071,15 @@ wxRichTextAttr wxRichTextAttr::Combine(const wxRichTextAttr& attr,
     if (attr.HasBulletName())
         newAttr.SetBulletName(attr.GetBulletName());
 
-    if (attr.HasBulletSymbol())
+    if (attr.HasBulletText())
     {
-        newAttr.SetBulletSymbol(attr.GetBulletSymbol());
+        newAttr.SetBulletText(attr.GetBulletText());
         newAttr.SetBulletFont(attr.GetBulletFont());
     }
 
+    if (attr.HasURL())
+        newAttr.SetURL(attr.GetURL());
+
     return newAttr;
 }
 
@@ -6730,19 +7087,9 @@ wxRichTextAttr wxRichTextAttr::Combine(const wxRichTextAttr& attr,
  * wxTextAttrEx is an extended version of wxTextAttr with more paragraph attributes.
  */
 
-wxTextAttrEx::wxTextAttrEx(const wxTextAttrEx& attr): wxTextAttr(attr)
+wxTextAttrEx::wxTextAttrEx(const wxTextAttrEx& attr)
 {
-    m_paragraphSpacingAfter = attr.m_paragraphSpacingAfter;
-    m_paragraphSpacingBefore = attr.m_paragraphSpacingBefore;
-    m_lineSpacing = attr.m_lineSpacing;
-    m_paragraphStyleName = attr.m_paragraphStyleName;
-    m_characterStyleName = attr.m_characterStyleName;
-    m_listStyleName = attr.m_listStyleName;
-    m_bulletStyle = attr.m_bulletStyle;
-    m_bulletNumber = attr.m_bulletNumber;
-    m_bulletSymbol = attr.m_bulletSymbol;
-    m_bulletName = attr.m_bulletName;
-    m_bulletFont = attr.m_bulletFont;
+    Copy(attr);
 }
 
 // Initialise this object.
@@ -6753,11 +7100,10 @@ void wxTextAttrEx::Init()
     m_lineSpacing = 0;
     m_bulletStyle = wxTEXT_ATTR_BULLET_STYLE_NONE;
     m_bulletNumber = 0;
-    m_bulletSymbol = wxT('*');
 }
 
-// Assignment from a wxTextAttrEx object
-void wxTextAttrEx::operator= (const wxTextAttrEx& attr)
+// Copy
+void wxTextAttrEx::Copy(const wxTextAttrEx& attr)
 {
     wxTextAttr::operator= (attr);
 
@@ -6769,9 +7115,16 @@ void wxTextAttrEx::operator= (const wxTextAttrEx& attr)
     m_listStyleName = attr.m_listStyleName;
     m_bulletStyle = attr.m_bulletStyle;
     m_bulletNumber = attr.m_bulletNumber;
-    m_bulletSymbol = attr.m_bulletSymbol;
+    m_bulletText = attr.m_bulletText;
     m_bulletFont = attr.m_bulletFont;
     m_bulletName = attr.m_bulletName;
+    m_urlTarget = attr.m_urlTarget;
+}
+
+// Assignment from a wxTextAttrEx object
+void wxTextAttrEx::operator= (const wxTextAttrEx& attr)
+{
+    Copy(attr);
 }
 
 // Assignment from a wxTextAttr object.
@@ -6797,12 +7150,13 @@ bool wxTextAttrEx::operator== (const wxTextAttrEx& attr) const
         GetParagraphSpacingBefore() == attr.GetParagraphSpacingBefore() &&
         GetBulletStyle() == attr.GetBulletStyle() &&
         GetBulletNumber() == attr.GetBulletNumber() &&
-        GetBulletSymbol() == attr.GetBulletSymbol() &&
+        GetBulletText() == attr.GetBulletText() &&
         GetBulletName() == attr.GetBulletName() &&
         GetBulletFont() == attr.GetBulletFont() &&
         GetCharacterStyleName() == attr.GetCharacterStyleName() &&
         GetParagraphStyleName() == attr.GetParagraphStyleName() &&
-        GetListStyleName() == attr.GetListStyleName());
+        GetListStyleName() == attr.GetListStyleName() &&
+        GetURL() == attr.GetURL());
 }
 
 wxTextAttrEx wxTextAttrEx::CombineEx(const wxTextAttrEx& attr,
@@ -6944,12 +7298,15 @@ wxTextAttrEx wxTextAttrEx::CombineEx(const wxTextAttrEx& attr,
     if (attr.HasBulletName())
         newAttr.SetBulletName(attr.GetBulletName());
 
-    if (attr.HasBulletSymbol())
+    if (attr.HasBulletText())
     {
-        newAttr.SetBulletSymbol(attr.GetBulletSymbol());
+        newAttr.SetBulletText(attr.GetBulletText());
         newAttr.SetBulletFont(attr.GetBulletFont());
     }
 
+    if (attr.HasURL())
+        newAttr.SetURL(attr.GetURL());
+
     return newAttr;
 }
 
@@ -7307,6 +7664,16 @@ bool wxRichTextImageBlock::WriteBlock(const wxString& filename, unsigned char* b
     return WriteBlock(outStream, block, size);
 }
 
+// Gets the extension for the block's type
+wxString wxRichTextImageBlock::GetExtension() const
+{
+    wxImageHandler* handler = wxImage::FindHandler(GetImageType());
+    if (handler)
+        return handler->GetExtension();
+    else
+        return wxEmptyString;
+}
+
 #if wxUSE_DATAOBJ
 
 /*!
diff --git a/src/richtext/richtextbulletspage.cpp b/src/richtext/richtextbulletspage.cpp
index 2a3cc06244..17057047b2 100644
--- a/src/richtext/richtextbulletspage.cpp
+++ b/src/richtext/richtextbulletspage.cpp
@@ -36,13 +36,10 @@ BEGIN_EVENT_TABLE( wxRichTextBulletsPage, wxPanel )
     EVT_CHECKBOX( ID_RICHTEXTBULLETSPAGE_PARENTHESESCTRL, wxRichTextBulletsPage::OnParenthesesctrlClick )
     EVT_UPDATE_UI( ID_RICHTEXTBULLETSPAGE_PARENTHESESCTRL, wxRichTextBulletsPage::OnParenthesesctrlUpdate )
 
-    EVT_UPDATE_UI( ID_RICHTEXTBULLETSPAGE_NUMBERSTATIC, wxRichTextBulletsPage::OnNumberstaticUpdate )
+    EVT_CHECKBOX( ID_RICHTEXTBULLETSPAGE_RIGHTPARENTHESISCTRL, wxRichTextBulletsPage::OnRightParenthesisCtrlClick )
+    EVT_UPDATE_UI( ID_RICHTEXTBULLETSPAGE_RIGHTPARENTHESISCTRL, wxRichTextBulletsPage::OnRightParenthesisCtrlUpdate )
 
-    EVT_SPINCTRL( ID_RICHTEXTBULLETSPAGE_NUMBERCTRL, wxRichTextBulletsPage::OnNumberctrlUpdated )
-    EVT_SPIN_UP( ID_RICHTEXTBULLETSPAGE_NUMBERCTRL, wxRichTextBulletsPage::OnNumberctrlUp )
-    EVT_SPIN_DOWN( ID_RICHTEXTBULLETSPAGE_NUMBERCTRL, wxRichTextBulletsPage::OnNumberctrlDown )
-    EVT_TEXT( ID_RICHTEXTBULLETSPAGE_NUMBERCTRL, wxRichTextBulletsPage::OnNumberctrlTextUpdated )
-    EVT_UPDATE_UI( ID_RICHTEXTBULLETSPAGE_NUMBERCTRL, wxRichTextBulletsPage::OnNumberctrlUpdate )
+    EVT_COMBOBOX( ID_RICHTEXTBULLETSPAGE_BULLETALIGNMENTCTRL, wxRichTextBulletsPage::OnBulletAlignmentCtrlSelected )
 
     EVT_UPDATE_UI( ID_RICHTEXTBULLETSPAGE_SYMBOLSTATIC, wxRichTextBulletsPage::OnSymbolstaticUpdate )
 
@@ -63,6 +60,14 @@ BEGIN_EVENT_TABLE( wxRichTextBulletsPage, wxPanel )
     EVT_TEXT( ID_RICHTEXTBULLETSPAGE_NAMECTRL, wxRichTextBulletsPage::OnNamectrlUpdated )
     EVT_UPDATE_UI( ID_RICHTEXTBULLETSPAGE_NAMECTRL, wxRichTextBulletsPage::OnNamectrlUIUpdate )
 
+    EVT_UPDATE_UI( ID_RICHTEXTBULLETSPAGE_NUMBERSTATIC, wxRichTextBulletsPage::OnNumberstaticUpdate )
+
+    EVT_SPINCTRL( ID_RICHTEXTBULLETSPAGE_NUMBERCTRL, wxRichTextBulletsPage::OnNumberctrlUpdated )
+    EVT_SPIN_UP( ID_RICHTEXTBULLETSPAGE_NUMBERCTRL, wxRichTextBulletsPage::OnNumberctrlUp )
+    EVT_SPIN_DOWN( ID_RICHTEXTBULLETSPAGE_NUMBERCTRL, wxRichTextBulletsPage::OnNumberctrlDown )
+    EVT_TEXT( ID_RICHTEXTBULLETSPAGE_NUMBERCTRL, wxRichTextBulletsPage::OnNumberctrlTextUpdated )
+    EVT_UPDATE_UI( ID_RICHTEXTBULLETSPAGE_NUMBERCTRL, wxRichTextBulletsPage::OnNumberctrlUpdate )
+
 ////@end wxRichTextBulletsPage event table entries
 
 END_EVENT_TABLE()
@@ -97,10 +102,12 @@ void wxRichTextBulletsPage::Init()
     m_styleListBox = NULL;
     m_periodCtrl = NULL;
     m_parenthesesCtrl = NULL;
-    m_numberCtrl = NULL;
+    m_rightParenthesisCtrl = NULL;
+    m_bulletAlignmentCtrl = NULL;
     m_symbolCtrl = NULL;
     m_symbolFontCtrl = NULL;
     m_bulletNameCtrl = NULL;
+    m_numberCtrl = NULL;
     m_previewCtrl = NULL;
 ////@end wxRichTextBulletsPage member initialisation
 }
@@ -149,7 +156,7 @@ void wxRichTextBulletsPage::CreateControls()
     itemBoxSizer5->Add(itemStaticText6, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
 
     wxString* m_styleListBoxStrings = NULL;
-    m_styleListBox = new wxListBox( itemPanel1, ID_RICHTEXTBULLETSPAGE_STYLELISTBOX, wxDefaultPosition, wxSize(-1, 130), 0, m_styleListBoxStrings, wxLB_SINGLE );
+    m_styleListBox = new wxListBox( itemPanel1, ID_RICHTEXTBULLETSPAGE_STYLELISTBOX, wxDefaultPosition, wxSize(-1, 140), 0, m_styleListBoxStrings, wxLB_SINGLE );
     m_styleListBox->SetHelpText(_("The available bullet styles."));
     if (ShowToolTips())
         m_styleListBox->SetToolTip(_("The available bullet styles."));
@@ -165,76 +172,100 @@ void wxRichTextBulletsPage::CreateControls()
         m_periodCtrl->SetToolTip(_("Check to add a period after the bullet."));
     itemBoxSizer8->Add(m_periodCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
 
-    m_parenthesesCtrl = new wxCheckBox( itemPanel1, ID_RICHTEXTBULLETSPAGE_PARENTHESESCTRL, _("&Parentheses"), wxDefaultPosition, wxDefaultSize, 0 );
+    m_parenthesesCtrl = new wxCheckBox( itemPanel1, ID_RICHTEXTBULLETSPAGE_PARENTHESESCTRL, _("(*)"), wxDefaultPosition, wxDefaultSize, 0 );
     m_parenthesesCtrl->SetValue(false);
     m_parenthesesCtrl->SetHelpText(_("Check to enclose the bullet in parentheses."));
     if (ShowToolTips())
         m_parenthesesCtrl->SetToolTip(_("Check to enclose the bullet in parentheses."));
     itemBoxSizer8->Add(m_parenthesesCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
 
-    itemBoxSizer5->Add(5, 5, 0, wxALIGN_CENTER_HORIZONTAL, 5);
+    m_rightParenthesisCtrl = new wxCheckBox( itemPanel1, ID_RICHTEXTBULLETSPAGE_RIGHTPARENTHESISCTRL, _("*)"), wxDefaultPosition, wxDefaultSize, 0 );
+    m_rightParenthesisCtrl->SetValue(false);
+    m_rightParenthesisCtrl->SetHelpText(_("Check to add a right parenthesis."));
+    if (ShowToolTips())
+        m_rightParenthesisCtrl->SetToolTip(_("Check to add a right parenthesis."));
+    itemBoxSizer8->Add(m_rightParenthesisCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
 
-    wxStaticText* itemStaticText12 = new wxStaticText( itemPanel1, ID_RICHTEXTBULLETSPAGE_NUMBERSTATIC, _("&Number:"), wxDefaultPosition, wxDefaultSize, 0 );
-    itemBoxSizer5->Add(itemStaticText12, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
+    itemBoxSizer5->Add(5, 5, 0, wxALIGN_CENTER_HORIZONTAL, 5);
 
-    m_numberCtrl = new wxSpinCtrl( itemPanel1, ID_RICHTEXTBULLETSPAGE_NUMBERCTRL, _T("0"), wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, 0, 100000, 0 );
-    m_numberCtrl->SetHelpText(_("The list item number."));
+    wxStaticText* itemStaticText13 = new wxStaticText( itemPanel1, wxID_STATIC, _("Bullet &Alignment:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemBoxSizer5->Add(itemStaticText13, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
+
+    wxString m_bulletAlignmentCtrlStrings[] = {
+        _("Left"),
+        _("Centre"),
+        _("Right")
+    };
+    m_bulletAlignmentCtrl = new wxComboBox( itemPanel1, ID_RICHTEXTBULLETSPAGE_BULLETALIGNMENTCTRL, _("Left"), wxDefaultPosition, wxSize(60, -1), 3, m_bulletAlignmentCtrlStrings, wxCB_READONLY );
+    m_bulletAlignmentCtrl->SetStringSelection(_("Left"));
+    m_bulletAlignmentCtrl->SetHelpText(_("The bullet character."));
     if (ShowToolTips())
-        m_numberCtrl->SetToolTip(_("The list item number."));
-    itemBoxSizer5->Add(m_numberCtrl, 0, wxGROW|wxALL, 5);
+        m_bulletAlignmentCtrl->SetToolTip(_("The bullet character."));
+    itemBoxSizer5->Add(m_bulletAlignmentCtrl, 0, wxGROW|wxALL|wxFIXED_MINSIZE, 5);
 
     itemBoxSizer4->Add(2, 1, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);
 
-    wxStaticLine* itemStaticLine15 = new wxStaticLine( itemPanel1, wxID_STATIC, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
-    itemBoxSizer4->Add(itemStaticLine15, 0, wxGROW|wxLEFT|wxRIGHT, 5);
+    wxStaticLine* itemStaticLine16 = new wxStaticLine( itemPanel1, wxID_STATIC, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
+    itemBoxSizer4->Add(itemStaticLine16, 0, wxGROW|wxLEFT|wxRIGHT, 5);
 
     itemBoxSizer4->Add(2, 1, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);
 
-    wxBoxSizer* itemBoxSizer17 = new wxBoxSizer(wxVERTICAL);
-    itemBoxSizer4->Add(itemBoxSizer17, 0, wxGROW, 5);
+    wxBoxSizer* itemBoxSizer18 = new wxBoxSizer(wxVERTICAL);
+    itemBoxSizer4->Add(itemBoxSizer18, 0, wxGROW, 5);
 
-    wxStaticText* itemStaticText18 = new wxStaticText( itemPanel1, ID_RICHTEXTBULLETSPAGE_SYMBOLSTATIC, _("&Symbol:"), wxDefaultPosition, wxDefaultSize, 0 );
-    itemBoxSizer17->Add(itemStaticText18, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
+    wxStaticText* itemStaticText19 = new wxStaticText( itemPanel1, ID_RICHTEXTBULLETSPAGE_SYMBOLSTATIC, _("&Symbol:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemBoxSizer18->Add(itemStaticText19, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
 
-    wxBoxSizer* itemBoxSizer19 = new wxBoxSizer(wxHORIZONTAL);
-    itemBoxSizer17->Add(itemBoxSizer19, 0, wxGROW, 5);
+    wxBoxSizer* itemBoxSizer20 = new wxBoxSizer(wxHORIZONTAL);
+    itemBoxSizer18->Add(itemBoxSizer20, 0, wxGROW, 5);
 
     wxString* m_symbolCtrlStrings = NULL;
     m_symbolCtrl = new wxComboBox( itemPanel1, ID_RICHTEXTBULLETSPAGE_SYMBOLCTRL, _T(""), wxDefaultPosition, wxSize(60, -1), 0, m_symbolCtrlStrings, wxCB_DROPDOWN );
     m_symbolCtrl->SetHelpText(_("The bullet character."));
     if (ShowToolTips())
         m_symbolCtrl->SetToolTip(_("The bullet character."));
-    itemBoxSizer19->Add(m_symbolCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxFIXED_MINSIZE, 5);
+    itemBoxSizer20->Add(m_symbolCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxFIXED_MINSIZE, 5);
 
-    wxButton* itemButton21 = new wxButton( itemPanel1, ID_RICHTEXTBULLETSPAGE_CHOOSE_SYMBOL, _("Ch&oose..."), wxDefaultPosition, wxDefaultSize, 0 );
-    itemButton21->SetHelpText(_("Click to browse for a symbol."));
+    wxButton* itemButton22 = new wxButton( itemPanel1, ID_RICHTEXTBULLETSPAGE_CHOOSE_SYMBOL, _("Ch&oose..."), wxDefaultPosition, wxDefaultSize, 0 );
+    itemButton22->SetHelpText(_("Click to browse for a symbol."));
     if (ShowToolTips())
-        itemButton21->SetToolTip(_("Click to browse for a symbol."));
-    itemBoxSizer19->Add(itemButton21, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+        itemButton22->SetToolTip(_("Click to browse for a symbol."));
+    itemBoxSizer20->Add(itemButton22, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
 
-    itemBoxSizer17->Add(5, 5, 0, wxALIGN_CENTER_HORIZONTAL, 5);
+    itemBoxSizer18->Add(5, 5, 0, wxALIGN_CENTER_HORIZONTAL, 5);
 
-    wxStaticText* itemStaticText23 = new wxStaticText( itemPanel1, ID_RICHTEXTBULLETSPAGE_SYMBOLSTATIC, _("Symbol &font:"), wxDefaultPosition, wxDefaultSize, 0 );
-    itemBoxSizer17->Add(itemStaticText23, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
+    wxStaticText* itemStaticText24 = new wxStaticText( itemPanel1, ID_RICHTEXTBULLETSPAGE_SYMBOLSTATIC, _("Symbol &font:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemBoxSizer18->Add(itemStaticText24, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
 
     wxString* m_symbolFontCtrlStrings = NULL;
     m_symbolFontCtrl = new wxComboBox( itemPanel1, ID_RICHTEXTBULLETSPAGE_SYMBOLFONTCTRL, _T(""), wxDefaultPosition, wxDefaultSize, 0, m_symbolFontCtrlStrings, wxCB_DROPDOWN );
     m_symbolFontCtrl->SetHelpText(_("Available fonts."));
     if (ShowToolTips())
         m_symbolFontCtrl->SetToolTip(_("Available fonts."));
-    itemBoxSizer17->Add(m_symbolFontCtrl, 0, wxGROW|wxALL, 5);
+    itemBoxSizer18->Add(m_symbolFontCtrl, 0, wxGROW|wxALL, 5);
 
-    itemBoxSizer17->Add(5, 5, 1, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
+    itemBoxSizer18->Add(5, 5, 1, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
 
-    wxStaticText* itemStaticText26 = new wxStaticText( itemPanel1, ID_RICHTEXTBULLETSPAGE_NAMESTATIC, _("S&tandard bullet name:"), wxDefaultPosition, wxDefaultSize, 0 );
-    itemBoxSizer17->Add(itemStaticText26, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
+    wxStaticText* itemStaticText27 = new wxStaticText( itemPanel1, ID_RICHTEXTBULLETSPAGE_NAMESTATIC, _("S&tandard bullet name:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemBoxSizer18->Add(itemStaticText27, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
 
     wxString* m_bulletNameCtrlStrings = NULL;
     m_bulletNameCtrl = new wxComboBox( itemPanel1, ID_RICHTEXTBULLETSPAGE_NAMECTRL, _T(""), wxDefaultPosition, wxDefaultSize, 0, m_bulletNameCtrlStrings, wxCB_DROPDOWN );
     m_bulletNameCtrl->SetHelpText(_("A standard bullet name."));
     if (ShowToolTips())
         m_bulletNameCtrl->SetToolTip(_("A standard bullet name."));
-    itemBoxSizer17->Add(m_bulletNameCtrl, 0, wxGROW|wxALL, 5);
+    itemBoxSizer18->Add(m_bulletNameCtrl, 0, wxGROW|wxALL, 5);
+
+    itemBoxSizer18->Add(5, 5, 1, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
+
+    wxStaticText* itemStaticText30 = new wxStaticText( itemPanel1, ID_RICHTEXTBULLETSPAGE_NUMBERSTATIC, _("&Number:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemBoxSizer18->Add(itemStaticText30, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
+
+    m_numberCtrl = new wxSpinCtrl( itemPanel1, ID_RICHTEXTBULLETSPAGE_NUMBERCTRL, _T("0"), wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, 0, 100000, 0 );
+    m_numberCtrl->SetHelpText(_("The list item number."));
+    if (ShowToolTips())
+        m_numberCtrl->SetToolTip(_("The list item number."));
+    itemBoxSizer18->Add(m_numberCtrl, 0, wxGROW|wxALL, 5);
 
     itemBoxSizer3->Add(5, 5, 1, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
 
@@ -252,18 +283,22 @@ void wxRichTextBulletsPage::CreateControls()
     m_styleListBox->Append(_("Lower case letters"));
     m_styleListBox->Append(_("Upper case roman numerals"));
     m_styleListBox->Append(_("Lower case roman numerals"));
+    m_styleListBox->Append(_("Numbered outline"));
     m_styleListBox->Append(_("Symbol"));
     m_styleListBox->Append(_("Bitmap"));
     m_styleListBox->Append(_("Standard"));
-
+    
     m_symbolCtrl->Append(_("*"));
     m_symbolCtrl->Append(_("-"));
     m_symbolCtrl->Append(_(">"));
     m_symbolCtrl->Append(_("+"));
     m_symbolCtrl->Append(_("~"));
     
-    m_bulletNameCtrl->Append(_("standard/round"));
-    m_bulletNameCtrl->Append(_("standard/square"));
+    wxArrayString standardBulletNames;
+    if (wxRichTextBuffer::GetRenderer())
+        wxRichTextBuffer::GetRenderer()->EnumerateStandardBulletNames(standardBulletNames);
+
+    m_bulletNameCtrl->Append(standardBulletNames);
 
     wxArrayString facenames = wxRichTextCtrl::GetAvailableFontNames();
     facenames.Sort();
@@ -280,24 +315,34 @@ bool wxRichTextBulletsPage::TransferDataFromWindow()
 
     if (m_hasBulletStyle)
     {
-        long bulletStyle = 0;
+        long bulletStyle = wxRICHTEXT_BULLETINDEX_NONE;
 
         int index = m_styleListBox->GetSelection();
-        if (index == 1)
+        if (index == wxRICHTEXT_BULLETINDEX_ARABIC)
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_ARABIC;
-        else if (index == 2)
+
+        else if (index == wxRICHTEXT_BULLETINDEX_UPPER_CASE)
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER;
-        else if (index == 3)
+
+        else if (index == wxRICHTEXT_BULLETINDEX_LOWER_CASE)
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER;
-        else if (index == 4)
+
+        else if (index == wxRICHTEXT_BULLETINDEX_UPPER_CASE_ROMAN)
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER;
-        else if (index == 5)
+
+        else if (index == wxRICHTEXT_BULLETINDEX_LOWER_CASE_ROMAN)
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER;
-        else if (index == 6)
+
+        else if (index == wxRICHTEXT_BULLETINDEX_OUTLINE)
+            bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_OUTLINE;
+
+        else if (index == wxRICHTEXT_BULLETINDEX_SYMBOL)
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_SYMBOL;
-        else if (index == 7)
+
+        else if (index == wxRICHTEXT_BULLETINDEX_BITMAP)
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_BITMAP;
-        else if (index == 8)
+
+        else if (index == wxRICHTEXT_BULLETINDEX_STANDARD)
         {
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_STANDARD;
             attr->SetBulletName(m_bulletNameCtrl->GetValue());
@@ -305,8 +350,16 @@ bool wxRichTextBulletsPage::TransferDataFromWindow()
 
         if (m_parenthesesCtrl->GetValue())
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_PARENTHESES;
+        if (m_rightParenthesisCtrl->GetValue())
+            bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_RIGHT_PARENTHESIS;
         if (m_periodCtrl->GetValue())
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_PERIOD;
+            
+        if (m_bulletAlignmentCtrl->GetSelection() == 1)
+            bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_ALIGN_CENTRE;
+        else if (m_bulletAlignmentCtrl->GetSelection() == 2)
+            bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_ALIGN_RIGHT;
+        // Left is implied            
 
         attr->SetBulletStyle(bulletStyle);
     }
@@ -318,12 +371,10 @@ bool wxRichTextBulletsPage::TransferDataFromWindow()
 
     if (m_hasBulletSymbol)
     {
-        wxChar c(wxT('*'));
-        if (m_symbolCtrl->GetValue().length() > 0)
-            c = m_symbolCtrl->GetValue()[0];
-        attr->SetBulletSymbol(c);
+        attr->SetBulletText(m_symbolCtrl->GetValue());
         attr->SetBulletFont(m_symbolFontCtrl->GetValue());
     }
+    
     return true;
 }
 
@@ -338,23 +389,35 @@ bool wxRichTextBulletsPage::TransferDataToWindow()
     if (attr->HasBulletStyle())
     {
         m_hasBulletStyle = true;
-        int index = -1;
+        int index = wxRICHTEXT_BULLETINDEX_NONE;
+
         if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ARABIC)
-            index = 1;
+            index = wxRICHTEXT_BULLETINDEX_ARABIC;
+
         else if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER)
-            index = 2;
+            index = wxRICHTEXT_BULLETINDEX_UPPER_CASE;
+
         else if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER)
-            index = 3;
+            index = wxRICHTEXT_BULLETINDEX_LOWER_CASE;
+
         else if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER)
-            index = 4;
+            index = wxRICHTEXT_BULLETINDEX_UPPER_CASE_ROMAN;
+
         else if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER)
-            index = 5;
+            index = wxRICHTEXT_BULLETINDEX_LOWER_CASE_ROMAN;
+
+        else if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_OUTLINE)
+            index = wxRICHTEXT_BULLETINDEX_OUTLINE;
+
         else if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_SYMBOL)
-            index = 6;
+            index = wxRICHTEXT_BULLETINDEX_SYMBOL;
+
         else if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_BITMAP)
-            index = 7;
+            index = wxRICHTEXT_BULLETINDEX_BITMAP;
+
         else if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_STANDARD)
-            index = 8;
+            index = wxRICHTEXT_BULLETINDEX_STANDARD;
+
         m_styleListBox->SetSelection(index);
 
         if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_PARENTHESES)
@@ -362,23 +425,33 @@ bool wxRichTextBulletsPage::TransferDataToWindow()
         else
             m_parenthesesCtrl->SetValue(false);
 
+        if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_RIGHT_PARENTHESIS)
+            m_rightParenthesisCtrl->SetValue(true);
+        else
+            m_rightParenthesisCtrl->SetValue(false);
+
         if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_PERIOD)
             m_periodCtrl->SetValue(true);
         else
             m_periodCtrl->SetValue(false);
+
+        if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ALIGN_CENTRE)
+            m_bulletAlignmentCtrl->SetSelection(1);
+        else if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ALIGN_RIGHT)
+            m_bulletAlignmentCtrl->SetSelection(2);
+        else
+            m_bulletAlignmentCtrl->SetSelection(0);
     }
     else
     {
         m_hasBulletStyle = false;
         m_styleListBox->SetSelection(-1);
+        m_bulletAlignmentCtrl->SetSelection(-1);
     }
 
-    if (attr->HasBulletSymbol())
+    if (attr->HasBulletText())
     {
-        wxChar c = attr->GetBulletSymbol();
-        wxString s;
-        s << c;
-        m_symbolCtrl->SetValue(s);
+        m_symbolCtrl->SetValue(attr->GetBulletText());
         m_symbolFontCtrl->SetValue(attr->GetBulletFont());
     }
     else
@@ -416,7 +489,7 @@ iaculis malesuada. Donec bibendum ipsum ut ante porta fringilla.\n");
     TransferDataFromWindow();
     wxTextAttrEx attr(*GetAttributes());
     attr.SetFlags(attr.GetFlags() &
-      (wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER|wxTEXT_ATTR_BULLET_SYMBOL|wxTEXT_ATTR_BULLET_NAME|
+      (wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER|wxTEXT_ATTR_BULLET_TEXT|wxTEXT_ATTR_BULLET_NAME|
        wxTEXT_ATTR_ALIGNMENT|wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT|wxTEXT_ATTR_PARA_SPACING_BEFORE|wxTEXT_ATTR_PARA_SPACING_AFTER|
        wxTEXT_ATTR_LINE_SPACING));
 
@@ -442,6 +515,8 @@ iaculis malesuada. Donec bibendum ipsum ut ante porta fringilla.\n");
     m_previewCtrl->BeginStyle(normalParaAttr);
     m_previewCtrl->WriteText(s_para3);
     m_previewCtrl->EndStyle();
+    
+    m_previewCtrl->NumberList(wxRichTextRange(0, m_previewCtrl->GetLastPosition()+1));
 
     m_previewCtrl->Thaw();
 }
@@ -496,7 +571,7 @@ void wxRichTextBulletsPage::OnStylelistboxSelected( wxCommandEvent& WXUNUSED(eve
     {
         m_hasBulletStyle = true;
 
-        if (m_styleListBox->GetSelection() == 6)
+        if (m_styleListBox->GetSelection() == wxRICHTEXT_BULLETINDEX_SYMBOL)
             m_hasBulletSymbol = true;
 
         UpdatePreview();
@@ -619,7 +694,9 @@ void wxRichTextBulletsPage::OnParenthesesctrlClick( wxCommandEvent& WXUNUSED(eve
 void wxRichTextBulletsPage::OnParenthesesctrlUpdate( wxUpdateUIEvent& event )
 {
     int sel = m_styleListBox->GetSelection();
-    event.Enable(m_hasBulletStyle && (sel != 6 && sel != 7 && sel != 0));
+    event.Enable(m_hasBulletStyle && (sel != wxRICHTEXT_BULLETINDEX_SYMBOL &&
+                                      sel != wxRICHTEXT_BULLETINDEX_BITMAP &&
+                                      sel != wxRICHTEXT_BULLETINDEX_NONE));
 }
 
 /*!
@@ -642,7 +719,9 @@ void wxRichTextBulletsPage::OnPeriodctrlClick( wxCommandEvent& WXUNUSED(event) )
 void wxRichTextBulletsPage::OnPeriodctrlUpdate( wxUpdateUIEvent& event )
 {
     int sel = m_styleListBox->GetSelection();
-    event.Enable(m_hasBulletStyle && (sel != 6 && sel != 7 && sel != 0));
+    event.Enable(m_hasBulletStyle && (sel != wxRICHTEXT_BULLETINDEX_SYMBOL &&
+                                      sel != wxRICHTEXT_BULLETINDEX_BITMAP &&
+                                      sel != wxRICHTEXT_BULLETINDEX_NONE));
 }
 
 /*!
@@ -652,7 +731,7 @@ void wxRichTextBulletsPage::OnPeriodctrlUpdate( wxUpdateUIEvent& event )
 void wxRichTextBulletsPage::OnChooseSymbolClick( wxCommandEvent& WXUNUSED(event) )
 {
     int sel = m_styleListBox->GetSelection();
-    if (m_hasBulletStyle && sel == 6)
+    if (m_hasBulletStyle && sel == wxRICHTEXT_BULLETINDEX_SYMBOL)
     {
         wxString symbol = m_symbolCtrl->GetValue();
         wxString fontName = m_symbolFontCtrl->GetValue();
@@ -716,21 +795,24 @@ void wxRichTextBulletsPage::OnSymbolfontctrlUIUpdate( wxUpdateUIEvent& event )
 void wxRichTextBulletsPage::OnSymbolUpdate( wxUpdateUIEvent& event )
 {
     int sel = m_styleListBox->GetSelection();
-    event.Enable(m_hasBulletStyle && (sel == 6));
+    event.Enable(m_hasBulletStyle && (sel == wxRICHTEXT_BULLETINDEX_SYMBOL));
 }
 
 /// Update for number-related controls
 void wxRichTextBulletsPage::OnNumberUpdate( wxUpdateUIEvent& event )
 {
     int sel = m_styleListBox->GetSelection();
-    event.Enable( m_hasBulletStyle && (sel != 6 && sel != 7 && sel != 8 && sel != 0));
+    event.Enable( m_hasBulletStyle && (sel != wxRICHTEXT_BULLETINDEX_SYMBOL &&
+                                       sel != wxRICHTEXT_BULLETINDEX_BITMAP &&
+                                       sel != wxRICHTEXT_BULLETINDEX_STANDARD &&
+                                       sel != wxRICHTEXT_BULLETINDEX_NONE));
 }
 
 /// Update for standard bullet-related controls
 void wxRichTextBulletsPage::OnStandardBulletUpdate( wxUpdateUIEvent& event )
 {
     int sel = m_styleListBox->GetSelection();
-    event.Enable( sel == 8 );
+    event.Enable( sel == wxRICHTEXT_BULLETINDEX_STANDARD );
 }
 
 
@@ -795,3 +877,40 @@ void wxRichTextBulletsPage::OnNamectrlUIUpdate( wxUpdateUIEvent& event )
 }
 
 #endif // wxUSE_RICHTEXT
+/*!
+ * wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_RICHTEXTBULLETSPAGE_RIGHT_PARENTHESIS_CTRL
+ */
+
+void wxRichTextBulletsPage::OnRightParenthesisCtrlClick( wxCommandEvent& WXUNUSED(event) )
+{
+    if (!m_dontUpdate)
+    {
+        m_hasBulletStyle = true;
+        UpdatePreview();
+    }
+}
+
+/*!
+ * wxEVT_UPDATE_UI event handler for ID_RICHTEXTBULLETSPAGE_RIGHT_PARENTHESIS_CTRL
+ */
+
+void wxRichTextBulletsPage::OnRightParenthesisCtrlUpdate( wxUpdateUIEvent& event )
+{
+    int sel = m_styleListBox->GetSelection();
+    event.Enable(m_hasBulletStyle && (sel != wxRICHTEXT_BULLETINDEX_SYMBOL &&
+                                      sel != wxRICHTEXT_BULLETINDEX_BITMAP &&
+                                      sel != wxRICHTEXT_BULLETINDEX_NONE));
+}
+
+/*!
+ * wxEVT_COMMAND_COMBOBOX_SELECTED event handler for ID_COMBOBOX
+ */
+
+void wxRichTextBulletsPage::OnBulletAlignmentCtrlSelected( wxCommandEvent& WXUNUSED(event) )
+{
+    if (m_dontUpdate)
+        return;
+    UpdatePreview();
+}
+
+
diff --git a/src/richtext/richtextctrl.cpp b/src/richtext/richtextctrl.cpp
index 58057e12a1..c59cbfb851 100644
--- a/src/richtext/richtextctrl.cpp
+++ b/src/richtext/richtextctrl.cpp
@@ -44,6 +44,10 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_MIDDLE_CLICK)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_RIGHT_CLICK)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_LEFT_DCLICK)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_RETURN)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACING)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACED)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_STYLESHEET_CHANGING)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_STYLESHEET_CHANGED)
 
 IMPLEMENT_CLASS( wxRichTextCtrl, wxControl )
 
@@ -137,7 +141,7 @@ bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxString& va
     attributes.SetLineSpacing(10);
     attributes.SetParagraphSpacingAfter(10);
     attributes.SetParagraphSpacingBefore(0);
-    attributes.SetFlags(wxTEXT_ATTR_ALL);
+
     SetBasicStyle(attributes);
 
     // The default attributes will be merged with base attributes, so
@@ -156,16 +160,23 @@ bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxString& va
     RecreateBuffer(size);
 #endif
 
-    SetCursor(wxCursor(wxCURSOR_IBEAM));
+    m_textCursor = wxCursor(wxCURSOR_IBEAM);
+    m_urlCursor = wxCursor(wxCURSOR_HAND);
+
+    SetCursor(m_textCursor);
 
     if (!value.IsEmpty())
         SetValue(value);
 
+    GetBuffer().AddEventHandler(this);
+
     return true;
 }
 
 wxRichTextCtrl::~wxRichTextCtrl()
 {
+    GetBuffer().RemoveEventHandler(this);
+    
     delete m_contextMenu;
 }
 
@@ -333,25 +344,59 @@ void wxRichTextCtrl::OnLeftClick(wxMouseEvent& event)
 }
 
 /// Left-up
-void wxRichTextCtrl::OnLeftUp(wxMouseEvent& WXUNUSED(event))
+void wxRichTextCtrl::OnLeftUp(wxMouseEvent& event)
 {
     if (m_dragging)
     {
         m_dragging = false;
         if (GetCapture() == this)
             ReleaseMouse();
+
+        // See if we clicked on a URL
+        wxClientDC dc(this);
+        PrepareDC(dc);
+        dc.SetFont(GetFont());
+
+        long position = 0;
+        wxPoint logicalPt = event.GetLogicalPosition(dc);
+        int hit = GetBuffer().HitTest(dc, logicalPt, position);
+    
+        if (hit != wxRICHTEXT_HITTEST_NONE)
+        {
+            wxTextAttrEx attr;
+            if (GetStyle(position, attr))
+            {
+                if (attr.HasFlag(wxTEXT_ATTR_URL))
+                {
+                    wxString urlTarget = attr.GetURL();
+                    if (!urlTarget.IsEmpty())
+                    {
+                        wxMouseEvent mouseEvent(event);
+                        
+                        long startPos = 0, endPos = 0;
+                        wxRichTextObject* obj = GetBuffer().GetLeafObjectAtPosition(position);
+                        if (obj)
+                        {
+                            startPos = obj->GetRange().GetStart();
+                            endPos = obj->GetRange().GetEnd();
+                        }                        
+                        
+                        wxTextUrlEvent urlEvent(GetId(), mouseEvent, startPos, endPos);
+                        InitCommandEvent(urlEvent);
+
+                        urlEvent.SetString(urlTarget);
+                        
+                        GetEventHandler()->ProcessEvent(urlEvent);
+                    }
+                }
+            }
+        }
     }
 }
 
 /// Left-click
 void wxRichTextCtrl::OnMoveMouse(wxMouseEvent& event)
 {
-    if (!event.Dragging())
-    {
-        event.Skip();
-        return;
-    }
-
     wxClientDC dc(this);
     PrepareDC(dc);
     dc.SetFont(GetFont());
@@ -359,6 +404,34 @@ void wxRichTextCtrl::OnMoveMouse(wxMouseEvent& event)
     long position = 0;
     wxPoint logicalPt = event.GetLogicalPosition(dc);
     int hit = GetBuffer().HitTest(dc, logicalPt, position);
+    
+    // See if we need to change the cursor
+    
+    {
+        if (hit != wxRICHTEXT_HITTEST_NONE)
+        {
+            wxTextAttrEx attr;
+            if (GetStyle(position, attr))
+            {
+                if (attr.HasFlag(wxTEXT_ATTR_URL))
+                {
+                    if (GetCursor() != m_urlCursor)
+                        SetCursor(m_urlCursor);
+                }
+                else if (!attr.HasFlag(wxTEXT_ATTR_URL))
+                {
+                    if (GetCursor() != m_textCursor)
+                        SetCursor(m_textCursor);
+                }
+            }
+        }
+    }
+
+    if (!event.Dragging())
+    {
+        event.Skip();
+        return;
+    }
 
     if (m_dragging && hit != wxRICHTEXT_HITTEST_NONE)
     {
@@ -462,18 +535,24 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
         DeleteSelectedContent(& newPos);
 
         GetBuffer().InsertNewlineWithUndo(newPos+1, this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE);
+        EndBatchUndo();
+        SetDefaultStyleToCursorStyle();
+
+        ScrollIntoView(m_caretPosition, WXK_RIGHT);
 
         wxRichTextEvent cmdEvent(
             wxEVT_COMMAND_RICHTEXT_RETURN,
             GetId());
         cmdEvent.SetEventObject(this);
         cmdEvent.SetFlags(flags);
-        GetEventHandler()->ProcessEvent(cmdEvent);
-
-        EndBatchUndo();
-        SetDefaultStyleToCursorStyle();
-
-        ScrollIntoView(m_caretPosition, WXK_RIGHT);
+        if (!GetEventHandler()->ProcessEvent(cmdEvent))
+        {
+            // Generate conventional event
+            wxCommandEvent textEvent(wxEVT_COMMAND_TEXT_ENTER, GetId());
+            InitCommandEvent(textEvent);
+            
+            GetEventHandler()->ProcessEvent(textEvent);
+        }
     }
     else if (event.GetKeyCode() == WXK_BACK)
     {
@@ -662,6 +741,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
                         int promoteBy = event.ShiftDown() ? 1 : -1;
 
                         PromoteList(promoteBy, range, NULL);
+
                         return;
                     }
                 }
diff --git a/src/richtext/richtexthtml.cpp b/src/richtext/richtexthtml.cpp
index 4326e33e15..eaf0343aea 100644
--- a/src/richtext/richtexthtml.cpp
+++ b/src/richtext/richtexthtml.cpp
@@ -27,8 +27,15 @@
 #include "wx/wfstream.h"
 #include "wx/txtstrm.h"
 
+#if wxUSE_FILESYSTEM
+#include "wx/filesys.h"
+#include "wx/fs_mem.h"
+#endif
+
 IMPLEMENT_DYNAMIC_CLASS(wxRichTextHTMLHandler, wxRichTextFileHandler)
 
+int wxRichTextHTMLHandler::sm_fileCounter = 1;
+
 /// Can we handle this filename (if using files)? By default, checks the extension.
 bool wxRichTextHTMLHandler::CanHandle(const wxString& filename) const
 {
@@ -51,6 +58,8 @@ bool wxRichTextHTMLHandler::DoLoadFile(wxRichTextBuffer *WXUNUSED(buffer), wxInp
 
 bool wxRichTextHTMLHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream& stream)
 {
+    ClearTemporaryImageLocations();
+
     buffer->Defragment();
 
     wxTextOutputStream str(stream);
@@ -60,32 +69,12 @@ bool wxRichTextHTMLHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream&
 
     str << wxT("<html><head></head><body>\n");
 
-    /*
-    wxRichText may be support paper formats like a1/a2/a3/a4
-    when this widget grown enough, i should turn back and support its new features
-    but not yet
-
-      str << wxT("<table border=0 cellpadding=0 cellspacing=0><tr><td>");
-
-        wxString left_indent = SymbolicIndent(currentParaStyle.GetLeftIndent());
-        wxString right_indent = SymbolicIndent(currentParaStyle.GetRightIndent());
-
-          str << wxString::Format(wxT("%s</td><td></td><td>%s</td></tr><tr>"),
-          left_indent.c_str(), //Document-Wide Left Indent
-          right_indent.c_str()); //Document-Wide Right Indent
-
-            str << wxT("<td></td><td width=\"100%\">");
-    */
-
     str << wxT("<table border=0 cellpadding=0 cellspacing=0><tr><td width=\"100%\">");
 
     str << wxString::Format(wxT("<font face=\"%s\" size=\"%ld\" color=\"%s\" >"),
-        currentParaStyle.GetFont().GetFaceName().c_str(), Pt_To_Size( currentParaStyle.GetFont().GetPointSize() ),
+        currentParaStyle.GetFont().GetFaceName().c_str(), PtToSize(currentParaStyle.GetFont().GetPointSize()),
         currentParaStyle.GetTextColour().GetAsString(wxC2S_HTML_SYNTAX).c_str());
 
-    //wxString align = GetAlignment( currentParaStyle.GetAlignment() );
-    //str << wxString::Format(wxT("<p align=\"%s\">"), align );
-
     m_font = false;
     m_indent = 0;
     m_list = false;
@@ -119,12 +108,11 @@ bool wxRichTextHTMLHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream&
 
                 wxRichTextImage* image = wxDynamicCast(obj, wxRichTextImage);
                 if( image && !image->IsEmpty())
-                    Image_to_Base64( image, stream );
+                    WriteImage( image, stream );
 
                 node2 = node2->GetNext();
             }
             str << wxT("\n");
-            //OutputParagraphFormatting(currentParaStyle, para->GetAttributes(), stream, false);
         }
         node = node->GetNext();
     }
@@ -138,30 +126,27 @@ void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& current
 {
     wxTextOutputStream str(stream);
 
-    //Is the item bulleted one?
-    if( paraStyle.GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE )
+    // Is the item a bulleted one?
+    if ( paraStyle.GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE )
     {
-        //Is there any opened list?
-        if( m_list )
+        // Is there any opened list?
+        if (m_list)
         {
-            //Yes there is
+            // Yes there is
 
-            //Is the item among the previous ones
-            //Is the item one of the previous list tag's child items
-            if( (paraStyle.GetLeftIndent() == (m_indent + 100)) || (paraStyle.GetLeftIndent() < 100) )
-                str << wxT("<li>");//Yes it is
+            // Is the item among the previous ones?
+            // Is the item one of the previous list tag's child items?            
+            if ((paraStyle.GetLeftIndent() == (m_indent + 100)) || (paraStyle.GetLeftIndent() < 100))
+                str << wxT("<li>"); //Yes it is
             else
             {
-                //No it isn't
-
-                //So we should close the list tag
+                // No it isn't, so we should close the list tag
                 str << (m_is_ul ? wxT("</ul>") : wxT("</ol>"));
 
-                //And renavigate to new list's horizontal position
+                // And renavigate to new list's horizontal position
                 NavigateToListPosition(paraStyle, str);
-                //Ok it's done
 
-                //Get the appropriate tag, an ol for numerical values, an ul for dot, square etc.
+                // Get the appropriate tag, an ol for numerical values, an ul for dot, square etc.
                 wxString tag;
                 TypeOfList(paraStyle, tag);
                 str << tag << wxT("<li>");
@@ -169,47 +154,47 @@ void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& current
         }
         else
         {
-            //No there isn't a list
-
-            //navigate to new list's horizontal position(indent)
+            // No there isn't a list.
+            // navigate to new list's horizontal position(indent)
             NavigateToListPosition(paraStyle, str);
 
-            //Get the appropriate tag, an ol for numerical values, an ul for dot, square etc.
+            // Get the appropriate tag, an ol for numerical values, an ul for dot, square etc.
             wxString tag;
             TypeOfList(paraStyle, tag);
             str << tag << wxT("<li>");
 
-            //Now we have a list, mark it.
+            // Now we have a list, mark it.
             m_list = true;
         }
     }
     else if( m_list )
     {
-        //The item is not bulleted and there is a list what should be closed now.
-        //So close the list
+        // The item is not bulleted and there is a list what should be closed now.
+        // So close the list
 
         str << (m_is_ul ? wxT("</ul>") : wxT("</ol>"));
-        //And mark as there is no an opened list
+
+        // And mark as there is no an opened list
         m_list = false;
     }
 
     // does the item have an indentation ?
     if( paraStyle.GetLeftIndent() )
     {
-        if( paraStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_NONE )
+        if (paraStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_NONE)
         {
-            if( m_indent )
+            if (m_indent)
             {
-                if( (paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent()) == m_indent )
+                if ((paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent()) == m_indent)
                 {
-                    if( paraStyle.GetLeftSubIndent() < 0 )
+                    if (paraStyle.GetLeftSubIndent() < 0)
                     {
                         str << SymbolicIndent(~paraStyle.GetLeftSubIndent());
                     }
                 }
                 else
                 {
-                    if( paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent() > m_indent )
+                    if (paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent() > m_indent)
                     {
                         Indent(paraStyle, str);
                         m_indent = paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent();
@@ -218,9 +203,9 @@ void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& current
                     else
                     {
                         int i = m_indents.size() - 1;
-                        for(; i > -1; i--)
+                        for (; i > -1; i--)
                         {
-                            if( m_indent < (paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent()) )
+                            if (m_indent < (paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent()))
                             {
                                 Indent(paraStyle, str);
                                 m_indent = paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent();
@@ -228,9 +213,9 @@ void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& current
 
                                 break;
                             }
-                            else if( m_indent == (paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent()) )
+                            else if (m_indent == (paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent()))
                             {
-                                if( paraStyle.GetLeftSubIndent() < 0 )
+                                if (paraStyle.GetLeftSubIndent() < 0)
                                 {
                                     str << SymbolicIndent(~paraStyle.GetLeftSubIndent());
                                 }
@@ -242,7 +227,10 @@ void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& current
 
                                 m_indents.RemoveAt(i);
 
-                                if( i < 1 ){m_indent=0; break;}
+                                if(i < 1)
+                                {
+                                    m_indent=0; break;
+                                }
                                 m_indent = m_indents[i-1];
                             }
                         }
@@ -257,12 +245,11 @@ void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& current
             }
         }
     }
-    else if( m_indent )
+    else if (m_indent)
     {
-        //The item is not indented and there is a table(s) what should be closed now.
+        // The item is not indented and there is a table(s) that should be closed now.
 
-        //So close them
-        for(unsigned int i = 0; i < m_indents.size(); i++ )
+        for (unsigned int i = 0; i < m_indents.size(); i++)
             str << wxT("</td></tr></table>");
 
         m_indent = 0;
@@ -272,40 +259,52 @@ void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& current
 
     wxString style;
 
-    //Is there any change on the font properties of the item
-    if( thisStyle.GetFont().GetFaceName() != currentStyle.GetFont().GetFaceName() )
-        style += wxString::Format(wxT(" face=\"%s\""), thisStyle.GetFont().GetFaceName().c_str());
-    if( thisStyle.GetFont().GetPointSize() != currentStyle.GetFont().GetPointSize() )
-        style += wxString::Format(wxT(" size=\"%ld\""), Pt_To_Size(thisStyle.GetFont().GetPointSize()) );
-    if( thisStyle.GetTextColour() != currentStyle.GetTextColour() )
-        style += wxString::Format(wxT(" color=\"%s\""), thisStyle.GetTextColour().GetAsString(wxC2S_HTML_SYNTAX).c_str());
+    // Is there any change in the font properties of the item?
+    if (thisStyle.GetFont().GetFaceName() != currentStyle.GetFont().GetFaceName())
+    {
+        wxString faceName(thisStyle.GetFont().GetFaceName());
+        style += wxString::Format(wxT(" face=\"%s\""), faceName.c_str());
+    }
+    if (thisStyle.GetFont().GetPointSize() != currentStyle.GetFont().GetPointSize())
+        style += wxString::Format(wxT(" size=\"%ld\""), PtToSize(thisStyle.GetFont().GetPointSize()));
+    if (thisStyle.GetTextColour() != currentStyle.GetTextColour() )
+    {
+        wxString color(thisStyle.GetTextColour().GetAsString(wxC2S_HTML_SYNTAX));
+        style += wxString::Format(wxT(" color=\"%s\""), color.c_str());
+    }
 
-    if( style.size() )
+    if (style.size())
     {
         str << wxString::Format(wxT("<font %s >"), style.c_str());
         m_font = true;
     }
 
-    if( thisStyle.GetFont().GetWeight() == wxBOLD )
+    if (thisStyle.GetFont().GetWeight() == wxBOLD)
         str << wxT("<b>");
-    if( thisStyle.GetFont().GetStyle() == wxITALIC )
+    if (thisStyle.GetFont().GetStyle() == wxITALIC)
         str << wxT("<i>");
-    if( thisStyle.GetFont().GetUnderlined() )
+    if (thisStyle.GetFont().GetUnderlined())
         str << wxT("<u>");
+    
+    if (thisStyle.HasURL())
+        str << wxT("<a href=\"") << thisStyle.GetURL() << wxT("\">");
 }
 
 void wxRichTextHTMLHandler::EndCharacterFormatting(const wxTextAttrEx& WXUNUSED(currentStyle), const wxTextAttrEx& thisStyle, const wxTextAttrEx& WXUNUSED(paraStyle), wxOutputStream& stream)
 {
     wxTextOutputStream str(stream);
 
-    if( thisStyle.GetFont().GetUnderlined() )
+    if (thisStyle.HasURL())
+        str << wxT("</a>");
+
+    if (thisStyle.GetFont().GetUnderlined())
         str << wxT("</u>");
-    if( thisStyle.GetFont().GetStyle() == wxITALIC )
+    if (thisStyle.GetFont().GetStyle() == wxITALIC)
         str << wxT("</i>");
-    if( thisStyle.GetFont().GetWeight() == wxBOLD )
+    if (thisStyle.GetFont().GetWeight() == wxBOLD)
         str << wxT("</b>");
 
-    if( m_font )
+    if (m_font)
     {
         m_font = false;
         str << wxT("</font>");
@@ -315,83 +314,83 @@ void wxRichTextHTMLHandler::EndCharacterFormatting(const wxTextAttrEx& WXUNUSED(
 /// Output paragraph formatting
 void wxRichTextHTMLHandler::OutputParagraphFormatting(const wxTextAttrEx& WXUNUSED(currentStyle), const wxTextAttrEx& thisStyle, wxOutputStream& stream)
 {
-    //If there is no opened list currently, insert a <p> after every paragraph
-    if(!m_list)
+    // If there is no opened list currently, insert a <p> after every paragraph
+    if (!m_list)
     {
         wxTextOutputStream str(stream);
-        wxString align = GetAlignment( thisStyle );
+        wxString align = GetAlignment(thisStyle);
         str << wxString::Format(wxT("<p align=\"%s\">"), align.c_str());
     }
 }
 
 void wxRichTextHTMLHandler::NavigateToListPosition(const wxTextAttrEx& thisStyle, wxTextOutputStream& str)
 {
-    //indenting an item using an ul/ol tag is equal to inserting 5 x &nbsp; on its left side.
-    //so we should start from 100 point left
+    // indenting an item using an ul/ol tag is equal to inserting 5 x &nbsp; on its left side.
+    // so we should start from 100 point left
 
-    //Is the second td's left wall of the current indentaion table at the 100+ point-left-side
-    //of the item, horizontally?
-    if( m_indent + 100 < thisStyle.GetLeftIndent() )
+    // Is the second td's left wall of the current indentaion table at the 100+ point-left-side
+    // of the item, horizontally?
+    if (m_indent + 100 < thisStyle.GetLeftIndent())
     {
-        //yes it is
+        // yes it is
         LIndent(thisStyle, str);
         m_indent = thisStyle.GetLeftIndent() - 100;
         m_indents.Add( m_indent );
         return;
     }
-    //No it isn't
+    // No it isn't
 
     int i = m_indents.size() - 1;
-    for(; i > -1; i--)
+    for (; i > -1; i--)
     {
         //Is the second td's left wall of the current indentaion table at the 100+ point-left-side
         //of the item ?
-        if( m_indent + 100 < thisStyle.GetLeftIndent() )
+        if (m_indent + 100 < thisStyle.GetLeftIndent())
         {
-            //Yes it is
+            // Yes it is
             LIndent(thisStyle, str);
             m_indent = thisStyle.GetLeftIndent() - 100;
             m_indents.Add( m_indent );
             break;
         }
-        else if( m_indent + 100 == thisStyle.GetLeftIndent() )
-            break;//exact match
+        else if (m_indent + 100 == thisStyle.GetLeftIndent())
+            break; //exact match
         else
         {
-            //No it is not, the second td's left wall of the current indentaion table is at the
+            // No it is not, the second td's left wall of the current indentaion table is at the
             //right side of the current item horizontally, so close it.
             str << wxT("</td></tr></table>");
 
             m_indents.RemoveAt(i);
 
-            if( i < 1 ){m_indent=0; break;}
+            if (i < 1)
+            {
+                m_indent=0; break;
+            }
             m_indent = m_indents[i-1];
         }
     }
 }
 void wxRichTextHTMLHandler::Indent( const wxTextAttrEx& thisStyle, wxTextOutputStream& str )
 {
-    //As a five year experienced web developer i assure you there is no way to indent an item
-    //in html way, but we can use tables.
-
+    //There is no way to indent an item in HTML, but we can use tables.
 
+    // Item -> "Hello world"
+    // Its Left Indentation -> 100
+    // Its Left Sub-Indentation ->40
+    // A typical indentation-table for the item will be construct as the following
 
-    //Item -> "Hello world"
-    //Its Left Indentation -> 100
-    //Its Left Sub-Indentation ->40
-    //A typical indentation-table for the item will be construct as the following
-
-    //3 x nbsp = 60
-    //2 x nbsp = 40
-    //LSI = Left Sub Indent
-    //LI = Left Indent - LSI
+    // 3 x nbsp = 60
+    // 2 x nbsp = 40
+    // LSI = Left Sub Indent
+    // LI = Left Indent - LSI
     //
-    //-------------------------------------------
-    //|&nbsp;&nbsp;nbsp;|nbsp;nbsp;Hello World  |
-    //|      |          |    |                  |
-    //|        V        |    V                  |
-    //|      --LI--     | --LSI--               |
-    //-------------------------------------------
+    // -------------------------------------------
+    // |&nbsp;&nbsp;nbsp;|nbsp;nbsp;Hello World  |
+    // |      |          |    |                  |
+    // |        V        |    V                  |
+    // |      --LI--     | --LSI--               |
+    // -------------------------------------------
 
     str << wxT("<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr>");
 
@@ -399,7 +398,7 @@ void wxRichTextHTMLHandler::Indent( const wxTextAttrEx& thisStyle, wxTextOutputS
     str << wxString::Format( wxT("<td>%s</td>"), symbolic_indent.c_str() );
     str << wxT("<td width=\"100%\">");
 
-    if( thisStyle.GetLeftSubIndent() < 0 )
+    if (thisStyle.GetLeftSubIndent() < 0)
     {
         str << SymbolicIndent(~thisStyle.GetLeftSubIndent());
     }
@@ -407,28 +406,28 @@ void wxRichTextHTMLHandler::Indent( const wxTextAttrEx& thisStyle, wxTextOutputS
 
 void wxRichTextHTMLHandler::LIndent( const wxTextAttrEx& thisStyle, wxTextOutputStream& str )
 {
-    //Code:
-    //r.BeginNumberedBullet(1, 200, 60);
-    //r.Newline();
-    //r.WriteText(wxT("first item"));
-    //r.EndNumberedBullet();
-    //r.BeginNumberedBullet(2, 200, 60);
-    //r.Newline();
-    //r.WriteText(wxT("second item."));
-    //r.EndNumberedBullet();
+    // Code:
+    // r.BeginNumberedBullet(1, 200, 60);
+    // r.Newline();
+    // r.WriteText(wxT("first item"));
+    // r.EndNumberedBullet();
+    // r.BeginNumberedBullet(2, 200, 60);
+    // r.Newline();
+    // r.WriteText(wxT("second item."));
+    // r.EndNumberedBullet();
     //
-    //A typical indentation-table for the item will be construct as the following
+    // A typical indentation-table for the item will be construct as the following
 
-    //1 x nbsp = 20 point
-    //ULI -> 100pt (UL/OL tag indents its sub element by 100 point)
-    //<--------- 100 pt ---------->|
-    //------------------------------------------------------
-    //|&nbsp;&nbsp;nbsp;&nbsp;nbsp;|<ul>                   |
-    //|                            |<-ULI-><li>first item  |
-    //|                            |<-ULI-><li>second item |
-    //|                            |</ul>                  |
-    //------------------------------------------------------
-    //                             |<-100->|
+    // 1 x nbsp = 20 point
+    // ULI -> 100pt (UL/OL tag indents its sub element by 100 point)
+    // <--------- 100 pt ---------->|
+    // ------------------------------------------------------
+    // |&nbsp;&nbsp;nbsp;&nbsp;nbsp;|<ul>                   |
+    // |                            |<-ULI-><li>first item  |
+    // |                            |<-ULI-><li>second item |
+    // |                            |</ul>                  |
+    // ------------------------------------------------------
+    //                              |<-100->|
 
 
     str << wxT("<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr>");
@@ -440,19 +439,19 @@ void wxRichTextHTMLHandler::LIndent( const wxTextAttrEx& thisStyle, wxTextOutput
 
 void wxRichTextHTMLHandler::TypeOfList( const wxTextAttrEx& thisStyle, wxString& tag )
 {
-    //We can use number attribute of li tag but not all the browsers support it.
-    //also wxHtmlWindow doesn't support type attribute.
+    // We can use number attribute of li tag but not all the browsers support it.
+    // also wxHtmlWindow doesn't support type attribute.
 
     m_is_ul = false;
-    if( thisStyle.GetBulletStyle() == (wxTEXT_ATTR_BULLET_STYLE_ARABIC|wxTEXT_ATTR_BULLET_STYLE_PERIOD))
+    if (thisStyle.GetBulletStyle() == (wxTEXT_ATTR_BULLET_STYLE_ARABIC|wxTEXT_ATTR_BULLET_STYLE_PERIOD))
         tag = wxT("<ol type=\"1\">");
-    else if( thisStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER )
+    else if (thisStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER)
         tag = wxT("<ol type=\"A\">");
-    else if( thisStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER )
+    else if (thisStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER)
         tag = wxT("<ol type=\"a\">");
-    else if( thisStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER )
+    else if (thisStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER)
         tag = wxT("<ol type=\"I\">");
-    else if( thisStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER )
+    else if (thisStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER)
         tag = wxT("<ol type=\"i\">");
     else
     {
@@ -478,30 +477,84 @@ wxString wxRichTextHTMLHandler::GetAlignment( const wxTextAttrEx& thisStyle )
     }
 }
 
-void wxRichTextHTMLHandler::Image_to_Base64(wxRichTextImage* image, wxOutputStream& stream)
+void wxRichTextHTMLHandler::WriteImage(wxRichTextImage* image, wxOutputStream& stream)
 {
     wxTextOutputStream str(stream);
 
     str << wxT("<img src=\"");
-    str << wxT("data:");
-    str << GetMimeType(image->GetImageBlock().GetImageType());
-    str << wxT(";base64,");
 
-    if (image->GetImage().Ok() && !image->GetImageBlock().GetData())
-        image->MakeBlock();
+#if wxUSE_FILESYSTEM
+    if (GetFlags() & wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_MEMORY)
+    {
+        if (!image->GetImage().Ok() && image->GetImageBlock().GetData())
+            image->LoadFromBlock();
+        if (image->GetImage().Ok() && !image->GetImageBlock().GetData())
+            image->MakeBlock();
+
+        if (image->GetImage().Ok())
+        {        
+            wxString ext(image->GetImageBlock().GetExtension());
+            wxString tempFilename(wxString::Format(wxT("image%d.%s"), sm_fileCounter, (const wxChar*) ext));
+            wxMemoryFSHandler::AddFile(tempFilename, image->GetImage(), image->GetImageBlock().GetImageType());
+            
+            m_imageLocations.Add(tempFilename);
+            
+            str << wxT("memory:") << tempFilename;
+        }
+        else
+            str << wxT("memory:?");
 
-    wxChar* data = b64enc( image->GetImageBlock().GetData(), image->GetImageBlock().GetDataSize() );
-    str << data;
+        sm_fileCounter ++;
+    }
+    else if (GetFlags() & wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_FILES)
+    {
+        if (!image->GetImage().Ok() && image->GetImageBlock().GetData())
+            image->LoadFromBlock();
+        if (image->GetImage().Ok() && !image->GetImageBlock().GetData())
+            image->MakeBlock();
+
+        if (image->GetImage().Ok())
+        {        
+            wxString tempDir(GetTempDir());
+            if (tempDir.IsEmpty())
+                tempDir = wxFileName::GetTempDir();
+            
+            wxString ext(image->GetImageBlock().GetExtension());
+            wxString tempFilename(wxString::Format(wxT("%s/image%d.%s"), tempDir, sm_fileCounter, (const wxChar*) ext));
+            image->GetImageBlock().Write(tempFilename);
+            
+            m_imageLocations.Add(tempFilename);
+            
+            str << wxFileSystem::FileNameToURL(tempFilename);            
+        }
+        else
+            str << wxT("file:?");
 
-    delete[] data;
+        sm_fileCounter ++;
+    }
+    else // if (GetFlags() & wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_BASE64) // this is implied
+#endif
+    {
+        str << wxT("data:");
+        str << GetMimeType(image->GetImageBlock().GetImageType());
+        str << wxT(";base64,");
+
+        if (image->GetImage().Ok() && !image->GetImageBlock().GetData())
+            image->MakeBlock();
+
+        wxChar* data = b64enc( image->GetImageBlock().GetData(), image->GetImageBlock().GetDataSize() );
+        str << data;
+
+        delete[] data;
+    }
 
     str << wxT("\" />");
 }
 
-long wxRichTextHTMLHandler::Pt_To_Size(long size)
+long wxRichTextHTMLHandler::PtToSize(long size)
 {
-    //return most approximate size
-    if(size < 9 ) return 1;
+    // return approximate size
+    if (size < 9 ) return 1;
     else if( size < 11 ) return 2;
     else if( size < 14 ) return 3;
     else if( size < 18 ) return 4;
@@ -537,13 +590,13 @@ const wxChar* wxRichTextHTMLHandler::GetMimeType(int imageType)
     }
 }
 
-//exim-style base64 encoder
+// exim-style base64 encoder
 wxChar* wxRichTextHTMLHandler::b64enc( unsigned char* input, size_t in_len )
 {
-    //elements of enc64 array must be 8 bit values
-    //otherwise encoder will fail
-    //hmmm.. Does wxT macro define a char as 16 bit value
-    //when compiling with UNICODE option?
+    // elements of enc64 array must be 8 bit values
+    // otherwise encoder will fail
+    // hmmm.. Does wxT macro define a char as 16 bit value
+    // when compiling with UNICODE option?
     static const wxChar enc64[] = wxT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
     wxChar* output = new wxChar[4*((in_len+2)/3)+1];
     wxChar* p = output;
@@ -588,5 +641,37 @@ wxChar* wxRichTextHTMLHandler::b64enc( unsigned char* input, size_t in_len )
 #endif
 // wxUSE_STREAMS
 
+/// Delete the in-memory or temporary files generated by the last operation
+bool wxRichTextHTMLHandler::DeleteTemporaryImages()
+{
+    return DeleteTemporaryImages(GetFlags(), m_imageLocations);
+}
+
+/// Delete the in-memory or temporary files generated by the last operation
+bool wxRichTextHTMLHandler::DeleteTemporaryImages(int flags, const wxArrayString& imageLocations)
+{
+    size_t i;
+    for (i = 0; i < imageLocations.GetCount(); i++)
+    {
+        wxString location = imageLocations[i];
+        
+        if (flags & wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_MEMORY)
+        {
+#if wxUSE_FILESYSTEM
+            wxMemoryFSHandler::RemoveFile(location);
+#endif
+        }
+        else if (flags & wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_FILES)
+        {
+            if (wxFileExists(location))
+                wxRemoveFile(location);
+        }
+    }
+    
+    return true;
+}
+
+
 #endif
 // wxUSE_RICHTEXT
+
diff --git a/src/richtext/richtextindentspage.cpp b/src/richtext/richtextindentspage.cpp
index 3d9a15f986..12ddce245d 100644
--- a/src/richtext/richtextindentspage.cpp
+++ b/src/richtext/richtextindentspage.cpp
@@ -205,7 +205,7 @@ void wxRichTextIndentsSpacingPage::CreateControls()
     wxBoxSizer* itemBoxSizer24 = new wxBoxSizer(wxHORIZONTAL);
     itemFlexGridSizer22->Add(itemBoxSizer24, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
 
-    m_indentLeft = new wxTextCtrl( itemPanel1, ID_RICHTEXTINDENTSSPACINGPAGE_INDENT_LEFT, wxEmptyString, wxDefaultPosition, wxSize(50, -1), 0 );
+    m_indentLeft = new wxTextCtrl( itemPanel1, ID_RICHTEXTINDENTSSPACINGPAGE_INDENT_LEFT, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
     m_indentLeft->SetHelpText(_("The left indent."));
     if (ShowToolTips())
         m_indentLeft->SetToolTip(_("The left indent."));
@@ -217,7 +217,7 @@ void wxRichTextIndentsSpacingPage::CreateControls()
     wxBoxSizer* itemBoxSizer27 = new wxBoxSizer(wxHORIZONTAL);
     itemFlexGridSizer22->Add(itemBoxSizer27, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
 
-    m_indentLeftFirst = new wxTextCtrl( itemPanel1, ID_RICHTEXTINDENTSSPACINGPAGE_INDENT_LEFT_FIRST, wxEmptyString, wxDefaultPosition, wxSize(50, -1), 0 );
+    m_indentLeftFirst = new wxTextCtrl( itemPanel1, ID_RICHTEXTINDENTSSPACINGPAGE_INDENT_LEFT_FIRST, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
     m_indentLeftFirst->SetHelpText(_("The first line indent."));
     if (ShowToolTips())
         m_indentLeftFirst->SetToolTip(_("The first line indent."));
@@ -229,7 +229,7 @@ void wxRichTextIndentsSpacingPage::CreateControls()
     wxBoxSizer* itemBoxSizer30 = new wxBoxSizer(wxHORIZONTAL);
     itemFlexGridSizer22->Add(itemBoxSizer30, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
 
-    m_indentRight = new wxTextCtrl( itemPanel1, ID_RICHTEXTINDENTSSPACINGPAGE_INDENT_RIGHT, wxEmptyString, wxDefaultPosition, wxSize(50, -1), 0 );
+    m_indentRight = new wxTextCtrl( itemPanel1, ID_RICHTEXTINDENTSSPACINGPAGE_INDENT_RIGHT, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
     m_indentRight->SetHelpText(_("The right indent."));
     if (ShowToolTips())
         m_indentRight->SetToolTip(_("The right indent."));
@@ -262,7 +262,7 @@ void wxRichTextIndentsSpacingPage::CreateControls()
     wxBoxSizer* itemBoxSizer41 = new wxBoxSizer(wxHORIZONTAL);
     itemFlexGridSizer39->Add(itemBoxSizer41, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
 
-    m_spacingBefore = new wxTextCtrl( itemPanel1, ID_RICHTEXTINDENTSSPACINGPAGE_SPACING_BEFORE, wxEmptyString, wxDefaultPosition, wxSize(50, -1), 0 );
+    m_spacingBefore = new wxTextCtrl( itemPanel1, ID_RICHTEXTINDENTSSPACINGPAGE_SPACING_BEFORE, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
     m_spacingBefore->SetHelpText(_("The spacing before the paragraph."));
     if (ShowToolTips())
         m_spacingBefore->SetToolTip(_("The spacing before the paragraph."));
@@ -274,7 +274,7 @@ void wxRichTextIndentsSpacingPage::CreateControls()
     wxBoxSizer* itemBoxSizer44 = new wxBoxSizer(wxHORIZONTAL);
     itemFlexGridSizer39->Add(itemBoxSizer44, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
 
-    m_spacingAfter = new wxTextCtrl( itemPanel1, ID_RICHTEXTINDENTSSPACINGPAGE_SPACING_AFTER, wxEmptyString, wxDefaultPosition, wxSize(50, -1), 0 );
+    m_spacingAfter = new wxTextCtrl( itemPanel1, ID_RICHTEXTINDENTSSPACINGPAGE_SPACING_AFTER, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
     if (ShowToolTips())
         m_spacingAfter->SetToolTip(_("The spacing after the paragraph."));
     itemBoxSizer44->Add(m_spacingAfter, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
@@ -330,7 +330,7 @@ iaculis malesuada. Donec bibendum ipsum ut ante porta fringilla.\n");
     attr.SetFlags(attr.GetFlags() &
       (wxTEXT_ATTR_ALIGNMENT|wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT|wxTEXT_ATTR_PARA_SPACING_BEFORE|wxTEXT_ATTR_PARA_SPACING_AFTER|
        wxTEXT_ATTR_LINE_SPACING|
-       wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER|wxTEXT_ATTR_BULLET_SYMBOL));
+       wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER|wxTEXT_ATTR_BULLET_TEXT));
 
     wxFont font(m_previewCtrl->GetFont());
     font.SetPointSize(9);
diff --git a/src/richtext/richtextliststylepage.cpp b/src/richtext/richtextliststylepage.cpp
index 326ac46425..dab66fda78 100644
--- a/src/richtext/richtextliststylepage.cpp
+++ b/src/richtext/richtextliststylepage.cpp
@@ -43,6 +43,11 @@ BEGIN_EVENT_TABLE( wxRichTextListStylePage, wxPanel )
     EVT_CHECKBOX( ID_RICHTEXTLISTSTYLEPAGE_PARENTHESESCTRL, wxRichTextListStylePage::OnParenthesesctrlClick )
     EVT_UPDATE_UI( ID_RICHTEXTLISTSTYLEPAGE_PARENTHESESCTRL, wxRichTextListStylePage::OnParenthesesctrlUpdate )
 
+    EVT_CHECKBOX( ID_RICHTEXTLISTSTYLEPAGE_RIGHTPARENTHESISCTRL, wxRichTextListStylePage::OnRightParenthesisCtrlClick )
+    EVT_UPDATE_UI( ID_RICHTEXTLISTSTYLEPAGE_RIGHTPARENTHESISCTRL, wxRichTextListStylePage::OnRightParenthesisCtrlUpdate )
+
+    EVT_COMBOBOX( ID_RICHTEXTLISTSTYLEPAGE_BULLETALIGNMENTCTRL, wxRichTextListStylePage::OnBulletAlignmentCtrlSelected )
+
     EVT_UPDATE_UI( ID_RICHTEXTLISTSTYLEPAGE_SYMBOLSTATIC, wxRichTextListStylePage::OnSymbolstaticUpdate )
 
     EVT_COMBOBOX( ID_RICHTEXTBULLETSPAGE_SYMBOLCTRL, wxRichTextListStylePage::OnSymbolctrlSelected )
@@ -136,6 +141,8 @@ void wxRichTextListStylePage::Init()
     m_styleListBox = NULL;
     m_periodCtrl = NULL;
     m_parenthesesCtrl = NULL;
+    m_rightParenthesisCtrl = NULL;
+    m_bulletAlignmentCtrl = NULL;
     m_symbolCtrl = NULL;
     m_symbolFontCtrl = NULL;
     m_bulletNameCtrl = NULL;
@@ -189,9 +196,9 @@ void wxRichTextListStylePage::CreateControls()
         itemButton8->SetToolTip(_("Click to choose the font for this level."));
     itemBoxSizer4->Add(itemButton8, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
 
-    wxBookCtrl* itemBook9 = new wxBookCtrl( itemPanel1, ID_RICHTEXTLISTSTYLEPAGE_BOOK, wxDefaultPosition, wxDefaultSize, wxBK_TOP );
+    wxNotebook* itemNotebook9 = new wxNotebook( itemPanel1, ID_RICHTEXTLISTSTYLEPAGE_NOTEBOOK, wxDefaultPosition, wxDefaultSize, wxNB_TOP );
 
-    wxPanel* itemPanel10 = new wxPanel( itemBook9, ID_RICHTEXTLISTSTYLEPAGE_BULLETS, wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxTAB_TRAVERSAL );
+    wxPanel* itemPanel10 = new wxPanel( itemNotebook9, ID_RICHTEXTLISTSTYLEPAGE_BULLETS, wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxTAB_TRAVERSAL );
     wxBoxSizer* itemBoxSizer11 = new wxBoxSizer(wxVERTICAL);
     itemPanel10->SetSizer(itemBoxSizer11);
 
@@ -203,7 +210,7 @@ void wxRichTextListStylePage::CreateControls()
     itemBoxSizer13->Add(itemStaticText14, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
 
     wxString* m_styleListBoxStrings = NULL;
-    m_styleListBox = new wxListBox( itemPanel10, ID_RICHTEXTLISTSTYLEPAGE_STYLELISTBOX, wxDefaultPosition, wxSize(-1, 130), 0, m_styleListBoxStrings, wxLB_SINGLE );
+    m_styleListBox = new wxListBox( itemPanel10, ID_RICHTEXTLISTSTYLEPAGE_STYLELISTBOX, wxDefaultPosition, wxSize(-1, 140), 0, m_styleListBoxStrings, wxLB_SINGLE );
     m_styleListBox->SetHelpText(_("The available bullet styles."));
     if (ShowToolTips())
         m_styleListBox->SetToolTip(_("The available bullet styles."));
@@ -218,230 +225,254 @@ void wxRichTextListStylePage::CreateControls()
         m_periodCtrl->SetToolTip(_("Check to add a period after the bullet."));
     itemBoxSizer16->Add(m_periodCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
 
-    m_parenthesesCtrl = new wxCheckBox( itemPanel10, ID_RICHTEXTLISTSTYLEPAGE_PARENTHESESCTRL, _("&Parentheses"), wxDefaultPosition, wxDefaultSize, 0 );
+    m_parenthesesCtrl = new wxCheckBox( itemPanel10, ID_RICHTEXTLISTSTYLEPAGE_PARENTHESESCTRL, _("(*)"), wxDefaultPosition, wxDefaultSize, 0 );
     m_parenthesesCtrl->SetValue(false);
     m_parenthesesCtrl->SetHelpText(_("Check to enclose the bullet in parentheses."));
     if (ShowToolTips())
         m_parenthesesCtrl->SetToolTip(_("Check to enclose the bullet in parentheses."));
     itemBoxSizer16->Add(m_parenthesesCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
 
+    m_rightParenthesisCtrl = new wxCheckBox( itemPanel10, ID_RICHTEXTLISTSTYLEPAGE_RIGHTPARENTHESISCTRL, _("*)"), wxDefaultPosition, wxDefaultSize, 0 );
+    m_rightParenthesisCtrl->SetValue(false);
+    m_rightParenthesisCtrl->SetHelpText(_("Check to add a right parenthesis."));
+    if (ShowToolTips())
+        m_rightParenthesisCtrl->SetToolTip(_("Check to add a right parenthesis."));
+    itemBoxSizer16->Add(m_rightParenthesisCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    itemBoxSizer13->Add(2, 1, 0, wxALIGN_CENTER_HORIZONTAL, 5);
+
+    wxStaticText* itemStaticText21 = new wxStaticText( itemPanel10, wxID_STATIC, _("Bullet &Alignment:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemBoxSizer13->Add(itemStaticText21, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
+
+    wxString m_bulletAlignmentCtrlStrings[] = {
+        _("Left"),
+        _("Centre"),
+        _("Right")
+    };
+    m_bulletAlignmentCtrl = new wxComboBox( itemPanel10, ID_RICHTEXTLISTSTYLEPAGE_BULLETALIGNMENTCTRL, _("Left"), wxDefaultPosition, wxSize(60, -1), 3, m_bulletAlignmentCtrlStrings, wxCB_READONLY );
+    m_bulletAlignmentCtrl->SetStringSelection(_("Left"));
+    m_bulletAlignmentCtrl->SetHelpText(_("The bullet character."));
+    if (ShowToolTips())
+        m_bulletAlignmentCtrl->SetToolTip(_("The bullet character."));
+    itemBoxSizer13->Add(m_bulletAlignmentCtrl, 0, wxGROW|wxALL|wxFIXED_MINSIZE, 5);
+
     itemBoxSizer12->Add(2, 1, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);
 
-    wxStaticLine* itemStaticLine20 = new wxStaticLine( itemPanel10, wxID_STATIC, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
-    itemBoxSizer12->Add(itemStaticLine20, 0, wxGROW|wxALL, 5);
+    wxStaticLine* itemStaticLine24 = new wxStaticLine( itemPanel10, wxID_STATIC, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
+    itemBoxSizer12->Add(itemStaticLine24, 0, wxGROW|wxALL, 5);
 
     itemBoxSizer12->Add(2, 1, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);
 
-    wxBoxSizer* itemBoxSizer22 = new wxBoxSizer(wxVERTICAL);
-    itemBoxSizer12->Add(itemBoxSizer22, 0, wxGROW, 5);
-    wxStaticText* itemStaticText23 = new wxStaticText( itemPanel10, ID_RICHTEXTLISTSTYLEPAGE_SYMBOLSTATIC, _("&Symbol:"), wxDefaultPosition, wxDefaultSize, 0 );
-    itemBoxSizer22->Add(itemStaticText23, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
+    wxBoxSizer* itemBoxSizer26 = new wxBoxSizer(wxVERTICAL);
+    itemBoxSizer12->Add(itemBoxSizer26, 0, wxGROW, 5);
+    wxStaticText* itemStaticText27 = new wxStaticText( itemPanel10, ID_RICHTEXTLISTSTYLEPAGE_SYMBOLSTATIC, _("&Symbol:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemBoxSizer26->Add(itemStaticText27, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
 
-    wxBoxSizer* itemBoxSizer24 = new wxBoxSizer(wxHORIZONTAL);
-    itemBoxSizer22->Add(itemBoxSizer24, 0, wxGROW, 5);
+    wxBoxSizer* itemBoxSizer28 = new wxBoxSizer(wxHORIZONTAL);
+    itemBoxSizer26->Add(itemBoxSizer28, 0, wxGROW, 5);
     wxString* m_symbolCtrlStrings = NULL;
     m_symbolCtrl = new wxComboBox( itemPanel10, ID_RICHTEXTBULLETSPAGE_SYMBOLCTRL, _T(""), wxDefaultPosition, wxSize(60, -1), 0, m_symbolCtrlStrings, wxCB_DROPDOWN );
     m_symbolCtrl->SetHelpText(_("The bullet character."));
     if (ShowToolTips())
         m_symbolCtrl->SetToolTip(_("The bullet character."));
-    itemBoxSizer24->Add(m_symbolCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxFIXED_MINSIZE, 5);
+    itemBoxSizer28->Add(m_symbolCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxFIXED_MINSIZE, 5);
 
-    wxButton* itemButton26 = new wxButton( itemPanel10, ID_RICHTEXTBULLETSPAGE_CHOOSE_SYMBOL, _("Ch&oose..."), wxDefaultPosition, wxDefaultSize, 0 );
-    itemButton26->SetHelpText(_("Click to browse for a symbol."));
+    wxButton* itemButton30 = new wxButton( itemPanel10, ID_RICHTEXTBULLETSPAGE_CHOOSE_SYMBOL, _("Ch&oose..."), wxDefaultPosition, wxDefaultSize, 0 );
+    itemButton30->SetHelpText(_("Click to browse for a symbol."));
     if (ShowToolTips())
-        itemButton26->SetToolTip(_("Click to browse for a symbol."));
-    itemBoxSizer24->Add(itemButton26, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+        itemButton30->SetToolTip(_("Click to browse for a symbol."));
+    itemBoxSizer28->Add(itemButton30, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
 
-    itemBoxSizer22->Add(5, 5, 0, wxALIGN_CENTER_HORIZONTAL, 5);
+    itemBoxSizer26->Add(5, 5, 0, wxALIGN_CENTER_HORIZONTAL, 5);
 
-    wxStaticText* itemStaticText28 = new wxStaticText( itemPanel10, ID_RICHTEXTLISTSTYLEPAGE_SYMBOLSTATIC, _("Symbol &font:"), wxDefaultPosition, wxDefaultSize, 0 );
-    itemBoxSizer22->Add(itemStaticText28, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
+    wxStaticText* itemStaticText32 = new wxStaticText( itemPanel10, ID_RICHTEXTLISTSTYLEPAGE_SYMBOLSTATIC, _("Symbol &font:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemBoxSizer26->Add(itemStaticText32, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
 
     wxString* m_symbolFontCtrlStrings = NULL;
     m_symbolFontCtrl = new wxComboBox( itemPanel10, ID_RICHTEXTLISTSTYLEPAGE_SYMBOLFONTCTRL, _T(""), wxDefaultPosition, wxDefaultSize, 0, m_symbolFontCtrlStrings, wxCB_DROPDOWN );
     if (ShowToolTips())
         m_symbolFontCtrl->SetToolTip(_("Available fonts."));
-    itemBoxSizer22->Add(m_symbolFontCtrl, 0, wxGROW|wxALL, 5);
+    itemBoxSizer26->Add(m_symbolFontCtrl, 0, wxGROW|wxALL, 5);
 
-    itemBoxSizer22->Add(5, 5, 1, wxALIGN_CENTER_HORIZONTAL, 5);
+    itemBoxSizer26->Add(5, 5, 1, wxALIGN_CENTER_HORIZONTAL, 5);
 
-    wxStaticText* itemStaticText31 = new wxStaticText( itemPanel10, ID_RICHTEXTLISTSTYLEPAGE_NAMESTATIC, _("S&tandard bullet name:"), wxDefaultPosition, wxDefaultSize, 0 );
-    itemBoxSizer22->Add(itemStaticText31, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
+    wxStaticText* itemStaticText35 = new wxStaticText( itemPanel10, ID_RICHTEXTLISTSTYLEPAGE_NAMESTATIC, _("S&tandard bullet name:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemBoxSizer26->Add(itemStaticText35, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
 
     wxString* m_bulletNameCtrlStrings = NULL;
     m_bulletNameCtrl = new wxComboBox( itemPanel10, ID_RICHTEXTLISTSTYLEPAGE_NAMECTRL, _T(""), wxDefaultPosition, wxDefaultSize, 0, m_bulletNameCtrlStrings, wxCB_DROPDOWN );
     m_bulletNameCtrl->SetHelpText(_("A standard bullet name."));
     if (ShowToolTips())
         m_bulletNameCtrl->SetToolTip(_("A standard bullet name."));
-    itemBoxSizer22->Add(m_bulletNameCtrl, 0, wxGROW|wxALL, 5);
+    itemBoxSizer26->Add(m_bulletNameCtrl, 0, wxGROW|wxALL, 5);
 
-    itemBook9->AddPage(itemPanel10, _("Bullet style"));
+    itemNotebook9->AddPage(itemPanel10, _("Bullet style"));
 
-    wxPanel* itemPanel33 = new wxPanel( itemBook9, ID_RICHTEXTLISTSTYLEPAGE_SPACING, wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxTAB_TRAVERSAL );
-    wxBoxSizer* itemBoxSizer34 = new wxBoxSizer(wxVERTICAL);
-    itemPanel33->SetSizer(itemBoxSizer34);
+    wxPanel* itemPanel37 = new wxPanel( itemNotebook9, ID_RICHTEXTLISTSTYLEPAGE_SPACING, wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxTAB_TRAVERSAL );
+    wxBoxSizer* itemBoxSizer38 = new wxBoxSizer(wxVERTICAL);
+    itemPanel37->SetSizer(itemBoxSizer38);
 
-    wxBoxSizer* itemBoxSizer35 = new wxBoxSizer(wxHORIZONTAL);
-    itemBoxSizer34->Add(itemBoxSizer35, 0, wxGROW, 5);
-    wxBoxSizer* itemBoxSizer36 = new wxBoxSizer(wxVERTICAL);
-    itemBoxSizer35->Add(itemBoxSizer36, 0, wxGROW, 5);
-    wxStaticText* itemStaticText37 = new wxStaticText( itemPanel33, wxID_STATIC, _("&Alignment"), wxDefaultPosition, wxDefaultSize, 0 );
-    itemBoxSizer36->Add(itemStaticText37, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
+    wxBoxSizer* itemBoxSizer39 = new wxBoxSizer(wxHORIZONTAL);
+    itemBoxSizer38->Add(itemBoxSizer39, 0, wxGROW, 5);
+    wxBoxSizer* itemBoxSizer40 = new wxBoxSizer(wxVERTICAL);
+    itemBoxSizer39->Add(itemBoxSizer40, 0, wxGROW, 5);
+    wxStaticText* itemStaticText41 = new wxStaticText( itemPanel37, wxID_STATIC, _("&Alignment"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemBoxSizer40->Add(itemStaticText41, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
 
-    wxBoxSizer* itemBoxSizer38 = new wxBoxSizer(wxHORIZONTAL);
-    itemBoxSizer36->Add(itemBoxSizer38, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
-    itemBoxSizer38->Add(5, 5, 0, wxALIGN_CENTER_VERTICAL, 5);
+    wxBoxSizer* itemBoxSizer42 = new wxBoxSizer(wxHORIZONTAL);
+    itemBoxSizer40->Add(itemBoxSizer42, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
+    itemBoxSizer42->Add(5, 5, 0, wxALIGN_CENTER_VERTICAL, 5);
 
-    wxBoxSizer* itemBoxSizer40 = new wxBoxSizer(wxVERTICAL);
-    itemBoxSizer38->Add(itemBoxSizer40, 0, wxALIGN_CENTER_VERTICAL|wxTOP, 5);
-    m_alignmentLeft = new wxRadioButton( itemPanel33, ID_RICHTEXTLISTSTYLEPAGE_ALIGNLEFT, _("&Left"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
+    wxBoxSizer* itemBoxSizer44 = new wxBoxSizer(wxVERTICAL);
+    itemBoxSizer42->Add(itemBoxSizer44, 0, wxALIGN_CENTER_VERTICAL|wxTOP, 5);
+    m_alignmentLeft = new wxRadioButton( itemPanel37, ID_RICHTEXTLISTSTYLEPAGE_ALIGNLEFT, _("&Left"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
     m_alignmentLeft->SetValue(false);
     m_alignmentLeft->SetHelpText(_("Left-align text."));
     if (ShowToolTips())
         m_alignmentLeft->SetToolTip(_("Left-align text."));
-    itemBoxSizer40->Add(m_alignmentLeft, 0, wxALIGN_LEFT|wxALL, 5);
+    itemBoxSizer44->Add(m_alignmentLeft, 0, wxALIGN_LEFT|wxALL, 5);
 
-    m_alignmentRight = new wxRadioButton( itemPanel33, ID_RICHTEXTLISTSTYLEPAGE_ALIGNRIGHT, _("&Right"), wxDefaultPosition, wxDefaultSize, 0 );
+    m_alignmentRight = new wxRadioButton( itemPanel37, ID_RICHTEXTLISTSTYLEPAGE_ALIGNRIGHT, _("&Right"), wxDefaultPosition, wxDefaultSize, 0 );
     m_alignmentRight->SetValue(false);
     m_alignmentRight->SetHelpText(_("Right-align text."));
     if (ShowToolTips())
         m_alignmentRight->SetToolTip(_("Right-align text."));
-    itemBoxSizer40->Add(m_alignmentRight, 0, wxALIGN_LEFT|wxALL, 5);
+    itemBoxSizer44->Add(m_alignmentRight, 0, wxALIGN_LEFT|wxALL, 5);
 
-    m_alignmentJustified = new wxRadioButton( itemPanel33, ID_RICHTEXTLISTSTYLEPAGE_JUSTIFIED, _("&Justified"), wxDefaultPosition, wxDefaultSize, 0 );
+    m_alignmentJustified = new wxRadioButton( itemPanel37, ID_RICHTEXTLISTSTYLEPAGE_JUSTIFIED, _("&Justified"), wxDefaultPosition, wxDefaultSize, 0 );
     m_alignmentJustified->SetValue(false);
     m_alignmentJustified->SetHelpText(_("Justify text left and right."));
     if (ShowToolTips())
         m_alignmentJustified->SetToolTip(_("Justify text left and right."));
-    itemBoxSizer40->Add(m_alignmentJustified, 0, wxALIGN_LEFT|wxALL, 5);
+    itemBoxSizer44->Add(m_alignmentJustified, 0, wxALIGN_LEFT|wxALL, 5);
 
-    m_alignmentCentred = new wxRadioButton( itemPanel33, ID_RICHTEXTLISTSTYLEPAGE_CENTERED, _("Cen&tred"), wxDefaultPosition, wxDefaultSize, 0 );
+    m_alignmentCentred = new wxRadioButton( itemPanel37, ID_RICHTEXTLISTSTYLEPAGE_CENTERED, _("Cen&tred"), wxDefaultPosition, wxDefaultSize, 0 );
     m_alignmentCentred->SetValue(false);
     m_alignmentCentred->SetHelpText(_("Centre text."));
     if (ShowToolTips())
         m_alignmentCentred->SetToolTip(_("Centre text."));
-    itemBoxSizer40->Add(m_alignmentCentred, 0, wxALIGN_LEFT|wxALL, 5);
+    itemBoxSizer44->Add(m_alignmentCentred, 0, wxALIGN_LEFT|wxALL, 5);
 
-    m_alignmentIndeterminate = new wxRadioButton( itemPanel33, ID_RICHTEXTLISTSTYLEPAGE_ALIGNINDETERMINATE, _("&Indeterminate"), wxDefaultPosition, wxDefaultSize, 0 );
+    m_alignmentIndeterminate = new wxRadioButton( itemPanel37, ID_RICHTEXTLISTSTYLEPAGE_ALIGNINDETERMINATE, _("&Indeterminate"), wxDefaultPosition, wxDefaultSize, 0 );
     m_alignmentIndeterminate->SetValue(false);
     m_alignmentIndeterminate->SetHelpText(_("Use the current alignment setting."));
     if (ShowToolTips())
         m_alignmentIndeterminate->SetToolTip(_("Use the current alignment setting."));
-    itemBoxSizer40->Add(m_alignmentIndeterminate, 0, wxALIGN_LEFT|wxALL, 5);
+    itemBoxSizer44->Add(m_alignmentIndeterminate, 0, wxALIGN_LEFT|wxALL, 5);
 
-    itemBoxSizer35->Add(2, 1, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);
+    itemBoxSizer39->Add(2, 1, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);
 
-    wxStaticLine* itemStaticLine47 = new wxStaticLine( itemPanel33, wxID_STATIC, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
-    itemBoxSizer35->Add(itemStaticLine47, 0, wxGROW|wxLEFT|wxBOTTOM, 5);
+    wxStaticLine* itemStaticLine51 = new wxStaticLine( itemPanel37, wxID_STATIC, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
+    itemBoxSizer39->Add(itemStaticLine51, 0, wxGROW|wxLEFT|wxBOTTOM, 5);
 
-    itemBoxSizer35->Add(2, 1, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);
+    itemBoxSizer39->Add(2, 1, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);
 
-    wxBoxSizer* itemBoxSizer49 = new wxBoxSizer(wxVERTICAL);
-    itemBoxSizer35->Add(itemBoxSizer49, 0, wxGROW, 5);
-    wxStaticText* itemStaticText50 = new wxStaticText( itemPanel33, wxID_STATIC, _("&Indentation (tenths of a mm)"), wxDefaultPosition, wxDefaultSize, 0 );
-    itemBoxSizer49->Add(itemStaticText50, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
+    wxBoxSizer* itemBoxSizer53 = new wxBoxSizer(wxVERTICAL);
+    itemBoxSizer39->Add(itemBoxSizer53, 0, wxGROW, 5);
+    wxStaticText* itemStaticText54 = new wxStaticText( itemPanel37, wxID_STATIC, _("&Indentation (tenths of a mm)"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemBoxSizer53->Add(itemStaticText54, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
 
-    wxBoxSizer* itemBoxSizer51 = new wxBoxSizer(wxHORIZONTAL);
-    itemBoxSizer49->Add(itemBoxSizer51, 0, wxALIGN_LEFT|wxALL, 5);
-    itemBoxSizer51->Add(5, 5, 0, wxALIGN_CENTER_VERTICAL, 5);
+    wxBoxSizer* itemBoxSizer55 = new wxBoxSizer(wxHORIZONTAL);
+    itemBoxSizer53->Add(itemBoxSizer55, 0, wxALIGN_LEFT|wxALL, 5);
+    itemBoxSizer55->Add(5, 5, 0, wxALIGN_CENTER_VERTICAL, 5);
 
-    wxFlexGridSizer* itemFlexGridSizer53 = new wxFlexGridSizer(2, 2, 0, 0);
-    itemBoxSizer51->Add(itemFlexGridSizer53, 0, wxALIGN_CENTER_VERTICAL, 5);
-    wxStaticText* itemStaticText54 = new wxStaticText( itemPanel33, wxID_STATIC, _("&Left:"), wxDefaultPosition, wxDefaultSize, 0 );
-    itemFlexGridSizer53->Add(itemStaticText54, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
+    wxFlexGridSizer* itemFlexGridSizer57 = new wxFlexGridSizer(2, 2, 0, 0);
+    itemBoxSizer55->Add(itemFlexGridSizer57, 0, wxALIGN_CENTER_VERTICAL, 5);
+    wxStaticText* itemStaticText58 = new wxStaticText( itemPanel37, wxID_STATIC, _("&Left:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemFlexGridSizer57->Add(itemStaticText58, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
 
-    wxBoxSizer* itemBoxSizer55 = new wxBoxSizer(wxHORIZONTAL);
-    itemFlexGridSizer53->Add(itemBoxSizer55, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
-    m_indentLeft = new wxTextCtrl( itemPanel33, ID_RICHTEXTLISTSTYLEPAGE_INDENTLEFT, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
+    wxBoxSizer* itemBoxSizer59 = new wxBoxSizer(wxHORIZONTAL);
+    itemFlexGridSizer57->Add(itemBoxSizer59, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
+    m_indentLeft = new wxTextCtrl( itemPanel37, ID_RICHTEXTLISTSTYLEPAGE_INDENTLEFT, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
     m_indentLeft->SetHelpText(_("The left indent."));
     if (ShowToolTips())
         m_indentLeft->SetToolTip(_("The left indent."));
-    itemBoxSizer55->Add(m_indentLeft, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+    itemBoxSizer59->Add(m_indentLeft, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
 
-    wxStaticText* itemStaticText57 = new wxStaticText( itemPanel33, wxID_STATIC, _("Left (&first line):"), wxDefaultPosition, wxDefaultSize, 0 );
-    itemFlexGridSizer53->Add(itemStaticText57, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
+    wxStaticText* itemStaticText61 = new wxStaticText( itemPanel37, wxID_STATIC, _("Left (&first line):"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemFlexGridSizer57->Add(itemStaticText61, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
 
-    wxBoxSizer* itemBoxSizer58 = new wxBoxSizer(wxHORIZONTAL);
-    itemFlexGridSizer53->Add(itemBoxSizer58, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
-    m_indentLeftFirst = new wxTextCtrl( itemPanel33, ID_RICHTEXTLISTSTYLEPAGE_INDENTFIRSTLINE, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
+    wxBoxSizer* itemBoxSizer62 = new wxBoxSizer(wxHORIZONTAL);
+    itemFlexGridSizer57->Add(itemBoxSizer62, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
+    m_indentLeftFirst = new wxTextCtrl( itemPanel37, ID_RICHTEXTLISTSTYLEPAGE_INDENTFIRSTLINE, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
     m_indentLeftFirst->SetHelpText(_("The first line indent."));
     if (ShowToolTips())
         m_indentLeftFirst->SetToolTip(_("The first line indent."));
-    itemBoxSizer58->Add(m_indentLeftFirst, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+    itemBoxSizer62->Add(m_indentLeftFirst, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
 
-    wxStaticText* itemStaticText60 = new wxStaticText( itemPanel33, wxID_STATIC, _("&Right:"), wxDefaultPosition, wxDefaultSize, 0 );
-    itemFlexGridSizer53->Add(itemStaticText60, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
+    wxStaticText* itemStaticText64 = new wxStaticText( itemPanel37, wxID_STATIC, _("&Right:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemFlexGridSizer57->Add(itemStaticText64, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
 
-    wxBoxSizer* itemBoxSizer61 = new wxBoxSizer(wxHORIZONTAL);
-    itemFlexGridSizer53->Add(itemBoxSizer61, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
-    m_indentRight = new wxTextCtrl( itemPanel33, ID_RICHTEXTLISTSTYLEPAGE_INDENTRIGHT, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
+    wxBoxSizer* itemBoxSizer65 = new wxBoxSizer(wxHORIZONTAL);
+    itemFlexGridSizer57->Add(itemBoxSizer65, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
+    m_indentRight = new wxTextCtrl( itemPanel37, ID_RICHTEXTLISTSTYLEPAGE_INDENTRIGHT, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
     m_indentRight->SetHelpText(_("The right indent."));
     if (ShowToolTips())
         m_indentRight->SetToolTip(_("The right indent."));
-    itemBoxSizer61->Add(m_indentRight, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+    itemBoxSizer65->Add(m_indentRight, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
 
-    itemBoxSizer35->Add(2, 1, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);
+    itemBoxSizer39->Add(2, 1, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);
 
-    wxStaticLine* itemStaticLine64 = new wxStaticLine( itemPanel33, wxID_STATIC, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
-    itemBoxSizer35->Add(itemStaticLine64, 0, wxGROW|wxTOP|wxBOTTOM, 5);
+    wxStaticLine* itemStaticLine68 = new wxStaticLine( itemPanel37, wxID_STATIC, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
+    itemBoxSizer39->Add(itemStaticLine68, 0, wxGROW|wxTOP|wxBOTTOM, 5);
 
-    itemBoxSizer35->Add(2, 1, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);
+    itemBoxSizer39->Add(2, 1, 1, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);
 
-    wxBoxSizer* itemBoxSizer66 = new wxBoxSizer(wxVERTICAL);
-    itemBoxSizer35->Add(itemBoxSizer66, 0, wxGROW, 5);
-    wxStaticText* itemStaticText67 = new wxStaticText( itemPanel33, wxID_STATIC, _("&Spacing (tenths of a mm)"), wxDefaultPosition, wxDefaultSize, 0 );
-    itemBoxSizer66->Add(itemStaticText67, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
+    wxBoxSizer* itemBoxSizer70 = new wxBoxSizer(wxVERTICAL);
+    itemBoxSizer39->Add(itemBoxSizer70, 0, wxGROW, 5);
+    wxStaticText* itemStaticText71 = new wxStaticText( itemPanel37, wxID_STATIC, _("&Spacing (tenths of a mm)"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemBoxSizer70->Add(itemStaticText71, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
 
-    wxBoxSizer* itemBoxSizer68 = new wxBoxSizer(wxHORIZONTAL);
-    itemBoxSizer66->Add(itemBoxSizer68, 0, wxALIGN_LEFT|wxALL, 5);
-    itemBoxSizer68->Add(5, 5, 0, wxALIGN_CENTER_VERTICAL, 5);
+    wxBoxSizer* itemBoxSizer72 = new wxBoxSizer(wxHORIZONTAL);
+    itemBoxSizer70->Add(itemBoxSizer72, 0, wxALIGN_LEFT|wxALL, 5);
+    itemBoxSizer72->Add(5, 5, 0, wxALIGN_CENTER_VERTICAL, 5);
 
-    wxFlexGridSizer* itemFlexGridSizer70 = new wxFlexGridSizer(2, 2, 0, 0);
-    itemBoxSizer68->Add(itemFlexGridSizer70, 0, wxALIGN_CENTER_VERTICAL, 5);
-    wxStaticText* itemStaticText71 = new wxStaticText( itemPanel33, wxID_STATIC, _("Before a paragraph:"), wxDefaultPosition, wxDefaultSize, 0 );
-    itemFlexGridSizer70->Add(itemStaticText71, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
+    wxFlexGridSizer* itemFlexGridSizer74 = new wxFlexGridSizer(2, 2, 0, 0);
+    itemBoxSizer72->Add(itemFlexGridSizer74, 0, wxALIGN_CENTER_VERTICAL, 5);
+    wxStaticText* itemStaticText75 = new wxStaticText( itemPanel37, wxID_STATIC, _("Before a paragraph:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemFlexGridSizer74->Add(itemStaticText75, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
 
-    wxBoxSizer* itemBoxSizer72 = new wxBoxSizer(wxHORIZONTAL);
-    itemFlexGridSizer70->Add(itemBoxSizer72, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
-    m_spacingBefore = new wxTextCtrl( itemPanel33, ID_RICHTEXTLISTSTYLEPAGE_SPACINGBEFORE, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
+    wxBoxSizer* itemBoxSizer76 = new wxBoxSizer(wxHORIZONTAL);
+    itemFlexGridSizer74->Add(itemBoxSizer76, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
+    m_spacingBefore = new wxTextCtrl( itemPanel37, ID_RICHTEXTLISTSTYLEPAGE_SPACINGBEFORE, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
     m_spacingBefore->SetHelpText(_("The spacing before the paragraph."));
     if (ShowToolTips())
         m_spacingBefore->SetToolTip(_("The spacing before the paragraph."));
-    itemBoxSizer72->Add(m_spacingBefore, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+    itemBoxSizer76->Add(m_spacingBefore, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
 
-    wxStaticText* itemStaticText74 = new wxStaticText( itemPanel33, wxID_STATIC, _("After a paragraph:"), wxDefaultPosition, wxDefaultSize, 0 );
-    itemFlexGridSizer70->Add(itemStaticText74, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
+    wxStaticText* itemStaticText78 = new wxStaticText( itemPanel37, wxID_STATIC, _("After a paragraph:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemFlexGridSizer74->Add(itemStaticText78, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
 
-    wxBoxSizer* itemBoxSizer75 = new wxBoxSizer(wxHORIZONTAL);
-    itemFlexGridSizer70->Add(itemBoxSizer75, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
-    m_spacingAfter = new wxTextCtrl( itemPanel33, ID_RICHTEXTLISTSTYLEPAGE_SPACINGAFTER, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
+    wxBoxSizer* itemBoxSizer79 = new wxBoxSizer(wxHORIZONTAL);
+    itemFlexGridSizer74->Add(itemBoxSizer79, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
+    m_spacingAfter = new wxTextCtrl( itemPanel37, ID_RICHTEXTLISTSTYLEPAGE_SPACINGAFTER, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
     m_spacingAfter->SetHelpText(_("The spacing after the paragraph."));
     if (ShowToolTips())
         m_spacingAfter->SetToolTip(_("The spacing after the paragraph."));
-    itemBoxSizer75->Add(m_spacingAfter, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+    itemBoxSizer79->Add(m_spacingAfter, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
 
-    wxStaticText* itemStaticText77 = new wxStaticText( itemPanel33, wxID_STATIC, _("Line spacing:"), wxDefaultPosition, wxDefaultSize, 0 );
-    itemFlexGridSizer70->Add(itemStaticText77, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
+    wxStaticText* itemStaticText81 = new wxStaticText( itemPanel37, wxID_STATIC, _("Line spacing:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemFlexGridSizer74->Add(itemStaticText81, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
 
-    wxBoxSizer* itemBoxSizer78 = new wxBoxSizer(wxHORIZONTAL);
-    itemFlexGridSizer70->Add(itemBoxSizer78, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
+    wxBoxSizer* itemBoxSizer82 = new wxBoxSizer(wxHORIZONTAL);
+    itemFlexGridSizer74->Add(itemBoxSizer82, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
     wxString m_spacingLineStrings[] = {
         _("Single"),
         _("1.5"),
         _("2")
     };
-    m_spacingLine = new wxComboBox( itemPanel33, ID_RICHTEXTLISTSTYLEPAGE_LINESPACING, _("Single"), wxDefaultPosition, wxDefaultSize, 3, m_spacingLineStrings, wxCB_READONLY );
+    m_spacingLine = new wxComboBox( itemPanel37, ID_RICHTEXTLISTSTYLEPAGE_LINESPACING, _("Single"), wxDefaultPosition, wxDefaultSize, 3, m_spacingLineStrings, wxCB_READONLY );
     m_spacingLine->SetStringSelection(_("Single"));
     m_spacingLine->SetHelpText(_("The line spacing."));
     if (ShowToolTips())
         m_spacingLine->SetToolTip(_("The line spacing."));
-    itemBoxSizer78->Add(m_spacingLine, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+    itemBoxSizer82->Add(m_spacingLine, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
 
-    itemBook9->AddPage(itemPanel33, _("Spacing"));
+    itemNotebook9->AddPage(itemPanel37, _("Spacing"));
 
-    itemBoxSizer3->Add(itemBook9, 0, wxGROW|wxALL, 5);
+    itemBoxSizer3->Add(itemNotebook9, 0, wxGROW|wxALL, 5);
 
-    m_previewCtrl = new wxRichTextCtrl( itemPanel1, ID_RICHTEXTLISTSTYLEPAGE_RICHTEXTCTRL, wxEmptyString, wxDefaultPosition, wxSize(350, 180), wxSUNKEN_BORDER );
+    m_previewCtrl = new wxRichTextCtrl( itemPanel1, ID_RICHTEXTLISTSTYLEPAGE_RICHTEXTCTRL, wxEmptyString, wxDefaultPosition, wxSize(350, 180), wxSUNKEN_BORDER|wxTE_READONLY );
     m_previewCtrl->SetHelpText(_("Shows a preview of the bullet settings."));
     if (ShowToolTips())
         m_previewCtrl->SetToolTip(_("Shows a preview of the bullet settings."));
@@ -449,12 +480,15 @@ void wxRichTextListStylePage::CreateControls()
 
 ////@end wxRichTextListStylePage content construction
 
+    m_dontUpdate = true;
+    
     m_styleListBox->Append(_("(None)"));
     m_styleListBox->Append(_("Arabic"));
     m_styleListBox->Append(_("Upper case letters"));
     m_styleListBox->Append(_("Lower case letters"));
     m_styleListBox->Append(_("Upper case roman numerals"));
     m_styleListBox->Append(_("Lower case roman numerals"));
+    m_styleListBox->Append(_("Numbered outline"));
     m_styleListBox->Append(_("Symbol"));
     m_styleListBox->Append(_("Bitmap"));
     m_styleListBox->Append(_("Standard"));
@@ -464,14 +498,20 @@ void wxRichTextListStylePage::CreateControls()
     m_symbolCtrl->Append(_(">"));
     m_symbolCtrl->Append(_("+"));
     m_symbolCtrl->Append(_("~"));
+    
+    wxArrayString standardBulletNames;
+    if (wxRichTextBuffer::GetRenderer())
+        wxRichTextBuffer::GetRenderer()->EnumerateStandardBulletNames(standardBulletNames);
 
-    m_bulletNameCtrl->Append(_("standard/round"));
-    m_bulletNameCtrl->Append(_("standard/square"));
-
+    m_bulletNameCtrl->Append(standardBulletNames);
     wxArrayString facenames = wxRichTextCtrl::GetAvailableFontNames();
     facenames.Sort();
 
     m_symbolFontCtrl->Append(facenames);
+
+    m_levelCtrl->SetValue(m_currentLevel);
+
+    m_dontUpdate = false;
 }
 
 /// Updates the font preview
@@ -492,7 +532,7 @@ iaculis malesuada. Donec bibendum ipsum ut ante porta fringilla.\n");
     attr.SetFlags(attr.GetFlags() &
       (wxTEXT_ATTR_ALIGNMENT|wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT|wxTEXT_ATTR_PARA_SPACING_BEFORE|wxTEXT_ATTR_PARA_SPACING_AFTER|
        wxTEXT_ATTR_LINE_SPACING|
-       wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER|wxTEXT_ATTR_BULLET_SYMBOL));
+       wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER|wxTEXT_ATTR_BULLET_TEXT));
 
     wxFont font(m_previewCtrl->GetFont());
     font.SetPointSize(9);
@@ -510,6 +550,7 @@ iaculis malesuada. Donec bibendum ipsum ut ante porta fringilla.\n");
     m_previewCtrl->EndStyle();
 
     m_previewCtrl->BeginStyle(attr);
+    long listStart = m_previewCtrl->GetInsertionPoint() + 1;
 
     int i;
     for (i = 0; i < 10; i++)
@@ -521,11 +562,14 @@ iaculis malesuada. Donec bibendum ipsum ut ante porta fringilla.\n");
         m_previewCtrl->EndStyle();
     }
     m_previewCtrl->EndStyle();
+    long listEnd = m_previewCtrl->GetInsertionPoint();
 
     m_previewCtrl->BeginStyle(normalParaAttr);
     m_previewCtrl->WriteText(s_para3);
     m_previewCtrl->EndStyle();
 
+    m_previewCtrl->NumberList(wxRichTextRange(listStart, listEnd), def);
+
     m_previewCtrl->Thaw();
 }
 
@@ -536,7 +580,7 @@ bool wxRichTextListStylePage::TransferDataFromWindow()
 
     m_currentLevel = m_levelCtrl->GetValue();
 
-    wxTextAttrEx* attr = GetAttributesForSelection();
+    wxRichTextAttr* attr = GetAttributesForSelection();
 
     if (m_alignmentLeft->GetValue())
         attr->SetAlignment(wxTEXT_ALIGNMENT_LEFT);
@@ -604,21 +648,31 @@ bool wxRichTextListStylePage::TransferDataFromWindow()
         long bulletStyle = 0;
 
         int index = m_styleListBox->GetSelection();
-        if (index == 1)
+        if (index == wxRICHTEXT_BULLETINDEX_ARABIC)
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_ARABIC;
-        else if (index == 2)
+
+        else if (index == wxRICHTEXT_BULLETINDEX_UPPER_CASE)
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER;
-        else if (index == 3)
+
+        else if (index == wxRICHTEXT_BULLETINDEX_LOWER_CASE)
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER;
-        else if (index == 4)
+
+        else if (index == wxRICHTEXT_BULLETINDEX_UPPER_CASE_ROMAN)
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER;
-        else if (index == 5)
+
+        else if (index == wxRICHTEXT_BULLETINDEX_LOWER_CASE_ROMAN)
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER;
-        else if (index == 6)
+
+        else if (index == wxRICHTEXT_BULLETINDEX_OUTLINE)
+            bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_OUTLINE;
+
+        else if (index == wxRICHTEXT_BULLETINDEX_SYMBOL)
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_SYMBOL;
-        else if (index == 7)
+
+        else if (index == wxRICHTEXT_BULLETINDEX_BITMAP)
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_BITMAP;
-        else if (index == 8)
+
+        else if (index == wxRICHTEXT_BULLETINDEX_STANDARD)
         {
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_STANDARD;
             attr->SetBulletName(m_bulletNameCtrl->GetValue());
@@ -626,18 +680,23 @@ bool wxRichTextListStylePage::TransferDataFromWindow()
 
         if (m_parenthesesCtrl->GetValue())
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_PARENTHESES;
+        if (m_rightParenthesisCtrl->GetValue())
+            bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_RIGHT_PARENTHESIS;
         if (m_periodCtrl->GetValue())
             bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_PERIOD;
 
+        if (m_bulletAlignmentCtrl->GetSelection() == 1)
+            bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_ALIGN_CENTRE;
+        else if (m_bulletAlignmentCtrl->GetSelection() == 2)
+            bulletStyle |= wxTEXT_ATTR_BULLET_STYLE_ALIGN_RIGHT;
+        // Left is implied            
+
         attr->SetBulletStyle(bulletStyle);
     }
 
     // if (m_hasBulletSymbol)
     {
-        wxChar c(wxT('*'));
-        if (m_symbolCtrl->GetValue().length() > 0)
-            c = m_symbolCtrl->GetValue()[0];
-        attr->SetBulletSymbol(c);
+        attr->SetBulletText(m_symbolCtrl->GetValue());
         attr->SetBulletFont(m_symbolFontCtrl->GetValue());
     }
 
@@ -659,9 +718,7 @@ void wxRichTextListStylePage::DoTransferDataToWindow()
 
     wxPanel::TransferDataToWindow();
 
-    m_levelCtrl->SetValue(m_currentLevel);
-
-    wxTextAttrEx* attr = GetAttributesForSelection();
+    wxRichTextAttr* attr = GetAttributesForSelection();
 
     if (attr->HasAlignment())
     {
@@ -742,23 +799,34 @@ void wxRichTextListStylePage::DoTransferDataToWindow()
     /// BULLETS
     if (attr->HasBulletStyle())
     {
-        int index = -1;
+        int index = 0;
         if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ARABIC)
-            index = 1;
+            index = wxRICHTEXT_BULLETINDEX_ARABIC;
+
         else if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER)
-            index = 2;
+            index = wxRICHTEXT_BULLETINDEX_UPPER_CASE;
+
         else if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER)
-            index = 3;
+            index = wxRICHTEXT_BULLETINDEX_LOWER_CASE;
+
         else if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER)
-            index = 4;
+            index = wxRICHTEXT_BULLETINDEX_UPPER_CASE_ROMAN;
+
         else if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER)
-            index = 5;
+            index = wxRICHTEXT_BULLETINDEX_LOWER_CASE_ROMAN;
+
+        else if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_OUTLINE)
+            index = wxRICHTEXT_BULLETINDEX_OUTLINE;
+
         else if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_SYMBOL)
-            index = 6;
+            index = wxRICHTEXT_BULLETINDEX_SYMBOL;
+
         else if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_BITMAP)
-            index = 7;
+            index = wxRICHTEXT_BULLETINDEX_BITMAP;
+
         else if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_STANDARD)
-            index = 8;
+            index = wxRICHTEXT_BULLETINDEX_STANDARD;
+
         m_styleListBox->SetSelection(index);
 
         if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_PARENTHESES)
@@ -766,20 +834,32 @@ void wxRichTextListStylePage::DoTransferDataToWindow()
         else
             m_parenthesesCtrl->SetValue(false);
 
+        if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_RIGHT_PARENTHESIS)
+            m_rightParenthesisCtrl->SetValue(true);
+        else
+            m_rightParenthesisCtrl->SetValue(false);
+
         if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_PERIOD)
             m_periodCtrl->SetValue(true);
         else
             m_periodCtrl->SetValue(false);
+
+        if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ALIGN_CENTRE)
+            m_bulletAlignmentCtrl->SetSelection(1);
+        else if (attr->GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_ALIGN_RIGHT)
+            m_bulletAlignmentCtrl->SetSelection(2);
+        else
+            m_bulletAlignmentCtrl->SetSelection(0);
     }
     else
+    {
         m_styleListBox->SetSelection(-1);
+        m_bulletAlignmentCtrl->SetSelection(-1);
+    }
 
-    if (attr->HasBulletSymbol())
+    if (attr->HasBulletText())
     {
-        wxChar c = attr->GetBulletSymbol();
-        wxString s;
-        s << c;
-        m_symbolCtrl->SetValue(s);
+        m_symbolCtrl->SetValue(attr->GetBulletText());
         m_symbolFontCtrl->SetValue(attr->GetBulletFont());
     }
     else
@@ -794,7 +874,7 @@ void wxRichTextListStylePage::DoTransferDataToWindow()
 }
 
 /// Get attributes for selected level
-wxTextAttrEx* wxRichTextListStylePage::GetAttributesForSelection()
+wxRichTextAttr* wxRichTextListStylePage::GetAttributesForSelection()
 {
     wxRichTextListStyleDefinition* def = wxDynamicCast(wxRichTextFormattingDialog::GetDialogStyleDefinition(this),
         wxRichTextListStyleDefinition);
@@ -937,7 +1017,7 @@ void wxRichTextListStylePage::OnSymbolctrlUIUpdate( wxUpdateUIEvent& event )
 void wxRichTextListStylePage::OnChooseSymbolClick( wxCommandEvent& WXUNUSED(event) )
 {
     int sel = m_styleListBox->GetSelection();
-    if (sel == 6)
+    if (sel == wxRICHTEXT_BULLETINDEX_SYMBOL)
     {
         wxString symbol = m_symbolCtrl->GetValue();
         wxString fontName = m_symbolFontCtrl->GetValue();
@@ -1008,10 +1088,10 @@ void wxRichTextListStylePage::OnParenthesesctrlClick( wxCommandEvent& WXUNUSED(e
 
 void wxRichTextListStylePage::OnParenthesesctrlUpdate( wxUpdateUIEvent& event )
 {
-////@begin wxEVT_UPDATE_UI event handler for ID_RICHTEXTLISTSTYLEPAGE__PARENTHESESCTRL in wxRichTextListStylePage.
-    // Before editing this code, remove the block markers.
-    event.Skip();
-////@end wxEVT_UPDATE_UI event handler for ID_RICHTEXTLISTSTYLEPAGE__PARENTHESESCTRL in wxRichTextListStylePage.
+    int sel = m_styleListBox->GetSelection();
+    event.Enable((sel != wxRICHTEXT_BULLETINDEX_SYMBOL &&
+                  sel != wxRICHTEXT_BULLETINDEX_BITMAP &&
+                  sel != wxRICHTEXT_BULLETINDEX_NONE));
 }
 
 /*!
@@ -1029,10 +1109,10 @@ void wxRichTextListStylePage::OnPeriodctrlClick( wxCommandEvent& WXUNUSED(event)
 
 void wxRichTextListStylePage::OnPeriodctrlUpdate( wxUpdateUIEvent& event )
 {
-////@begin wxEVT_UPDATE_UI event handler for ID_RICHTEXTLISTSTYLEPAGE_PERIODCTRL in wxRichTextListStylePage.
-    // Before editing this code, remove the block markers.
-    event.Skip();
-////@end wxEVT_UPDATE_UI event handler for ID_RICHTEXTLISTSTYLEPAGE_PERIODCTRL in wxRichTextListStylePage.
+    int sel = m_styleListBox->GetSelection();
+    event.Enable((sel != wxRICHTEXT_BULLETINDEX_SYMBOL &&
+                  sel != wxRICHTEXT_BULLETINDEX_BITMAP &&
+                  sel != wxRICHTEXT_BULLETINDEX_NONE));
 }
 
 /*!
@@ -1173,21 +1253,24 @@ wxIcon wxRichTextListStylePage::GetIconResource( const wxString& name )
 void wxRichTextListStylePage::OnSymbolUpdate( wxUpdateUIEvent& event )
 {
     int sel = m_styleListBox->GetSelection();
-    event.Enable(sel == 6);
+    event.Enable(sel == wxRICHTEXT_BULLETINDEX_SYMBOL);
 }
 
 /// Update for number-related controls
 void wxRichTextListStylePage::OnNumberUpdate( wxUpdateUIEvent& event )
 {
     int sel = m_styleListBox->GetSelection();
-    event.Enable((sel != 6 && sel != 7 && sel != 8 && sel != 0));
+    event.Enable((sel != wxRICHTEXT_BULLETINDEX_SYMBOL &&
+                  sel != wxRICHTEXT_BULLETINDEX_BITMAP &&
+                  sel != wxRICHTEXT_BULLETINDEX_STANDARD &&
+                  sel != wxRICHTEXT_BULLETINDEX_NONE));
 }
 
 /// Update for standard bullet-related controls
 void wxRichTextListStylePage::OnStandardBulletUpdate( wxUpdateUIEvent& event )
 {
     int sel = m_styleListBox->GetSelection();
-    event.Enable( sel == 8 );
+    event.Enable( sel == wxRICHTEXT_BULLETINDEX_STANDARD );
 }
 
 /*!
@@ -1196,7 +1279,7 @@ void wxRichTextListStylePage::OnStandardBulletUpdate( wxUpdateUIEvent& event )
 
 void wxRichTextListStylePage::OnChooseFontClick( wxCommandEvent& WXUNUSED(event) )
 {
-    wxTextAttrEx* attr = GetAttributesForSelection();
+    wxRichTextAttr* attr = GetAttributesForSelection();
 
     int pages = wxRICHTEXT_FORMAT_FONT;
     wxRichTextFormattingDialog formatDlg;
@@ -1244,3 +1327,34 @@ void wxRichTextListStylePage::OnNamectrlUIUpdate( wxUpdateUIEvent& event )
 {
     OnStandardBulletUpdate(event);
 }
+/*!
+ * wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_RICHTEXTLISTSTYLEPAGE_RIGHTPARENTHESISCTRL
+ */
+
+void wxRichTextListStylePage::OnRightParenthesisCtrlClick( wxCommandEvent& WXUNUSED(event) )
+{
+    TransferAndPreview();
+}
+
+/*!
+ * wxEVT_UPDATE_UI event handler for ID_RICHTEXTLISTSTYLEPAGE_RIGHTPARENTHESISCTRL
+ */
+
+void wxRichTextListStylePage::OnRightParenthesisCtrlUpdate( wxUpdateUIEvent& event )
+{
+    int sel = m_styleListBox->GetSelection();
+    event.Enable((sel != wxRICHTEXT_BULLETINDEX_SYMBOL &&
+                  sel != wxRICHTEXT_BULLETINDEX_BITMAP &&
+                  sel != wxRICHTEXT_BULLETINDEX_NONE));
+}
+
+/*!
+ * wxEVT_COMMAND_COMBOBOX_SELECTED event handler for ID_RICHTEXTLISTSTYLEPAGE_BULLETALIGNMENTCTRL
+ */
+
+void wxRichTextListStylePage::OnBulletAlignmentCtrlSelected( wxCommandEvent& WXUNUSED(event) )
+{
+    TransferAndPreview();
+}
+
+
diff --git a/src/richtext/richtextstyledlg.cpp b/src/richtext/richtextstyledlg.cpp
index 8ffb037227..79080f7959 100644
--- a/src/richtext/richtextstyledlg.cpp
+++ b/src/richtext/richtextstyledlg.cpp
@@ -456,6 +456,7 @@ iaculis malesuada. Donec bibendum ipsum ut ante porta fringilla.\n");
 
     if (listDef)
     {
+        long listStart = m_previewCtrl->GetInsertionPoint() + 1;
         int i;
         for (i = 0; i < 10; i++)
         {
@@ -465,6 +466,8 @@ iaculis malesuada. Donec bibendum ipsum ut ante porta fringilla.\n");
             m_previewCtrl->WriteText(wxString::Format(wxT("\nList level %d. "), i+1) + s_para2List);
             m_previewCtrl->EndStyle();
         }
+        long listEnd = m_previewCtrl->GetInsertionPoint();
+        m_previewCtrl->NumberList(wxRichTextRange(listStart, listEnd), listDef);
     }
     else
     {
diff --git a/src/richtext/richtextstyles.cpp b/src/richtext/richtextstyles.cpp
index e40229b843..a0817a69b2 100644
--- a/src/richtext/richtextstyles.cpp
+++ b/src/richtext/richtextstyles.cpp
@@ -94,14 +94,14 @@ bool wxRichTextListStyleDefinition::operator ==(const wxRichTextListStyleDefinit
 }
 
 /// Sets/gets the attributes for the given level
-void wxRichTextListStyleDefinition::SetLevelAttributes(int i, const wxTextAttrEx& attr)
+void wxRichTextListStyleDefinition::SetLevelAttributes(int i, const wxRichTextAttr& attr)
 {
     wxASSERT( (i >= 0 && i < 10) );
     if (i >= 0 && i < 10)
         m_levelStyles[i] = attr;
 }
 
-const wxTextAttrEx* wxRichTextListStyleDefinition::GetLevelAttributes(int i) const
+const wxRichTextAttr* wxRichTextListStyleDefinition::GetLevelAttributes(int i) const
 {
     wxASSERT( (i >= 0 && i < 10) );
     if (i >= 0 && i < 10)
@@ -110,7 +110,7 @@ const wxTextAttrEx* wxRichTextListStyleDefinition::GetLevelAttributes(int i) con
         return NULL;
 }
 
-wxTextAttrEx* wxRichTextListStyleDefinition::GetLevelAttributes(int i)
+wxRichTextAttr* wxRichTextListStyleDefinition::GetLevelAttributes(int i)
 {
     wxASSERT( (i >= 0 && i < 10) );
     if (i >= 0 && i < 10)
@@ -125,13 +125,18 @@ void wxRichTextListStyleDefinition::SetAttributes(int i, int leftIndent, int lef
     wxASSERT( (i >= 0 && i < 10) );
     if (i >= 0 && i < 10)
     {
-        wxTextAttrEx attr;
+        wxRichTextAttr attr;
 
         attr.SetBulletStyle(bulletStyle);
         attr.SetLeftIndent(leftIndent, leftSubIndent);
 
         if (!bulletSymbol.IsEmpty())
-            attr.SetBulletSymbol(bulletSymbol[0]);
+        {
+            if (bulletStyle & wxTEXT_ATTR_BULLET_STYLE_SYMBOL)
+                attr.SetBulletText(bulletSymbol);
+            else
+                attr.SetBulletName(bulletSymbol);
+        }
 
         m_levelStyles[i] = attr;
     }
@@ -156,11 +161,11 @@ int wxRichTextListStyleDefinition::FindLevelForIndent(int indent) const
 
 /// Combine the list style with a paragraph style, using the given indent (from which
 /// an appropriate level is found)
-wxTextAttrEx wxRichTextListStyleDefinition::CombineWithParagraphStyle(int indent, const wxTextAttrEx& paraStyle)
+wxRichTextAttr wxRichTextListStyleDefinition::CombineWithParagraphStyle(int indent, const wxRichTextAttr& paraStyle)
 {
     int listLevel = FindLevelForIndent(indent);
 
-    wxTextAttrEx attr(*GetLevelAttributes(listLevel));
+    wxRichTextAttr attr(*GetLevelAttributes(listLevel));
     int oldLeftIndent = attr.GetLeftIndent();
     int oldLeftSubIndent = attr.GetLeftSubIndent();
 
@@ -178,7 +183,7 @@ wxTextAttrEx wxRichTextListStyleDefinition::CombineWithParagraphStyle(int indent
 
 /// Combine the base and list style, using the given indent (from which
 /// an appropriate level is found)
-wxTextAttrEx wxRichTextListStyleDefinition::GetCombinedStyle(int indent)
+wxRichTextAttr wxRichTextListStyleDefinition::GetCombinedStyle(int indent)
 {
     int listLevel = FindLevelForIndent(indent);
     return GetCombinedStyleForLevel(listLevel);
@@ -186,9 +191,9 @@ wxTextAttrEx wxRichTextListStyleDefinition::GetCombinedStyle(int indent)
 
 /// Combine the base and list style, using the given indent (from which
 /// an appropriate level is found)
-wxTextAttrEx wxRichTextListStyleDefinition::GetCombinedStyleForLevel(int listLevel)
+wxRichTextAttr wxRichTextListStyleDefinition::GetCombinedStyleForLevel(int listLevel)
 {
-    wxTextAttrEx attr(*GetLevelAttributes(listLevel));
+    wxRichTextAttr attr(*GetLevelAttributes(listLevel));
     int oldLeftIndent = attr.GetLeftIndent();
     int oldLeftSubIndent = attr.GetLeftSubIndent();
 
diff --git a/src/richtext/richtextxml.cpp b/src/richtext/richtextxml.cpp
index 4184e2fa3c..801c5d2fbc 100644
--- a/src/richtext/richtextxml.cpp
+++ b/src/richtext/richtextxml.cpp
@@ -210,6 +210,27 @@ bool wxRichTextXMLHandler::ImportXML(wxRichTextBuffer* buffer, wxXmlNode* node)
 
         doneChildren = true;
     }
+    else if (name == wxT("stylesheet"))
+    {
+        if (GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET)
+        {
+            wxRichTextStyleSheet* sheet = new wxRichTextStyleSheet;
+            
+            wxXmlNode* child = node->GetChildren();
+            while (child)
+            {
+                ImportStyleDefinition(sheet, child);
+                
+                child = child->GetNext();
+            }
+            
+            // Notify that styles have changed. If this is vetoed by the app,
+            // the new sheet will be deleted. If it is not vetoed, the
+            // old sheet will be deleted and replaced with the new one.
+            buffer->SetStyleSheetAndNotify(sheet);
+        }
+        doneChildren = true;
+    }
 
     if (!doneChildren)
     {
@@ -224,6 +245,94 @@ bool wxRichTextXMLHandler::ImportXML(wxRichTextBuffer* buffer, wxXmlNode* node)
     return true;
 }
 
+bool wxRichTextXMLHandler::ImportStyleDefinition(wxRichTextStyleSheet* sheet, wxXmlNode* node)
+{
+    wxString styleType = node->GetName();    
+    wxString styleName = node->GetPropVal(wxT("name"), wxEmptyString);
+    wxString baseStyleName = node->GetPropVal(wxT("basestyle"), wxEmptyString);
+    
+    if (styleName.IsEmpty())
+        return false;
+    
+    if (styleType == wxT("characterstyle"))
+    {
+        wxRichTextCharacterStyleDefinition* def = new wxRichTextCharacterStyleDefinition(styleName);
+        def->SetBaseStyle(baseStyleName);
+
+        wxXmlNode* child = node->GetChildren();
+        while (child)
+        {
+            if (child->GetName() == wxT("style"))
+            {
+                wxTextAttrEx attr;
+                GetStyle(attr, child, false);
+                def->SetStyle(attr);
+            }
+            child = child->GetNext();
+        }
+        
+        sheet->AddCharacterStyle(def);
+    }
+    else if (styleType == wxT("paragraphstyle"))
+    {
+        wxRichTextParagraphStyleDefinition* def = new wxRichTextParagraphStyleDefinition(styleName);
+
+        wxString nextStyleName = node->GetPropVal(wxT("nextstyle"), wxEmptyString);
+        def->SetNextStyle(nextStyleName);
+        def->SetBaseStyle(baseStyleName);
+
+        wxXmlNode* child = node->GetChildren();
+        while (child)
+        {
+            if (child->GetName() == wxT("style"))
+            {
+                wxTextAttrEx attr;
+                GetStyle(attr, child, false);
+                def->SetStyle(attr);
+            }
+            child = child->GetNext();
+        }
+
+        sheet->AddParagraphStyle(def);
+    }
+    else if (styleType == wxT("liststyle"))
+    {
+        wxRichTextListStyleDefinition* def = new wxRichTextListStyleDefinition(styleName);
+
+        wxString nextStyleName = node->GetPropVal(wxT("nextstyle"), wxEmptyString);
+        def->SetNextStyle(nextStyleName);
+        def->SetBaseStyle(baseStyleName);
+
+        wxXmlNode* child = node->GetChildren();
+        while (child)
+        {
+            if (child->GetName() == wxT("style"))
+            {
+                wxTextAttrEx attr;
+                GetStyle(attr, child, false);
+
+                wxString styleLevel = child->GetPropVal(wxT("level"), wxEmptyString);
+                if (styleLevel.IsEmpty())
+                {                
+                    def->SetStyle(attr);
+                }
+                else
+                {
+                    int level = wxAtoi(styleLevel);
+                    if (level > 0 && level <= 10)
+                    {
+                        def->SetLevelAttributes(level-1, attr);
+                    }
+                }
+            }
+            child = child->GetNext();
+        }
+
+        sheet->AddListStyle(def);
+    }
+    
+    return true;
+}
 
 //-----------------------------------------------------------------------------
 //  xml support routines
@@ -460,8 +569,39 @@ bool wxRichTextXMLHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream&
     OutputString(stream, wxT("<richtext version=\"1.0.0.0\" xmlns=\"http://www.wxwidgets.org\">") , NULL, NULL);
 
     int level = 1;
-    bool success = ExportXML(stream, convMem, convFile, *buffer, level);
 
+    if (buffer->GetStyleSheet() && (GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET))
+    {
+        OutputIndentation(stream, level);
+        OutputString(stream, wxT("<stylesheet>"), convMem, convFile);
+
+        int i;
+
+        for (i = 0; i < (int) buffer->GetStyleSheet()->GetCharacterStyleCount(); i++)
+        {
+            wxRichTextCharacterStyleDefinition* def = buffer->GetStyleSheet()->GetCharacterStyle(i);
+            ExportStyleDefinition(stream, convMem, convFile, def, level + 1);
+        }
+
+        for (i = 0; i < (int) buffer->GetStyleSheet()->GetParagraphStyleCount(); i++)
+        {
+            wxRichTextParagraphStyleDefinition* def = buffer->GetStyleSheet()->GetParagraphStyle(i);
+            ExportStyleDefinition(stream, convMem, convFile, def, level + 1);
+        }
+
+        for (i = 0; i < (int) buffer->GetStyleSheet()->GetListStyleCount(); i++)
+        {
+            wxRichTextListStyleDefinition* def = buffer->GetStyleSheet()->GetListStyle(i);
+            ExportStyleDefinition(stream, convMem, convFile, def, level + 1);
+        }
+
+        OutputIndentation(stream, level);
+        OutputString(stream, wxT("</stylesheet>"), convMem, convFile);
+    }
+
+
+    bool success = ExportXML(stream, convMem, convFile, *buffer, level);
+    
     OutputString(stream, wxT("\n</richtext>") , NULL, NULL);
     OutputString(stream, wxT("\n"), NULL, NULL);
 
@@ -622,6 +762,106 @@ bool wxRichTextXMLHandler::ExportXML(wxOutputStream& stream, wxMBConv* convMem,
     return true;
 }
 
+bool wxRichTextXMLHandler::ExportStyleDefinition(wxOutputStream& stream, wxMBConv* convMem, wxMBConv* convFile, wxRichTextStyleDefinition* def, int level)
+{
+    wxRichTextCharacterStyleDefinition* charDef = wxDynamicCast(def, wxRichTextCharacterStyleDefinition);    
+    wxRichTextParagraphStyleDefinition* paraDef = wxDynamicCast(def, wxRichTextParagraphStyleDefinition);
+    wxRichTextListStyleDefinition* listDef = wxDynamicCast(def, wxRichTextListStyleDefinition);
+    
+    wxString baseStyle = def->GetBaseStyle();
+    wxString baseStyleProp;
+    if (!baseStyle.IsEmpty())
+        baseStyleProp = wxT(" basestyle=\"") + baseStyle + wxT("\"");
+    
+    if (charDef)
+    {
+        OutputIndentation(stream, level);
+        OutputString(stream, wxT("<characterstyle") + baseStyleProp + wxT(">"), convMem, convFile);
+        
+        level ++;
+
+        wxString style = CreateStyle(def->GetStyle(), false);
+
+        OutputIndentation(stream, level);
+        OutputString(stream, wxT("<style ") + style + wxT(">"), convMem, convFile);
+        
+        OutputIndentation(stream, level);
+        OutputString(stream, wxT("</style>"), convMem, convFile);
+
+        level --;
+
+        OutputIndentation(stream, level);
+        OutputString(stream, wxT("</characterstyle>"), convMem, convFile);
+    }
+    else if (listDef)
+    {
+        OutputIndentation(stream, level);
+        
+        if (!listDef->GetNextStyle().IsEmpty())
+            baseStyleProp << wxT(" basestyle=\"") << listDef->GetNextStyle() << wxT("\"");
+        
+        OutputString(stream, wxT("<liststyle") + baseStyleProp + wxT(">"), convMem, convFile);
+        
+        level ++;
+
+        wxString style = CreateStyle(def->GetStyle(), false);
+
+        OutputIndentation(stream, level);
+        OutputString(stream, wxT("<style ") + style + wxT(">"), convMem, convFile);
+        
+        OutputIndentation(stream, level);
+        OutputString(stream, wxT("</style>"), convMem, convFile);
+
+        int i;
+        for (i = 0; i < 10; i ++)
+        {
+            wxRichTextAttr* levelAttr = listDef->GetLevelAttributes(i);
+            if (levelAttr)
+            {
+                wxString style = CreateStyle(def->GetStyle(), false);
+                wxString levelStr = wxString::Format(wxT(" level=\"%d\" "), (i+1));
+
+                OutputIndentation(stream, level);
+                OutputString(stream, wxT("<style ") + levelStr + style + wxT(">"), convMem, convFile);
+        
+                OutputIndentation(stream, level);
+                OutputString(stream, wxT("</style>"), convMem, convFile);
+            }
+        }
+
+        level --;
+
+        OutputIndentation(stream, level);
+        OutputString(stream, wxT("</liststyle>"), convMem, convFile);
+    }
+    else if (paraDef)
+    {
+        OutputIndentation(stream, level);
+        
+        if (!listDef->GetNextStyle().IsEmpty())
+            baseStyleProp << wxT(" basestyle=\"") << listDef->GetNextStyle() << wxT("\"");
+        
+        OutputString(stream, wxT("<paragraphstyle") + baseStyleProp + wxT(">"), convMem, convFile);
+        
+        level ++;
+
+        wxString style = CreateStyle(def->GetStyle(), false);
+
+        OutputIndentation(stream, level);
+        OutputString(stream, wxT("<style ") + style + wxT(">"), convMem, convFile);
+        
+        OutputIndentation(stream, level);
+        OutputString(stream, wxT("</style>"), convMem, convFile);
+        
+        level --;
+
+        OutputIndentation(stream, level);
+        OutputString(stream, wxT("</paragraphstyle>"), convMem, convFile);
+    }
+
+    return true;
+}
+
 /// Create style parameters
 wxString wxRichTextXMLHandler::CreateStyle(const wxTextAttrEx& attr, bool isPara)
 {
@@ -688,15 +928,24 @@ wxString wxRichTextXMLHandler::CreateStyle(const wxTextAttrEx& attr, bool isPara
         if (attr.HasBulletNumber())
             str << wxT(" bulletnumber=\"") << (int) attr.GetBulletNumber() << wxT("\"");
 
-        if (attr.HasBulletSymbol())
+        if (attr.HasBulletText())
         {
-            str << wxT(" bulletsymbol=\"") << (int) (attr.GetBulletSymbol()) << wxT("\"");
+            // If using a bullet symbol, convert to integer in case it's a non-XML-friendly character.
+            // Otherwise, assume it's XML-friendly text such as outline numbering, e.g. 1.2.3.1
+            if (!attr.GetBulletText().IsEmpty() && (attr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_SYMBOL))
+                str << wxT(" bulletsymbol=\"") << (int) (attr.GetBulletText()[0]) << wxT("\"");
+            else
+                str << wxT(" bullettext=\"") << attr.GetBulletText() << wxT("\"");
+                
             str << wxT(" bulletfont=\"") << attr.GetBulletFont() << wxT("\"");
         }
 
         if (attr.HasBulletName())
             str << wxT(" bulletname=\"") << attr.GetBulletName() << wxT("\"");
 
+        if (attr.HasURL())
+            str << wxT(" url=\"") << attr.GetURL() << wxT("\"");
+        
         if (!attr.GetParagraphStyleName().empty())
             str << wxT(" parstyle=\"") << wxString(attr.GetParagraphStyleName()) << wxT("\"");
         
@@ -853,7 +1102,16 @@ bool wxRichTextXMLHandler::GetStyle(wxTextAttrEx& attr, wxXmlNode* node, bool is
 
         value = node->GetPropVal(wxT("bulletsymbol"), wxEmptyString);
         if (!value.empty())
-            attr.SetBulletSymbol(wxChar(wxAtoi(value)));
+        {
+            wxChar ch = wxAtoi(value);
+            wxString s;
+            s << ch;
+            attr.SetBulletText(s);
+        }
+
+        value = node->GetPropVal(wxT("bullettext"), wxEmptyString);
+        if (!value.empty())
+            attr.SetBulletText(value);
 
         value = node->GetPropVal(wxT("bulletfont"), wxEmptyString);
         if (!value.empty())
@@ -863,6 +1121,10 @@ bool wxRichTextXMLHandler::GetStyle(wxTextAttrEx& attr, wxXmlNode* node, bool is
         if (!value.empty())
             attr.SetBulletName(value);
 
+        value = node->GetPropVal(wxT("url"), wxEmptyString);
+        if (!value.empty())
+            attr.SetURL(value);
+
         value = node->GetPropVal(wxT("parstyle"), wxEmptyString);
         if (!value.empty())
             attr.SetParagraphStyleName(value);
-- 
2.50.0

