diff --git a/product/CMFCategory/Category.py b/product/CMFCategory/Category.py
index f616419196de3577f311a7296dd13ae9e8cc0d42..cb0d52ada5631ee799859ddc2d513aeb78216a85 100755
--- a/product/CMFCategory/Category.py
+++ b/product/CMFCategory/Category.py
@@ -373,30 +373,22 @@ class Category(Folder):
             spec=spec, filter=filter, portal_type=portal_type,strict = strict)
 
     security.declareProtected( Permissions.AccessContentsInformation, 'getCategoryMemberItemList' )
-    def getCategoryMemberItemList(self, base_category = None,
-                    spec = (), filter=None, portal_type=(), strict = 0, display_id = None):
+    def getCategoryMemberItemList(self, **kw):
       """
       Returns a list of objects or brains
       """
-
-      return self.portal_categories.getCategoryMemberItemList(self,
-               base_category = base_category, spec=spec,
-               filter=filter, portal_type=portal_type, strict=strict, display_id=display_id)
-
+      #LOG('Category#getCategoryMemberItemList', 0, repr(kw))
+      return self.portal_categories.getCategoryMemberItemList(self, **kw)
 
     security.declareProtected( Permissions.AccessContentsInformation,
                                                                'getCategoryMemberTitleItemList' )
-    def getCategoryMemberTitleItemList(self, base_category = None,
-                          spec = (), filter=None, portal_type=(), strict = 0):
+    def getCategoryMemberTitleItemList(self, **kw):
       """
       Returns a list of objects or brains
       """
-
-      return self.portal_categories.getCategoryMemberItemList(self,
-           base_category = base_category,
-           spec=spec, filter=filter, portal_type=portal_type,strict = strict, display_id = 'getTitle')
-
-
+      kw['display_id'] = 'getTitle'
+      kw['display_method'] = None
+      return self.portal_categories.getCategoryMemberItemList(self, **kw)
 
 manage_addBaseCategoryForm=DTMLFile('dtml/base_category_add', globals())
 
diff --git a/product/CMFCategory/CategoryTool.py b/product/CMFCategory/CategoryTool.py
index e81a9a19c3a165fe79c980db48c50a4cf02efa93..dee46d432cfe5f26ce922de52a4501d62133c024 100755
--- a/product/CMFCategory/CategoryTool.py
+++ b/product/CMFCategory/CategoryTool.py
@@ -39,6 +39,7 @@ from Products.ERP5Type import Permissions
 from Products.ERP5Type.Base import Base
 from Products.CMFCategory import _dtmldir
 from Products.CMFCore.PortalFolder import ContentFilter
+from Products.CMFCategory.Renderer import Renderer
 
 import string, re
 
@@ -332,7 +333,10 @@ class CategoryTool( UniqueObject, Folder, Base ):
       return result
 
     security.declareProtected(Permissions.AccessContentsInformation, 'getPathList')
-    getPathList = getCategoryChildRelativeUrlList
+    getPathList = getCategoryChildRelativeUrlList # Exists for backward compatibility
+
+    security.declareProtected(Permissions.AccessContentsInformation, 'getCategoryChildList')
+    getCategoryChildList = getCategoryChildRelativeUrlList # This is more consistent
 
     security.declareProtected(Permissions.AccessContentsInformation,
                                                       'getCategoryChildTitleItemList')
@@ -1010,7 +1014,6 @@ class CategoryTool( UniqueObject, Folder, Base ):
         sql_expr = string.join(sql_expr, ' OR ')
       return sql_expr
 
-
     security.declareProtected( Permissions.AccessContentsInformation, 'getCategoryMemberValueList' )
     def getCategoryMemberValueList(self, context, base_category = None,
                                          spec = (), filter=None, portal_type=(), strict = 0):
@@ -1020,48 +1023,22 @@ class CategoryTool( UniqueObject, Folder, Base ):
       """
       cat_sql = context.asSqlExpression()
 
-
       if spec is ():
         catalog_search = self.portal_catalog(query = cat_sql)
       else:
         catalog_search = self.portal_catalog(portal_type = portal_type, query = cat_sql)
 
-
       return catalog_search
 
-
     security.declareProtected( Permissions.AccessContentsInformation, 'getCategoryMemberItemList' )
-    def getCategoryMemberItemList(self, context, base_category = None,
-         spec = (), filter=None, portal_type=(), strict = 0, display_id = None, sort_id=None):
+    def getCategoryMemberItemList(self, context, strict = 0, **kw):
       """
-      This returns with "display_id" method a list of items belonging to a category
+      This returns a list of items belonging to a category
 
       """
-      result = []
-
-      if base_category is None:
-        base = ''
-      else:
-        base = base_category + '/'
-
       catalog_search = self.getCategoryMemberValueList(context)
-
-      for b in catalog_search:
-        if display_id is None:
-          v = base + b.relative_url
-          result += [(v,v)]
-        else:
-          try:
-            o = b.getObject()
-            v = getattr(o, display_id)()
-            result += [(v,base + b.relative_url)]
-          except:
-            LOG('WARNING: CategoriesTool',0, 'Unable to call %s on %s' % (display_id, b))
-
-      if sort_id is not None:
-        result.sort()
-
-      return result
+      #LOG('getCategoryMemberItemList', 0, repr(kw))
+      return Renderer(**kw).render(context, catalog_search)
 
     security.declareProtected( Permissions.AccessContentsInformation,
                                                                 'getCategoryMemberTitleItemList' )
diff --git a/product/CMFCategory/Filter.py b/product/CMFCategory/Filter.py
index 2942a656be06b86dbfbbabaa41fad05e780208ab..d358a6227f0af6c4a7813c1912fa758bc36d32f6 100755
--- a/product/CMFCategory/Filter.py
+++ b/product/CMFCategory/Filter.py
@@ -29,26 +29,38 @@
 
 from Acquisition import Implicit
 
+from zLOG import LOG
+
 class Filter(Implicit):
 
   def __init__(self, spec=None, filter={}, portal_type=None):
     """
-      A fil
+      Initialize attributes. spec and portal_type can be lists, tuples or strings.
     """
     if type(filter) is type({}):
-      self.filter = filter
+      self.filter_dict = filter
     else:
-      self.filter = {}
+      self.filter_dict = {}
     if portal_type is not None:
-      self.filter['portal_type'] = portal_type
+      if type(portal_type) == type(''):
+        portal_type = [portal_type]
+      # XXX An empty list or tuple is the same as None here.
+      if len(portal_type) > 0:
+        self.filter_dict['portal_type'] = portal_type
     if spec is not None:
-      self.filter['meta_type'] = spec
+      if type(spec) == type(''):
+        spec = [spec]
+      # XXX An empty list or tuple is the same as None here.
+      if len(spec) > 0:
+        self.filter_dict['meta_type'] = spec
 
   def test(self, context):
     """
       Test filter on a context
     """
-    for k, v in self.filter.items():
+    #LOG('test', 0, repr(context))
+    for k, v in self.filter_dict.items():
+      #LOG('Filter', 0, "%s, %s" % (repr(k), repr(v)))
       if type(v) in (type([]), type(())):
         if context.getProperty(k) not in v:
           return 0
@@ -61,7 +73,7 @@ class Filter(Implicit):
     """
       Returns a dictionnary of parameters which can be passed to SQL Catalog
     """
-    return self.filter
+    return self.filter_dict
 
   def asSql(self):
     """
@@ -70,4 +82,5 @@ class Filter(Implicit):
     # To be done
 
   def filter(self, value_list):
+    #LOG('filter', 0, repr(value_list))
     return filter(lambda v: self.test(v), value_list)
diff --git a/product/CMFCategory/Renderer.py b/product/CMFCategory/Renderer.py
index f04be655f2d95a93b17afde5181ecaecd7ca206d..e0f18445f6373625b30a7150fc39b8e0df0d65ed 100755
--- a/product/CMFCategory/Renderer.py
+++ b/product/CMFCategory/Renderer.py
@@ -27,18 +27,23 @@
 ##############################################################################
 
 
-from Filter import Filter
+from Products.CMFCategory.Filter import Filter
+
+from zLOG import LOG
 
 class Renderer(Filter):
   """
     Produces Item list out of category list
+
+    FIXME: translation
   """
 
-  def __init__(self, spec=None, filter={}, portal_type=None,
+  def __init__(self, spec = None, filter = {}, portal_type = None,
                      display_id = None, sort_id = None,
                      display_method = None, sort_method = None,
                      is_right_display = 0, translate_display = 0, translatation_domain = None,
-                     base_category = None, base=1, display_none_category=0):
+                     base_category = None, base = 1,
+                     display_none_category = 0, current_category = None):
     """
     - *display_id*: the id of attribute to "call" to calculate the value to display
                       (getProperty(display_id) -> getDisplayId)
@@ -54,7 +59,7 @@ class Renderer(Filter):
                     foo2      5
           display order will be (foo1, foo, foo2)
 
-    - *sort_method*: a callable method which provides a sort function (à la cmp)
+    - *sort_method*: a callable method which provides a sort function (?la cmp)
 
     - *is_right_display*: use the right value in the couple as the display value.
 
@@ -92,6 +97,7 @@ class Renderer(Filter):
 
 
     """
+    #LOG('Renderer', 0, 'spec = %s, filter = %s, portal_type = %s, display_id = %s, sort_id = %s, display_method = %s, sort_method = %s, is_right_display = %s, translate_display = %s, translatation_domain = %s, base_category = %s, base = %s, display_none_category = %s, current_category = %s' % (repr(spec), repr(filter), repr(portal_type), repr(display_id), repr(sort_id), repr(display_method), repr(sort_method), repr(is_right_display), repr(translate_display), repr(translatation_domain), repr(base_category), repr(base), repr(display_none_category), repr(current_category)))
     Filter.__init__(self, spec=spec, filter=filter, portal_type=portal_type)
     self.display_id = display_id
     self.sort_id = sort_id
@@ -103,31 +109,105 @@ class Renderer(Filter):
     self.base_category = base_category
     self.base = base
     self.display_none_category = display_none_category
+    self.current_category = current_category
 
-  def render(self, category_tool, value_list, current_category):
+  def getObjectList(self, value_list):
+    new_value_list = []
+    for value in value_list:
+      obj = value.getObject()
+      if obj is not None:
+        new_value_list.append(obj)
+    return new_value_list
+
+  def render(self, category_tool, value_list):
     """
       Returns rendered items
     """
+    #LOG('render', 0, repr(self.filter))
+    #LOG('render', 10, repr(value_list))
+    value_list = self.getObjectList(value_list)
     value_list = self.filter(value_list)
+    LOG('render', 10, repr(value_list))
     if self.sort_method is not None:
       value_list.sort(self.sort_method)
     elif self.sort_id is not None:
       value_list.sort(lambda x,y: cmp(x.getProperty(self.sort_id), y.getProperty(self.sort_id)))
 
-    """
-      for b in catalog_search:
-        if display_id is None:
-          v = base + b.relative_url
-          result += [(v,v)]
+    # If base=1 but base_category is None, it is necessary to guess the base category
+    # by heuristic.
+    if self.base and self.base_category is None:
+      base_category_count_map = {}
+      for value in value_list:
+        if not getattr(value, 'isCategory', 0):
+          continue
+        b = value.getBaseCategoryId()
+        if b in base_category_count_map:
+          base_category_count_map[b] += 1
         else:
-          try:
-            o = b.getObject()
-            v = getattr(o, display_id)()
-            result += [(v,base + b.relative_url)]
-          except:
-            LOG('WARNING: CategoriesTool',0, 'Unable to call %s on %s' % (display_id, b))
-
-      if sort_id is not None:
-        result.sort()
-
-    """
\ No newline at end of file
+          base_category_count_map[b] = 1
+      guessed_base_category = None
+      max_count = 0
+      for k,v in base_category_count_map.items():
+        if v > max_count:
+          guessed_base_category = k
+          max_count = v
+
+    # Initialize the list of items.
+    item_list = []
+    if self.current_category:
+      if self.is_right_display:
+        item = [None, self.current_category]
+      else:
+        item = [self.current_category, None]
+      item_list.append(item)
+    if self.display_none_category:
+      if self.is_right_display:
+        item = [None, '']
+      else:
+        item = ['', None]
+      item_list.append(item)
+
+    for value in value_list:
+      #LOG('Renderer', 10, repr(value))
+      # Get the label.
+      if self.display_method is not None:
+        label = self.display_method(value)
+      elif self.display_id is not None:
+        try:
+          label = value.getProperty(self.display_id)
+        except:
+          LOG('WARNING: Renderer', 0,
+              'Unable to call %s on %s' % (self.display_id, value.getRelativeUrl()))
+          label = None
+      else:
+        label = None
+      # Get the url.
+      url = value.getRelativeUrl()
+      if self.base:
+        if self.base_category:
+          # Prepend the specified base category to the url.
+          url = self.base_category + '/' + url
+        else:
+          # If the base category of this category does not match the guessed base category,
+          # merely ignore this category.
+          if value.getBaseCategoryId() != guessed_base_category:
+            continue
+      else:
+        if self.base_category:
+          # Nothing to do.
+          pass
+        else:
+          # Get rid of the base category of this url, only if this is a category.
+          if getattr(value, 'isCategory', 0):
+            b = value.getBaseCategoryId()
+            url = url[len(b)+1:]
+      # Add the pair of a label and an url.
+      if label is None:
+        label = url
+      if self.is_right_display:
+        item = [url, label]
+      else:
+        item = [label, url]
+      item_list.append(item)
+
+    return item_list