changeset 784:73850527064e

Merge with main.
author Alexander Schremmer <alex AT alexanderweb DOT de>
date Sun, 04 Jun 2006 23:00:23 +0200
parents d5c59be8b62c (current diff) 8802d6935b6f (diff)
children f3c1ea6ef86e
files MoinMoin/wikixml/xsltutil.py
diffstat 17 files changed, 182 insertions(+), 230 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/__init__.py	Sun Jun 04 22:59:30 2006 +0200
+++ b/MoinMoin/__init__.py	Sun Jun 04 23:00:23 2006 +0200
@@ -1,6 +1,6 @@
 # -*- coding: iso-8859-1 -*-
 """
-MoinMoin Version 1.6.0alpha 8e8130a1f46b+ tip
+MoinMoin Version 1.6.0alpha 43b158d3cf22+ tip
 
 @copyright: 2000-2006 by Jürgen Hermann <jh@web.de>
 @license: GNU GPL, see COPYING for details.
--- a/MoinMoin/config.py	Sun Jun 04 22:59:30 2006 +0200
+++ b/MoinMoin/config.py	Sun Jun 04 23:00:23 2006 +0200
@@ -2,7 +2,7 @@
 """
     MoinMoin - site-wide configuration defaults (NOT per single wiki!)
 
-    @copyright: 2005 by Thomas Waldmann (MoinMoin:ThomasWaldmann)
+    @copyright: 2005-2006 by Thomas Waldmann (MoinMoin:ThomasWaldmann)
     @license: GNU GPL, see COPYING for details.
 """
 import re
@@ -13,8 +13,7 @@
 
 # Charset - we support only 'utf-8'. While older encodings might work,
 # we don't have the resources to test them, and there is no real
-# benefit for the user.
-# IMPORTANT: use only lowercase 'utf-8'!
+# benefit for the user. IMPORTANT: use only lowercase 'utf-8'!
 charset = 'utf-8'
 
 # Invalid characters - invisible characters that should not be in page
@@ -37,48 +36,8 @@
 umask = 0770
 url_schemas = []
 
-smileys = {
-    "X-(":  (15, 15, 0, "angry.png"),
-    ":D":   (15, 15, 0, "biggrin.png"),
-    "<:(":  (15, 15, 0, "frown.png"),
-    ":o":   (15, 15, 0, "redface.png"),
-    ":(":   (15, 15, 0, "sad.png"),
-    ":)":   (15, 15, 0, "smile.png"),
-    "B)":   (15, 15, 0, "smile2.png"),
-    ":))":  (15, 15, 0, "smile3.png"),
-    ";)":   (15, 15, 0, "smile4.png"),
-    "/!\\": (15, 15, 0, "alert.png"),
-    "<!>":  (15, 15, 0, "attention.png"),
-    "(!)":  (15, 15, 0, "idea.png"),
-
-    # copied 2001-11-16 from http://pikie.darktech.org/cgi/pikie.py?EmotIcon
-    ":-?":  (15, 15, 0, "tongue.png"),
-    ":\\":  (15, 15, 0, "ohwell.png"),
-    ">:>":  (15, 15, 0, "devil.png"),
-    "|)":   (15, 15, 0, "tired.png"),
-    
-    # some folks use noses in their emoticons
-    ":-(":  (15, 15, 0, "sad.png"),
-    ":-)":  (15, 15, 0, "smile.png"),
-    "B-)":  (15, 15, 0, "smile2.png"),
-    ":-))": (15, 15, 0, "smile3.png"),
-    ";-)":  (15, 15, 0, "smile4.png"),
-    "|-)":  (15, 15, 0, "tired.png"),
-    
-    # version 1.0
-    "(./)":  (20, 15, 0, "checkmark.png"),
-    "{OK}":  (14, 12, 0, "thumbs-up.png"),
-    "{X}":   (16, 16, 0, "icon-error.png"),
-    "{i}":   (16, 16, 0, "icon-info.png"),
-    "{1}":   (15, 13, 0, "prio1.png"),
-    "{2}":   (15, 13, 0, "prio2.png"),
-    "{3}":   (15, 13, 0, "prio3.png"),
-
-    # version 1.3.4 (stars)
-    # try {*}{*}{o}
-    "{*}":   (15, 15, 0, "star_on.png"),
-    "{o}":   (15, 15, 0, "star_off.png"),
-}
+smileys = (r"X-( :D <:( :o :( :) B) :)) ;) /!\ <!> (!) :-? :\ >:> |) " +
+           r":-( :-) B-) :-)) ;-) |-) (./) {OK} {X} {i} {1} {2} {3} {*} {o}").split()
 
 # unicode: set the char types (upper, lower, digits, spaces)
 from MoinMoin.util.chartypes import _chartypes
--- a/MoinMoin/converter/text_html_text_moin_wiki.py	Sun Jun 04 22:59:30 2006 +0200
+++ b/MoinMoin/converter/text_html_text_moin_wiki.py	Sun Jun 04 23:00:23 2006 +0200
@@ -1182,9 +1182,9 @@
         # Smiley
         elif src and (self.request.cfg.url_prefix in src or '../' in src) and "img/" in src: # XXX this is dirty!
             filename = src.split("/")[-1]
-            for name, data in config.smileys.iteritems():
-                if data[3] == filename:
-                    self.text.extend([self.white_space, name, self.white_space])
+            for markup, data in self.request.theme.icons.iteritems():
+                if data[1] == filename:
+                    self.text.extend([self.white_space, markup, self.white_space])
                     return
                 else:
                     pass #print name, data, filename, alt
@@ -1193,7 +1193,7 @@
         elif src and src.startswith("http") and wikiutil.isPicture(src): # matches http: and https: !
             self.text.extend([self.white_space, src, self.white_space])
         else:
-            raise ConvertError("Strange image src: '%s'" % src)
+            raise ConvertError("Strange image src: '%s' alt == '%r'" % (src, alt))
 
 
 def parse(request, text):
--- a/MoinMoin/formatter/text_docbook.py	Sun Jun 04 22:59:30 2006 +0200
+++ b/MoinMoin/formatter/text_docbook.py	Sun Jun 04 23:00:23 2006 +0200
@@ -451,9 +451,9 @@
         if kw.has_key('src'):
             image.setAttribute('fileref', kw['src'])
         if kw.has_key('width'):
-            image.setAttribute('width', kw['width'])
+            image.setAttribute('width', str(kw['width']))
         if kw.has_key('height'):
-            image.setAttribute('depth', kw['height'])
+            image.setAttribute('depth', str(kw['height']))
         imagewrap.appendChild(image)
 
         title = ''
@@ -472,11 +472,7 @@
         return ""        
  
     def smiley(self, text):
-        w, h, b, img = config.smileys[text.strip()]
-        href = img
-        if not href.startswith('/'):
-            href = self.request.theme.img_url(img)
-        return self.image(src=href, alt=text, width=str(w), height=str(h))
+        return self.request.theme.make_icon(text)
 
     def icon(self, type):
         return '' # self.request.theme.make_icon(type)
--- a/MoinMoin/formatter/text_html.py	Sun Jun 04 22:59:30 2006 +0200
+++ b/MoinMoin/formatter/text_html.py	Sun Jun 04 23:00:23 2006 +0200
@@ -1055,12 +1055,7 @@
     def icon(self, type):
         return self.request.theme.make_icon(type)
 
-    def smiley(self, text):
-        w, h, b, img = config.smileys[text.strip()]
-        href = img
-        if not href.startswith('/'):
-            href = self.request.theme.img_url(img)
-        return self.image(src=href, alt=text, width=str(w), height=str(h))
+    smiley = icon
 
     def image(self, src=None, **kw):
         """Creates an inline image with an <img> element.
--- a/MoinMoin/formatter/text_python.py	Sun Jun 04 22:59:30 2006 +0200
+++ b/MoinMoin/formatter/text_python.py	Sun Jun 04 23:00:23 2006 +0200
@@ -171,6 +171,8 @@
             return self.__insert_code('request.write(%s.icon(%r))' %
                                       (self.__formatter, type))
 
+    smiley = icon
+
     def macro(self, macro_obj, name, args):
         if self.__is_static(macro_obj.get_dependencies(name)):
             return macro_obj.execute(name, args)
--- a/MoinMoin/macro/ShowSmileys.py	Sun Jun 04 22:59:30 2006 +0200
+++ b/MoinMoin/macro/ShowSmileys.py	Sun Jun 04 23:00:23 2006 +0200
@@ -14,7 +14,7 @@
 from MoinMoin.util.dataset import TupleDataset, Column
 from MoinMoin.widget.browser import DataBrowserWidget
 
-COLUMNS = 3
+COLUMNS = 4
 
 Dependencies = ['user'] # different users have different themes and different user prefs (text/gfx)
 
@@ -29,28 +29,20 @@
         data.columns.extend([
             Column('markup', label=_('Markup')),
             Column('image', label=_('Display'), align='center'),
-            Column('filename', label=_('Filename')),
             Column('', label=''),
         ])
     data.columns[-1].hidden = 1
 
     # iterate over smileys, in groups of size COLUMNS
-    smileys = config.smileys.items()
-    smileys.sort()
+    smileys = config.smileys
     for idx in range(0, len(smileys), COLUMNS):
         row = []
         for off in range(COLUMNS):
             if idx+off < len(smileys):
-                markup, smiley = smileys[idx+off]
-                img = fmt.smiley(markup)
-                row.extend([
-                    fmt.code(1) + fmt.text(markup) + fmt.code(0),
-                    img,
-                    fmt.code(1) + smiley[3] + fmt.code(0),
-                    '',
-                ])
+                markup = smileys[idx+off]
+                row.extend([fmt.code(1) + fmt.text(markup) + fmt.code(0), fmt.smiley(markup), '', ])
             else:
-                row.extend(['&nbsp;'] * 4)
+                row.extend(['&nbsp;'] * 3)
         data.addRow(tuple(row))
 
     # display table
--- a/MoinMoin/macro/__init__.py	Sun Jun 04 22:59:30 2006 +0200
+++ b/MoinMoin/macro/__init__.py	Sun Jun 04 23:00:23 2006 +0200
@@ -48,14 +48,6 @@
         cfg.macro_names = lnames # remember it
         return lnames
 
-def _make_index_key(index_letters, additional_html=""):
-    index_letters.sort()
-    links = map(lambda ch:
-                    '<a href="#%s">%s</a>' %
-                    (wikiutil.quoteWikinameURL(ch), ch.replace('~', 'Others')),
-                index_letters)
-    return "<p>%s%s</p>" % (' | '.join(links), additional_html)
-
 
 #############################################################################
 ### Macros - Handlers for [[macroname]] markup
@@ -223,7 +215,21 @@
         html = u'\n'.join(html)
         return self.formatter.rawHTML(html)
 
-    def _macro_WordIndex(self, args):
+    def _make_index(self, args, word_re=u'.+'):
+        """ make an index page (used for TitleIndex and WordIndex macro)
+
+            word_re is a regex used for splitting a pagename into fragments
+            matched by it (used for WordIndex). For TitleIndex, we just match
+            the whole page name, so we only get one fragment that is the same
+            as the pagename.
+
+            TODO: later this can get a macro on its own, more powerful and less
+                  special than WordIndex and TitleIndex.
+                  It should be able to filter for specific mimetypes, maybe match
+                  pagenames by regex (replace PageList?), etc.
+
+                  it should use the formatter asap
+        """
         _ = self._
         allpages = int(self.form.get('allpages', [0])[0]) != 0
         # Get page list readable by current user
@@ -235,8 +241,9 @@
             def filter(name):
                 return not wikiutil.isSystemPage(self.request, name)
             pages = self.request.rootpage.getPageList(filter=filter)
+        
+        word_re = re.compile(word_re, re.UNICODE)
         map = {}
-        word_re = re.compile(u'[%s][%s]+' % (config.chars_upper, config.chars_lower), re.UNICODE)
         for name in pages:
             for word in word_re.findall(name):
                 try:
@@ -245,8 +252,12 @@
                 except KeyError:
                     map[word] = [name]
 
+        # Sort ignoring case
         all_words = map.keys()
-        all_words.sort()
+        tmp = [(word.upper(), word) for word in all_words]
+        tmp.sort()
+        all_words = [item[1] for item in tmp]
+
         index_letters = []
         current_letter = None
         html = []
@@ -254,88 +265,74 @@
             letter = wikiutil.getUnicodeIndexGroup(word)
             if letter != current_letter:
                 #html.append(self.formatter.anchordef()) # XXX no text param available!
-                html.append(u'<a name="%s"><h3>%s</h3></a>' % (
+                html.append(u'<a name="%s"><h2>%s</h2></a>' % (
                     wikiutil.quoteWikinameURL(letter), letter.replace('~', 'Others')))
                 current_letter = letter
             if letter not in index_letters:
                 index_letters.append(letter)
-
-            html.append(self.formatter.strong(1))
-            html.append(word)
-            html.append(self.formatter.strong(0))
+            links = map[word]
+            if len(links) and links[0] != word: # show word fragment as on WordIndex
+                html.append(self.formatter.strong(1))
+                html.append(word)
+                html.append(self.formatter.strong(0))
+            
             html.append(self.formatter.bullet_list(1))
-            links = map[word]
             links.sort()
             last_page = None
             for name in links:
                 if name == last_page:
                     continue
                 html.append(self.formatter.listitem(1))
-                html.append(Page(self.request, name).link_to(self.request))
+                html.append(Page(self.request, name).link_to(self.request, attachment_indicator=1))
                 html.append(self.formatter.listitem(0))
             html.append(self.formatter.bullet_list(0))
         
+        def _make_index_key(index_letters, additional_html=''):
+            index_letters.sort()
+            def letter_link(ch):
+                return '<a href="#%s">%s</a>' % (wikiutil.quoteWikinameURL(ch), ch.replace('~', 'Others'))
+            links = [letter_link(letter) for letter in index_letters]
+            return "<p>%s%s</p>" % (' | '.join(links), additional_html)
+
         qpagename = wikiutil.quoteWikinameURL(self.formatter.page.page_name)
+        allpages_txt = (_('Include system pages'), _('Exclude system pages'))[allpages]
         index = _make_index_key(index_letters, u"""<br>
 <a href="%s?allpages=%d">%s</a>
-""" % (qpagename, not allpages, (_('Include system pages'), _('Exclude system pages'))[allpages]) )
+""" % (qpagename, not allpages, allpages_txt) )
+        # ?action=titleindex and ?action=titleindex&mimetype=text/xml removed
+
         return u'%s%s' % (index, u''.join(html)) 
 
 
     def _macro_TitleIndex(self, args):
-        _ = self._
-        html = []
-        index_letters = []
-        allpages = int(self.form.get('allpages', [0])[0]) != 0
-        # Get page list readable by current user
-        # Filter by isSystemPage if needed
-        if allpages:
-            # TODO: make this fast by caching full page list
-            pages = self.request.rootpage.getPageList()
-        else:
-            def filter(name):
-                return not wikiutil.isSystemPage(self.request, name)
-            pages = self.request.rootpage.getPageList(filter=filter)
+        return self._make_index(args)
 
-        # Sort ignoring case
-        tmp = [(name.upper(), name) for name in pages]
-        tmp.sort()
-        pages = [item[1] for item in tmp]
-                
-        current_letter = None
-        for name in pages:
-            letter = wikiutil.getUnicodeIndexGroup(name)
-            if letter not in index_letters:
-                index_letters.append(letter)
-            if letter != current_letter:
-                html.append(u'<a name="%s"><h3>%s</h3></a>' % (
-                    wikiutil.quoteWikinameURL(letter), letter.replace('~', 'Others')))
-                current_letter = letter
-            else:
-                html.append(u'<br>')
-            html.append(u'%s\n' % Page(self.request, name).link_to(self.request, attachment_indicator=1))
-
-        # add rss link
-        index = ''
-        if 0: # if wikixml.ok: # XXX currently switched off (not implemented)
-            from MoinMoin import wikixml
-            index = (index + self.formatter.url(1, 
-                wikiutil.quoteWikinameURL(self.formatter.page.page_name) + "?action=rss_ti", do_escape=0) +
-                     self.formatter.icon("rss") +
-                     self.formatter.url(0))
-
-        qpagename = wikiutil.quoteWikinameURL(self.formatter.page.page_name)
-        index = index + _make_index_key(index_letters, u"""<br>
-<a href="%s?allpages=%d">%s</a>&nbsp;|
-<a href="%s?action=titleindex">%s</a>&nbsp;|
-<a href="%s?action=titleindex&amp;mimetype=text/xml">%s</a>
-""" % (qpagename, not allpages, (_('Include system pages'), _('Exclude system pages'))[allpages],
-       qpagename, _('Plain title index'),
-       qpagename, _('XML title index')) )
-
-        return u'%s%s' % (index, u''.join(html)) 
+    def _macro_WordIndex(self, args):
+        word_re = u'[%s][%s]+' % (config.chars_upper, config.chars_lower)
+        return self._make_index(args, word_re=word_re)
 
 
+    def _macro_PageList(self, needle):
+        from MoinMoin import search
+        _ = self._
+        literal = 0
+        case = 0
+
+        # If called with empty or no argument, default to regex search for .+, the full page list.
+        if not needle:
+            needle = 'regex:.+'
+
+        # With whitespace argument, return same error message as FullSearch
+        elif needle.isspace():
+            err = _('Please use a more selective search term instead of {{{"%s"}}}') %  needle
+            return '<span class="error">%s</span>' % err
+            
+        # Return a title search for needle, sorted by name.
+        query = search.QueryParser(literal=literal, titlesearch=1, case=case).parse_query(needle)
+        results = search.searchPages(self.request, query)
+        results.sortByPagename()
+        return results.pageList(self.request, self.formatter)
+        
     def _macro_InterWiki(self, args):
         from StringIO import StringIO
 
@@ -381,30 +378,6 @@
         icon = args.lower()
         return self.formatter.icon(icon)
 
-    def _macro_PageList(self, needle):
-        from MoinMoin import search
-        _ = self._
-        literal=0
-        case=0
-
-        # If called with empty or no argument, default to regex search for .+,
-        # the full page list.
-        if not needle:
-            needle = 'regex:.+'
-
-        # With whitespace argument, return same error message as FullSearch
-        elif needle.isspace():
-            err = _('Please use a more selective search term instead of '
-                    '{{{"%s"}}}') %  needle
-            return '<span class="error">%s</span>' % err
-            
-        # Return a title search for needle, sorted by name.
-        query = search.QueryParser(literal=literal, titlesearch=1,
-                                   case=case).parse_query(needle)
-        results = search.searchPages(self.request, query)
-        results.sortByPagename()
-        return results.pageList(self.request, self.formatter)
-        
     def _macro_TemplateList(self, args):
         _ = self._
         try:
--- a/MoinMoin/multiconfig.py	Sun Jun 04 22:59:30 2006 +0200
+++ b/MoinMoin/multiconfig.py	Sun Jun 04 23:00:23 2006 +0200
@@ -424,19 +424,13 @@
         ('name', _('Name'), "text", "36", _("(Use Firstname''''''Lastname)")),
         ('aliasname', _('Alias-Name'), "text", "36", ''),
         ('password', _('Password'), "password", "36", ''),
-        ('password2', _('Password repeat'), "password", "36", _('(Only when changing passwords)')),
+        ('password2', _('Password repeat'), "password", "36", _('(Only for password change or new account)')),
         ('email', _('Email'), "text", "36", ''),
         ('css_url', _('User CSS URL'), "text", "40", _('(Leave it empty for disabling user CSS)')),
         ('edit_rows', _('Editor size'), "text", "3", ''),
-        ##('theme', _('Preferred theme'), [self._theme_select()])
-        ##('', _('Editor Preference'), [self._editor_default_select()])
-        ##('', _('Editor shown on UI'), [self._editor_ui_select()])
-        ##('', _('Time zone'), [self._tz_select()])
-        ##('', _('Date format'), [self._dtfmt_select()])
-        ##('', _('Preferred language'), [self._lang_select()])
     ]
     
-    user_form_defaults = { # key: default
+    user_form_defaults = { # key: default - do NOT remove keys from here!
         'name': '',
         'aliasname': '',
         'password': '',
--- a/MoinMoin/parser/text_moin_wiki.py	Sun Jun 04 22:59:30 2006 +0200
+++ b/MoinMoin/parser/text_moin_wiki.py	Sun Jun 04 23:00:23 2006 +0200
@@ -96,7 +96,7 @@
         'dl_rule': dl_rule,
         'url_rule': url_rule,
         'word_rule': word_rule,
-        'smiley': u'|'.join(map(re.escape, config.smileys.keys()))}
+        'smiley': u'|'.join(map(re.escape, config.smileys))}
 
     # Don't start p before these 
     no_new_p_before = ("heading rule table tableZ tr td "
--- a/MoinMoin/theme/__init__.py	Sun Jun 04 22:59:30 2006 +0200
+++ b/MoinMoin/theme/__init__.py	Sun Jun 04 23:00:23 2006 +0200
@@ -64,6 +64,50 @@
         # search forms
         'searchbutton': ("[?]",                  "moin-search.png", 12, 12),
         'interwiki':  ("[%(wikitag)s]",          "moin-inter.png",  16, 16),
+    
+        # smileys (this is CONTENT, but good looking smileys depend on looking
+        # adapted to the theme background color and theme style in general)
+        #vvv    ==      vvv  this must be the same for GUI editor converter
+        'X-(':        ("X-(",                    'angry.png',       15, 15),
+        ':D':         (":D",                     'biggrin.png',     15, 15),
+        '<:(':        ("<:(",                    'frown.png',       15, 15),
+        ':o':         (":o",                     'redface.png',     15, 15),
+        ':(':         (":(",                     'sad.png',         15, 15),
+        ':)':         (":)",                     'smile.png',       15, 15),
+        'B)':         ("B)",                     'smile2.png',      15, 15),
+        ':))':        (":))",                    'smile3.png',      15, 15),
+        ';)':         (";)",                     'smile4.png',      15, 15),
+        '/!\\':       ("/!\\",                   'alert.png',       15, 15),
+        '<!>':        ("<!>",                    'attention.png',   15, 15),
+        '(!)':        ("(!)",                    'idea.png',        15, 15),
+
+        # copied 2001-11-16 from http://pikie.darktech.org/cgi/pikie.py?EmotIcon
+        ':-?':        (":-?",                    'tongue.png',      15, 15),
+        ':\\':        (":\\",                    'ohwell.png',      15, 15),
+        '>:>':        (">:>",                    'devil.png',       15, 15),
+        '|)':         ("|)",                     'tired.png',       15, 15),
+        
+        # some folks use noses in their emoticons
+        ':-(':        (":-(",                    'sad.png',         15, 15),
+        ':-)':        (":-)",                    'smile.png',       15, 15),
+        'B-)':        ("B-)",                    'smile2.png',      15, 15),
+        ':-))':       (":-))",                   'smile3.png',      15, 15),
+        ';-)':        (";-)",                    'smile4.png',      15, 15),
+        '|-)':        ("|-)",                    'tired.png',       15, 15),
+        
+        # version 1.0
+        '(./)':       ("(./)",                   'checkmark.png',   20, 15),
+        '{OK}':       ("{OK}",                   'thumbs-up.png',   14, 12),
+        '{X}':        ("{X}",                    'icon-error.png',  16, 16),
+        '{i}':        ("{i}",                    'icon-info.png',   16, 16),
+        '{1}':        ("{1}",                    'prio1.png',       15, 13),
+        '{2}':        ("{2}",                    'prio2.png',       15, 13),
+        '{3}':        ("{3}",                    'prio3.png',       15, 13),
+
+        # version 1.3.4 (stars)
+        # try {*}{*}{o}
+        '{*}':        ("{*}",                    'star_on.png',     15, 15),
+        '{o}':        ("{o}",                    'star_off.png',    15, 15),
     }
     del _
 
@@ -406,7 +450,7 @@
         @return: alt (unicode), href (string), width, height (int)
         """
         if icon in self.icons:
-            alt, filename, w, h = self.icons[icon]
+            alt, icon, w, h = self.icons[icon]
         else:
             # Create filenames to icon data mapping on first call, then
             # cache in class for next calls.
@@ -417,19 +461,18 @@
                 self.__class__.iconsByFile = d
 
             # Try to get icon data by file name
-            filename = icon.replace('.gif','.png')
-            if filename in self.iconsByFile:
-                alt, filename, w, h = self.iconsByFile[filename]
+            if icon in self.iconsByFile:
+                alt, icon, w, h = self.iconsByFile[icon]
             else:
-                alt, filename, w, h = '', icon, '', ''
+                alt, icon, w, h = '', icon, '', ''
                 
-        return alt, self.img_url(filename), w, h
+        return alt, self.img_url(icon), w, h
    
     def make_icon(self, icon, vars=None):
         """
         This is the central routine for making <img> tags for icons!
-        All icons stuff except the top left logo, smileys and search
-        field icons are handled here.
+        All icons stuff except the top left logo and search field icons are
+        handled here.
         
         @param icon: icon id (dict key)
         @param vars: ...
--- a/MoinMoin/user.py	Sun Jun 04 22:59:30 2006 +0200
+++ b/MoinMoin/user.py	Sun Jun 04 23:00:23 2006 +0200
@@ -137,8 +137,8 @@
     @return: user name that can be used in acl lines
     """
     name = name.replace('_', ' ') # we treat _ as a blank
-    username_allowedchars = "'@." # ' for names like O'Brian or email addresses.
-                                  # "," and ":" must not be allowed (ACL delimiters).
+    username_allowedchars = "'@.-" # ' for names like O'Brian or email addresses.
+                                   # "," and ":" must not be allowed (ACL delimiters).
     # Strip non alpha numeric characters (except username_allowedchars), keep white space
     name = ''.join([c for c in name if c.isalnum() or c.isspace() or c in username_allowedchars])
 
@@ -223,11 +223,8 @@
         self.auth_attribs = kw.get('auth_attribs', ())
                                        
         # create some vars automatically
-        for tuple in self._cfg.user_form_fields:
-            key = tuple[0]
-            default = self._cfg.user_form_defaults.get(key, '')
-            setattr(self, key, default)
-       
+        self.__dict__.update(self._cfg.user_form_defaults)
+
         if name:
             self.name = name
         elif auth_username: # this is needed for user_autocreate
--- a/MoinMoin/wikixml/marshal.py	Sun Jun 04 22:59:30 2006 +0200
+++ b/MoinMoin/wikixml/marshal.py	Sun Jun 04 23:00:23 2006 +0200
@@ -24,12 +24,12 @@
         Default is to omit all properties starting with an underscore.
 
         TAG_MAP is a translation table for tag names, and is empty by
-        default. It can also be used to surpress certain properties by
+        default. It can also be used to suppress certain properties by
         mapping a tag name to `None`.
     """
 
-    # Convenience: Standard-XML-Deklaration
-    XML_DECL = '<?xml version="1.0" encoding="ISO-8859-1"?>\n'
+    # Convenience: Standard XML declaration
+    XML_DECL = '<?xml version="1.0" encoding="utf-8"?>\n'
 
     # Container Tags
     ROOT_CONTAINER = "data"
@@ -65,18 +65,15 @@
             content = "<none/>"
 
         elif isinstance(data, types.StringType):
-            # String
             content = (data.replace("&", "&amp;") # Must be done first!
                            .replace("<", "&lt;")
                            .replace(">", "&gt;"))
 
         elif isinstance(data, types.DictionaryType):
-            # Dictionary
             for key, value in data.items():
                 add_content(self.__toXML(key, value))
 
         elif isinstance(data, types.ListType) or isinstance(data, types.TupleType):
-            # List or Tuple
             for item in data:
                 add_content(self.__toXML(self.ITEM_CONTAINER, item))
 
@@ -87,7 +84,6 @@
             add_content(self.__toXML(self.ROOT_CONTAINER, data.__dict__))
 
         else:
-            # Everything else
             content = (str(data).replace("&", "&amp;") # Must be done first!
                                 .replace("<", "&lt;")
                                 .replace(">", "&gt;"))
--- a/MoinMoin/wikixml/util.py	Sun Jun 04 22:59:30 2006 +0200
+++ b/MoinMoin/wikixml/util.py	Sun Jun 04 23:00:23 2006 +0200
@@ -70,4 +70,3 @@
         self.endElementNS((self.xmlns['rdf'], 'RDF'), 'rdf:RDF')
         XMLGenerator.endDocument(self)
 
-
--- a/MoinMoin/wikixml/xsltutil.py	Sun Jun 04 22:59:30 2006 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-# -*- coding: iso-8859-1 -*-
-"""
-    MoinMoin - XSLT Utilities
-
-    @copyright: 2001, 2003 by Jürgen Hermann <jh@web.de>
-    @license: GNU GPL, see COPYING for details.
-"""
-
-## currently empty, due to adaption to 4Suite 1.0a1
-## keep this file for later!
-
--- a/docs/CHANGES	Sun Jun 04 22:59:30 2006 +0200
+++ b/docs/CHANGES	Sun Jun 04 23:00:23 2006 +0200
@@ -67,6 +67,7 @@
       specify 'wiki', it will use a cache directory per wiki and if you specify
       'item', it will use a cache directory per item (== per page).
       Creating a CacheEntry without explicit scope is DEPRECATED.
+    * smileys moved from MoinMoin.config to MoinMoin.theme
 
   New Features:
 
@@ -84,6 +85,15 @@
     * fix deletion of empty Interwiki links ([wiki:MoinMaster: mm entry page])
     * fix mod_python attachment upload bug (thanks to Nick Phillips)
     * fix show_version to show it in the same way as SystemInfo
+    * allow "-" in usernames (fixes "Invalid user name" msg)
+    * fixed smiley caching bug (smileys didn't change theme)
+    * fixed backtrace when user removed css_url entry from user_form_fields
+
+  Other changes:
+    * we use (again) the same browser compatibility check as FCKeditor uses
+      internally, too. So if GUI editor invocation is broken due to browser
+      compatibility issues or a wrong browser version check, please file a bug
+      at FCKeditor development or browser development.
 
 Version 1.5.current:
   Developer notes:
--- a/wiki/htdocs/common/js/common.js	Sun Jun 04 22:59:30 2006 +0200
+++ b/wiki/htdocs/common/js/common.js	Sun Jun 04 23:00:23 2006 +0200
@@ -17,26 +17,33 @@
 }
 
 function can_use_gui_editor() {
-    var sAgent = navigator.userAgent.toLowerCase();
- 
-    if (sAgent.indexOf("msie") != -1 && sAgent.indexOf("mac") == -1 &&
-        sAgent.indexOf("opera") == -1 ) {
-        // Internet Explorer
-        var sBrowserVersion = navigator.appVersion.match(/MSIE (.\..)/)[1];
-        return ( sBrowserVersion >= 5.5 );
-    } else if (navigator.product == "Gecko" && 
-               navigator.productSub >= 20030210) {
-        // Gecko
-        return true;
+    var sAgent = navigator.userAgent.toLowerCase() ;
+
+    // Internet Explorer
+    if ( sAgent.indexOf("msie") != -1 && sAgent.indexOf("mac") == -1 && sAgent.indexOf("opera") == -1 )
+    {   
+        var sBrowserVersion = navigator.appVersion.match(/MSIE (.\..)/)[1] ;
+        return ( sBrowserVersion >= 5.5 ) ;
     }
-    // else if (sAgent.indexOf("safari") != -1 ) {
-    //    // Safari - build must be at least 312 (1.3)
-    //    return (sAgent.match( /safari\/(\d+)/ )[1] >= 312 );
-    // } 
-    else {
-        // Unknown browser, assume gui editor is not compatible
-        return false;
+    
+    // Gecko
+    if ( navigator.product == "Gecko" && navigator.productSub >= 20030210 )
+        return true ;
+
+    // Opera
+    if ( this.EnableOpera )
+    {   
+        var aMatch = sAgent.match( /^opera\/(\d+\.\d+)/ ) ;
+        if ( aMatch && aMatch[1] >= 9.0 )
+            return true ;
     }
+    
+    // Safari
+    if ( this.EnableSafari && sAgent.indexOf( 'safari' ) != -1 )
+        return ( sAgent.match( /safari\/(\d+)/ )[1] >= 312 ) ;  // Build must be at least 312 (1.3)
+
+    return false ;
+
 }