LCOV - code coverage report
Current view: directory - content/xul/templates/src - nsXULSortService.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 244 0 0.0 %
Date: 2012-06-02 Functions: 14 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Scott Putterman          <putterman@netscape.com>
      24                 :  *   Pierre Phaneuf           <pp@ludusdesign.com>
      25                 :  *   Chase Tingley            <tingley@sundell.net>
      26                 :  *   Neil Deakin              <enndeakin@sympatico.ca>
      27                 :  *
      28                 :  * Alternatively, the contents of this file may be used under the terms of
      29                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      30                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      32                 :  * of those above. If you wish to allow use of your version of this file only
      33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      34                 :  * use your version of this file under the terms of the MPL, indicate your
      35                 :  * decision by deleting the provisions above and replace them with the notice
      36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      37                 :  * the provisions above, a recipient may use your version of this file under
      38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      39                 :  *
      40                 :  * ***** END LICENSE BLOCK *****
      41                 :  *
      42                 :  * This Original Code has been modified by IBM Corporation.
      43                 :  * Modifications made by IBM described herein are
      44                 :  * Copyright (c) International Business Machines
      45                 :  * Corporation, 2000
      46                 :  *
      47                 :  * Modifications to Mozilla code or documentation
      48                 :  * identified per MPL Section 3.3
      49                 :  *
      50                 :  * Date         Modified by     Description of modification
      51                 :  * 03/27/2000   IBM Corp.       Added PR_CALLBACK for Optlink
      52                 :  *                               use in OS2
      53                 :  */
      54                 : 
      55                 : /*
      56                 :   This file provides the implementation for the sort service manager.
      57                 :  */
      58                 : 
      59                 : #include "nsCOMPtr.h"
      60                 : #include "nsIContent.h"
      61                 : #include "nsIDOMElement.h"
      62                 : #include "nsIDOMNode.h"
      63                 : #include "nsIDocument.h"
      64                 : #include "nsINameSpaceManager.h"
      65                 : #include "nsIServiceManager.h"
      66                 : #include "nsGkAtoms.h"
      67                 : #include "nsXULContentUtils.h"
      68                 : #include "nsString.h"
      69                 : #include "nsQuickSort.h"
      70                 : #include "nsWhitespaceTokenizer.h"
      71                 : #include "nsXULSortService.h"
      72                 : #include "nsIDOMXULElement.h"
      73                 : #include "nsIXULTemplateBuilder.h"
      74                 : #include "nsTemplateMatch.h"
      75                 : #include "nsICollation.h"
      76                 : #include "nsUnicharUtils.h"
      77                 : 
      78               0 : NS_IMPL_ISUPPORTS1(XULSortServiceImpl, nsIXULSortService)
      79                 : 
      80                 : void
      81               0 : XULSortServiceImpl::SetSortHints(nsIContent *aNode, nsSortState* aSortState)
      82                 : {
      83                 :   // set sort and sortDirection attributes when is sort is done
      84                 :   aNode->SetAttr(kNameSpaceID_None, nsGkAtoms::sort,
      85               0 :                  aSortState->sort, true);
      86                 : 
      87               0 :   nsAutoString direction;
      88               0 :   if (aSortState->direction == nsSortState_descending)
      89               0 :     direction.AssignLiteral("descending");
      90               0 :   else if (aSortState->direction == nsSortState_ascending)
      91               0 :     direction.AssignLiteral("ascending");
      92                 :   aNode->SetAttr(kNameSpaceID_None, nsGkAtoms::sortDirection,
      93               0 :                  direction, true);
      94                 : 
      95                 :   // for trees, also set the sort info on the currently sorted column
      96               0 :   if (aNode->NodeInfo()->Equals(nsGkAtoms::tree, kNameSpaceID_XUL)) {
      97               0 :     if (aSortState->sortKeys.Count() >= 1) {
      98               0 :       nsAutoString sortkey;
      99               0 :       aSortState->sortKeys[0]->ToString(sortkey);
     100               0 :       SetSortColumnHints(aNode, sortkey, direction);
     101                 :     }
     102                 :   }
     103               0 : }
     104                 : 
     105                 : void
     106               0 : XULSortServiceImpl::SetSortColumnHints(nsIContent *content,
     107                 :                                        const nsAString &sortResource,
     108                 :                                        const nsAString &sortDirection)
     109                 : {
     110                 :   // set sort info on current column. This ensures that the
     111                 :   // column header sort indicator is updated properly.
     112               0 :   for (nsIContent* child = content->GetFirstChild();
     113                 :        child;
     114               0 :        child = child->GetNextSibling()) {
     115               0 :     if (child->IsXUL()) {
     116               0 :       nsIAtom *tag = child->Tag();
     117                 : 
     118               0 :       if (tag == nsGkAtoms::treecols) {
     119               0 :         SetSortColumnHints(child, sortResource, sortDirection);
     120               0 :       } else if (tag == nsGkAtoms::treecol) {
     121               0 :         nsAutoString value;
     122               0 :         child->GetAttr(kNameSpaceID_None, nsGkAtoms::sort, value);
     123                 :         // also check the resource attribute for older code
     124               0 :         if (value.IsEmpty())
     125               0 :           child->GetAttr(kNameSpaceID_None, nsGkAtoms::resource, value);
     126               0 :         if (value == sortResource) {
     127                 :           child->SetAttr(kNameSpaceID_None, nsGkAtoms::sortActive,
     128               0 :                          NS_LITERAL_STRING("true"), true);
     129                 :           child->SetAttr(kNameSpaceID_None, nsGkAtoms::sortDirection,
     130               0 :                          sortDirection, true);
     131                 :           // Note: don't break out of loop; want to set/unset
     132                 :           // attribs on ALL sort columns
     133               0 :         } else if (!value.IsEmpty()) {
     134                 :           child->UnsetAttr(kNameSpaceID_None, nsGkAtoms::sortActive,
     135               0 :                            true);
     136                 :           child->UnsetAttr(kNameSpaceID_None, nsGkAtoms::sortDirection,
     137               0 :                            true);
     138                 :         }
     139                 :       }
     140                 :     }
     141                 :   }
     142               0 : }
     143                 : 
     144                 : nsresult
     145               0 : XULSortServiceImpl::GetItemsToSort(nsIContent *aContainer,
     146                 :                                    nsSortState* aSortState,
     147                 :                                    nsTArray<contentSortInfo>& aSortItems)
     148                 : {
     149                 :   // if there is a template attached to the sort node, use the builder to get
     150                 :   // the items to be sorted
     151               0 :   nsCOMPtr<nsIDOMXULElement> element = do_QueryInterface(aContainer);
     152               0 :   if (element) {
     153               0 :     nsCOMPtr<nsIXULTemplateBuilder> builder;
     154               0 :     element->GetBuilder(getter_AddRefs(builder));
     155                 : 
     156               0 :     if (builder) {
     157               0 :       nsresult rv = builder->GetQueryProcessor(getter_AddRefs(aSortState->processor));
     158               0 :       if (NS_FAILED(rv) || !aSortState->processor)
     159               0 :         return rv;
     160                 : 
     161               0 :       return GetTemplateItemsToSort(aContainer, builder, aSortState, aSortItems);
     162                 :     }
     163                 :   }
     164                 :   
     165                 :   // if there is no template builder, just get the children. For trees,
     166                 :   // get the treechildren element as use that as the parent
     167               0 :   nsCOMPtr<nsIContent> treechildren;
     168               0 :   if (aContainer->NodeInfo()->Equals(nsGkAtoms::tree, kNameSpaceID_XUL)) {
     169                 :     nsXULContentUtils::FindChildByTag(aContainer,
     170                 :                                       kNameSpaceID_XUL,
     171                 :                                       nsGkAtoms::treechildren,
     172               0 :                                       getter_AddRefs(treechildren));
     173               0 :     if (!treechildren)
     174               0 :       return NS_OK;
     175                 :   
     176               0 :     aContainer = treechildren;
     177                 :   }
     178                 :   
     179               0 :   for (nsIContent* child = aContainer->GetFirstChild();
     180                 :        child;
     181               0 :        child = child->GetNextSibling()) {
     182               0 :     contentSortInfo* cinfo = aSortItems.AppendElement();
     183               0 :     if (!cinfo)
     184               0 :       return NS_ERROR_OUT_OF_MEMORY;
     185                 : 
     186               0 :     cinfo->content = child;
     187                 :   }
     188                 : 
     189               0 :   return NS_OK;
     190                 : }
     191                 : 
     192                 : 
     193                 : nsresult
     194               0 : XULSortServiceImpl::GetTemplateItemsToSort(nsIContent* aContainer,
     195                 :                                            nsIXULTemplateBuilder* aBuilder,
     196                 :                                            nsSortState* aSortState,
     197                 :                                            nsTArray<contentSortInfo>& aSortItems)
     198                 : {
     199               0 :   for (nsIContent* child = aContainer->GetFirstChild();
     200                 :        child;
     201               0 :        child = child->GetNextSibling()) {
     202                 :   
     203               0 :     nsCOMPtr<nsIDOMElement> childnode = do_QueryInterface(child);
     204                 : 
     205               0 :     nsCOMPtr<nsIXULTemplateResult> result;
     206               0 :     nsresult rv = aBuilder->GetResultForContent(childnode, getter_AddRefs(result));
     207               0 :     NS_ENSURE_SUCCESS(rv, rv);
     208                 : 
     209               0 :     if (result) {
     210               0 :       contentSortInfo* cinfo = aSortItems.AppendElement();
     211               0 :       if (!cinfo)
     212               0 :         return NS_ERROR_OUT_OF_MEMORY;
     213                 : 
     214               0 :       cinfo->content = child;
     215               0 :       cinfo->result = result;
     216                 :     }
     217               0 :     else if (aContainer->Tag() != nsGkAtoms::_template) {
     218               0 :       rv = GetTemplateItemsToSort(child, aBuilder, aSortState, aSortItems);
     219               0 :       NS_ENSURE_SUCCESS(rv, rv);
     220                 :     }
     221                 :   }
     222                 : 
     223               0 :   return NS_OK;
     224                 : }
     225                 : 
     226                 : int
     227               0 : testSortCallback(const void *data1, const void *data2, void *privateData)
     228                 : {
     229                 :   /// Note: testSortCallback is a small C callback stub for NS_QuickSort
     230               0 :   contentSortInfo *left = (contentSortInfo *)data1;
     231               0 :   contentSortInfo *right = (contentSortInfo *)data2;
     232               0 :   nsSortState* sortState = (nsSortState *)privateData;
     233                 :       
     234               0 :   PRInt32 sortOrder = 0;
     235                 : 
     236               0 :   if (sortState->direction == nsSortState_natural && sortState->processor) {
     237                 :     // sort in natural order
     238               0 :     sortState->processor->CompareResults(left->result, right->result,
     239               0 :                                          nsnull, sortState->sortHints, &sortOrder);
     240                 :   }
     241                 :   else {
     242               0 :     PRInt32 length = sortState->sortKeys.Count();
     243               0 :     for (PRInt32 t = 0; t < length; t++) {
     244                 :       // for templates, use the query processor to do sorting
     245               0 :       if (sortState->processor) {
     246               0 :         sortState->processor->CompareResults(left->result, right->result,
     247                 :                                              sortState->sortKeys[t],
     248               0 :                                              sortState->sortHints, &sortOrder);
     249               0 :         if (sortOrder)
     250               0 :           break;
     251                 :       }
     252                 :       else {
     253                 :         // no template, so just compare attributes. Ignore namespaces for now.
     254               0 :         nsAutoString leftstr, rightstr;
     255               0 :         left->content->GetAttr(kNameSpaceID_None, sortState->sortKeys[t], leftstr);
     256               0 :         right->content->GetAttr(kNameSpaceID_None, sortState->sortKeys[t], rightstr);
     257                 : 
     258               0 :         sortOrder = XULSortServiceImpl::CompareValues(leftstr, rightstr, sortState->sortHints);
     259                 :       }
     260                 :     }
     261                 :   }
     262                 : 
     263               0 :   if (sortState->direction == nsSortState_descending)
     264               0 :     sortOrder = -sortOrder;
     265                 : 
     266               0 :   return sortOrder;
     267                 : }
     268                 : 
     269                 : nsresult
     270               0 : XULSortServiceImpl::SortContainer(nsIContent *aContainer, nsSortState* aSortState)
     271                 : {
     272               0 :   nsTArray<contentSortInfo> items;
     273               0 :   nsresult rv = GetItemsToSort(aContainer, aSortState, items);
     274               0 :   NS_ENSURE_SUCCESS(rv, rv);
     275                 : 
     276               0 :   PRUint32 numResults = items.Length();
     277               0 :   if (!numResults)
     278               0 :     return NS_OK;
     279                 : 
     280                 :   PRUint32 i;
     281                 : 
     282                 :   // inbetweenSeparatorSort sorts the items between separators independently
     283               0 :   if (aSortState->inbetweenSeparatorSort) {
     284               0 :     PRUint32 startIndex = 0;
     285               0 :     for (i = 0; i < numResults; i++) {
     286               0 :       if (i > startIndex + 1) {
     287               0 :         nsAutoString type;
     288               0 :         items[i].result->GetType(type);
     289               0 :         if (type.EqualsLiteral("separator")) {
     290               0 :           if (aSortState->invertSort)
     291               0 :             InvertSortInfo(items, startIndex, i - startIndex);
     292                 :           else
     293               0 :             NS_QuickSort((void *)(items.Elements() + startIndex), i - startIndex,
     294               0 :                          sizeof(contentSortInfo), testSortCallback, (void*)aSortState);
     295                 : 
     296               0 :           startIndex = i + 1;
     297                 :         }
     298                 :       }
     299                 :     }
     300                 : 
     301               0 :     if (i > startIndex + 1) {
     302               0 :       if (aSortState->invertSort)
     303               0 :         InvertSortInfo(items, startIndex, i - startIndex);
     304                 :       else
     305               0 :         NS_QuickSort((void *)(items.Elements() + startIndex), i - startIndex,
     306               0 :                      sizeof(contentSortInfo), testSortCallback, (void*)aSortState);
     307                 :     }
     308                 :   } else {
     309                 :     // if the items are just being inverted, that is, just switching between
     310                 :     // ascending and descending, just reverse the list.
     311               0 :     if (aSortState->invertSort)
     312               0 :       InvertSortInfo(items, 0, numResults);
     313                 :     else
     314               0 :       NS_QuickSort((void *)items.Elements(), numResults,
     315               0 :                    sizeof(contentSortInfo), testSortCallback, (void*)aSortState);
     316                 :   }
     317                 : 
     318                 :   // first remove the items from the old positions
     319               0 :   for (i = 0; i < numResults; i++) {
     320               0 :     nsIContent* child = items[i].content;
     321               0 :     nsIContent* parent = child->GetParent();
     322                 : 
     323               0 :     if (parent) {
     324                 :       // remember the parent so that it can be reinserted back
     325                 :       // into the same parent. This is necessary as multiple rules
     326                 :       // may generate results which get placed in different locations.
     327               0 :       items[i].parent = parent;
     328               0 :       PRInt32 index = parent->IndexOf(child);
     329               0 :       parent->RemoveChildAt(index, true);
     330                 :     }
     331                 :   }
     332                 : 
     333                 :   // now add the items back in sorted order
     334               0 :   for (i = 0; i < numResults; i++)
     335                 :   {
     336               0 :     nsIContent* child = items[i].content;
     337               0 :     nsIContent* parent = items[i].parent;
     338               0 :     if (parent) {
     339               0 :       parent->AppendChildTo(child, true);
     340                 : 
     341                 :       // if it's a container in a tree or menu, find its children,
     342                 :       // and sort those also
     343               0 :       if (!child->AttrValueIs(kNameSpaceID_None, nsGkAtoms::container,
     344               0 :                               nsGkAtoms::_true, eCaseMatters))
     345               0 :         continue;
     346                 :         
     347               0 :       for (nsIContent* grandchild = child->GetFirstChild();
     348                 :            grandchild;
     349               0 :            grandchild = grandchild->GetNextSibling()) {
     350               0 :         nsINodeInfo *ni = grandchild->NodeInfo();
     351               0 :         nsIAtom *localName = ni->NameAtom();
     352               0 :         if (ni->NamespaceID() == kNameSpaceID_XUL &&
     353                 :             (localName == nsGkAtoms::treechildren ||
     354                 :              localName == nsGkAtoms::menupopup)) {
     355               0 :           SortContainer(grandchild, aSortState);
     356                 :         }
     357                 :       }
     358                 :     }
     359                 :   }
     360                 :   
     361               0 :   return NS_OK;
     362                 : }
     363                 : 
     364                 : nsresult
     365               0 : XULSortServiceImpl::InvertSortInfo(nsTArray<contentSortInfo>& aData,
     366                 :                                    PRInt32 aStart, PRInt32 aNumItems)
     367                 : {
     368               0 :   if (aNumItems > 1) {
     369                 :     // reverse the items in the array starting from aStart
     370               0 :     PRInt32 upPoint = (aNumItems + 1) / 2 + aStart;
     371               0 :     PRInt32 downPoint = (aNumItems - 2) / 2 + aStart;
     372               0 :     PRInt32 half = aNumItems / 2;
     373               0 :     while (half-- > 0) {
     374               0 :       aData[downPoint--].swap(aData[upPoint++]);
     375                 :     }
     376                 :   }
     377               0 :   return NS_OK;
     378                 : }
     379                 : 
     380                 : nsresult
     381               0 : XULSortServiceImpl::InitializeSortState(nsIContent* aRootElement,
     382                 :                                         nsIContent* aContainer,
     383                 :                                         const nsAString& aSortKey,
     384                 :                                         const nsAString& aSortHints,
     385                 :                                         nsSortState* aSortState)
     386                 : {
     387                 :   // used as an optimization for the content builder
     388               0 :   if (aContainer != aSortState->lastContainer.get()) {
     389               0 :     aSortState->lastContainer = aContainer;
     390               0 :     aSortState->lastWasFirst = false;
     391               0 :     aSortState->lastWasLast = false;
     392                 :   }
     393                 : 
     394                 :   // The attributes allowed are either:
     395                 :   //    sort="key1 key2 ..."
     396                 :   // or sortResource="key1" sortResource2="key2"
     397                 :   // The latter is for backwards compatibility, and is equivalent to concatenating
     398                 :   // both values in the sort attribute
     399               0 :   nsAutoString sort(aSortKey);
     400               0 :   aSortState->sortKeys.Clear();
     401               0 :   if (sort.IsEmpty()) {
     402               0 :     nsAutoString sortResource, sortResource2;
     403               0 :     aRootElement->GetAttr(kNameSpaceID_None, nsGkAtoms::sortResource, sortResource);
     404               0 :     if (!sortResource.IsEmpty()) {
     405               0 :       nsCOMPtr<nsIAtom> sortkeyatom = do_GetAtom(sortResource);
     406               0 :       aSortState->sortKeys.AppendObject(sortkeyatom);
     407               0 :       sort.Append(sortResource);
     408                 : 
     409               0 :       aRootElement->GetAttr(kNameSpaceID_None, nsGkAtoms::sortResource2, sortResource2);
     410               0 :       if (!sortResource2.IsEmpty()) {
     411               0 :         nsCOMPtr<nsIAtom> sortkeyatom2 = do_GetAtom(sortResource2);
     412               0 :         aSortState->sortKeys.AppendObject(sortkeyatom2);
     413               0 :         sort.AppendLiteral(" ");
     414               0 :         sort.Append(sortResource2);
     415                 :       }
     416                 :     }
     417                 :   }
     418                 :   else {
     419               0 :     nsWhitespaceTokenizer tokenizer(sort);
     420               0 :     while (tokenizer.hasMoreTokens()) {
     421               0 :       nsCOMPtr<nsIAtom> keyatom = do_GetAtom(tokenizer.nextToken());
     422               0 :       NS_ENSURE_TRUE(keyatom, NS_ERROR_OUT_OF_MEMORY);
     423               0 :       aSortState->sortKeys.AppendObject(keyatom);
     424                 :     }
     425                 :   }
     426                 : 
     427               0 :   aSortState->sort.Assign(sort);
     428               0 :   aSortState->direction = nsSortState_natural;
     429                 : 
     430               0 :   bool noNaturalState = false;
     431               0 :   nsWhitespaceTokenizer tokenizer(aSortHints);
     432               0 :   while (tokenizer.hasMoreTokens()) {
     433               0 :     const nsDependentSubstring& token(tokenizer.nextToken());
     434               0 :     if (token.EqualsLiteral("comparecase"))
     435               0 :       aSortState->sortHints |= nsIXULSortService::SORT_COMPARECASE;
     436               0 :     else if (token.EqualsLiteral("integer"))
     437               0 :       aSortState->sortHints |= nsIXULSortService::SORT_INTEGER;
     438               0 :     else if (token.EqualsLiteral("descending"))
     439               0 :       aSortState->direction = nsSortState_descending;
     440               0 :     else if (token.EqualsLiteral("ascending"))
     441               0 :       aSortState->direction = nsSortState_ascending;
     442               0 :     else if (token.EqualsLiteral("twostate"))
     443               0 :       noNaturalState = true;
     444                 :   }
     445                 : 
     446                 :   // if the twostate flag was set, the natural order is skipped and only
     447                 :   // ascending and descending are allowed
     448               0 :   if (aSortState->direction == nsSortState_natural && noNaturalState) {
     449               0 :     aSortState->direction = nsSortState_ascending;
     450                 :   }
     451                 : 
     452                 :   // set up sort order info
     453               0 :   aSortState->invertSort = false;
     454                 : 
     455               0 :   nsAutoString existingsort;
     456               0 :   aRootElement->GetAttr(kNameSpaceID_None, nsGkAtoms::sort, existingsort);
     457               0 :   nsAutoString existingsortDirection;
     458               0 :   aRootElement->GetAttr(kNameSpaceID_None, nsGkAtoms::sortDirection, existingsortDirection);
     459                 :           
     460                 :   // if just switching direction, set the invertSort flag
     461               0 :   if (sort.Equals(existingsort)) {
     462               0 :     if (aSortState->direction == nsSortState_descending) {
     463               0 :       if (existingsortDirection.EqualsLiteral("ascending"))
     464               0 :         aSortState->invertSort = true;
     465                 :     }
     466               0 :     else if (aSortState->direction == nsSortState_ascending &&
     467               0 :              existingsortDirection.EqualsLiteral("descending")) {
     468               0 :       aSortState->invertSort = true;
     469                 :     }
     470                 :   }
     471                 : 
     472                 :   // sort items between separators independently
     473                 :   aSortState->inbetweenSeparatorSort =
     474                 :     aRootElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::sortSeparators,
     475               0 :                               nsGkAtoms::_true, eCaseMatters);
     476                 : 
     477                 :   // sort static content (non template generated nodes) after generated content
     478                 :   aSortState->sortStaticsLast = aRootElement->AttrValueIs(kNameSpaceID_None,
     479                 :                                   nsGkAtoms::sortStaticsLast,
     480               0 :                                   nsGkAtoms::_true, eCaseMatters);
     481                 : 
     482               0 :   aSortState->initialized = true;
     483                 : 
     484               0 :   return NS_OK;
     485                 : }
     486                 : 
     487                 : PRInt32
     488               0 : XULSortServiceImpl::CompareValues(const nsAString& aLeft,
     489                 :                                   const nsAString& aRight,
     490                 :                                   PRUint32 aSortHints)
     491                 : {
     492               0 :   if (aSortHints & SORT_INTEGER) {
     493                 :     PRInt32 err;
     494               0 :     PRInt32 leftint = PromiseFlatString(aLeft).ToInteger(&err);
     495               0 :     if (NS_SUCCEEDED(err)) {
     496               0 :       PRInt32 rightint = PromiseFlatString(aRight).ToInteger(&err);
     497               0 :       if (NS_SUCCEEDED(err)) {
     498               0 :         return leftint - rightint;
     499                 :       }
     500                 :     }
     501                 :     // if they aren't integers, just fall through and compare strings
     502                 :   }
     503                 : 
     504               0 :   if (aSortHints & SORT_COMPARECASE) {
     505               0 :     return ::Compare(aLeft, aRight);
     506                 :   }
     507                 : 
     508               0 :   nsICollation* collation = nsXULContentUtils::GetCollation();
     509               0 :   if (collation) {
     510                 :     PRInt32 result;
     511                 :     collation->CompareString(nsICollation::kCollationCaseInSensitive,
     512               0 :                              aLeft, aRight, &result);
     513               0 :     return result;
     514                 :   }
     515                 : 
     516               0 :   return ::Compare(aLeft, aRight, nsCaseInsensitiveStringComparator());
     517                 : }
     518                 : 
     519                 : NS_IMETHODIMP
     520               0 : XULSortServiceImpl::Sort(nsIDOMNode* aNode,
     521                 :                          const nsAString& aSortKey,
     522                 :                          const nsAString& aSortHints)
     523                 : {
     524                 :   // get root content node
     525               0 :   nsCOMPtr<nsIContent> sortNode = do_QueryInterface(aNode);
     526               0 :   if (!sortNode)
     527               0 :     return NS_ERROR_FAILURE;
     528                 : 
     529               0 :   nsSortState sortState;
     530                 :   nsresult rv = InitializeSortState(sortNode, sortNode,
     531               0 :                                     aSortKey, aSortHints, &sortState);
     532               0 :   NS_ENSURE_SUCCESS(rv, rv);
     533                 :   
     534                 :   // store sort info in attributes on content
     535               0 :   SetSortHints(sortNode, &sortState);
     536               0 :   rv = SortContainer(sortNode, &sortState);
     537                 :   
     538               0 :   sortState.processor = nsnull; // don't hang on to this reference
     539               0 :   return rv;
     540                 : }
     541                 : 
     542                 : nsresult
     543               0 : NS_NewXULSortService(nsIXULSortService** sortService)
     544                 : {
     545               0 :   *sortService = new XULSortServiceImpl();
     546               0 :   if (!*sortService)
     547               0 :     return NS_ERROR_OUT_OF_MEMORY;
     548                 : 
     549               0 :   NS_ADDREF(*sortService);
     550               0 :   return NS_OK;
     551                 : }

Generated by: LCOV version 1.7