michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsString.h" michael@0: #include "nsReadableUtils.h" michael@0: #include "nsTArray.h" michael@0: #include "nsISimpleEnumerator.h" michael@0: #include "nsXPCOM.h" michael@0: #include "nsSupportsPrimitives.h" michael@0: #include "nsIComponentManager.h" michael@0: michael@0: #include "nsCommandGroup.h" michael@0: #include "nsIControllerCommand.h" michael@0: #include "nsCRT.h" michael@0: michael@0: michael@0: class nsGroupsEnumerator : public nsISimpleEnumerator michael@0: { michael@0: public: michael@0: nsGroupsEnumerator(nsHashtable& inHashTable); michael@0: virtual ~nsGroupsEnumerator(); michael@0: michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSISIMPLEENUMERATOR michael@0: michael@0: protected: michael@0: michael@0: static bool HashEnum(nsHashKey *aKey, void *aData, void* aClosure); michael@0: michael@0: nsresult Initialize(); michael@0: michael@0: protected: michael@0: michael@0: nsHashtable& mHashTable; michael@0: int32_t mIndex; michael@0: char ** mGroupNames; // array of pointers to char16_t* in the hash table michael@0: bool mInitted; michael@0: michael@0: }; michael@0: michael@0: /* Implementation file */ michael@0: NS_IMPL_ISUPPORTS(nsGroupsEnumerator, nsISimpleEnumerator) michael@0: michael@0: nsGroupsEnumerator::nsGroupsEnumerator(nsHashtable& inHashTable) michael@0: : mHashTable(inHashTable) michael@0: , mIndex(-1) michael@0: , mGroupNames(nullptr) michael@0: , mInitted(false) michael@0: { michael@0: /* member initializers and constructor code */ michael@0: } michael@0: michael@0: nsGroupsEnumerator::~nsGroupsEnumerator() michael@0: { michael@0: delete [] mGroupNames; // ok on null pointer michael@0: } michael@0: michael@0: /* boolean hasMoreElements (); */ michael@0: NS_IMETHODIMP michael@0: nsGroupsEnumerator::HasMoreElements(bool *_retval) michael@0: { michael@0: nsresult rv = NS_OK; michael@0: michael@0: NS_ENSURE_ARG_POINTER(_retval); michael@0: michael@0: if (!mInitted) { michael@0: rv = Initialize(); michael@0: if (NS_FAILED(rv)) return rv; michael@0: } michael@0: michael@0: *_retval = (mIndex < mHashTable.Count() - 1); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* nsISupports getNext (); */ michael@0: NS_IMETHODIMP michael@0: nsGroupsEnumerator::GetNext(nsISupports **_retval) michael@0: { michael@0: nsresult rv = NS_OK; michael@0: michael@0: NS_ENSURE_ARG_POINTER(_retval); michael@0: michael@0: if (!mInitted) { michael@0: rv = Initialize(); michael@0: if (NS_FAILED(rv)) return rv; michael@0: } michael@0: michael@0: mIndex ++; michael@0: if (mIndex >= mHashTable.Count()) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: char *thisGroupName = mGroupNames[mIndex]; michael@0: michael@0: nsCOMPtr supportsString = do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: supportsString->SetData(nsDependentCString(thisGroupName)); michael@0: return CallQueryInterface(supportsString, _retval); michael@0: } michael@0: michael@0: /* static */ michael@0: /* return false to stop */ michael@0: bool michael@0: nsGroupsEnumerator::HashEnum(nsHashKey *aKey, void *aData, void* aClosure) michael@0: { michael@0: nsGroupsEnumerator* groupsEnum = reinterpret_cast(aClosure); michael@0: nsCStringKey* stringKey = static_cast(aKey); michael@0: michael@0: groupsEnum->mGroupNames[groupsEnum->mIndex] = (char*)stringKey->GetString(); michael@0: groupsEnum->mIndex ++; michael@0: return true; michael@0: } michael@0: michael@0: nsresult michael@0: nsGroupsEnumerator::Initialize() michael@0: { michael@0: if (mInitted) return NS_OK; michael@0: michael@0: mGroupNames = new char*[mHashTable.Count()]; michael@0: if (!mGroupNames) return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: mIndex = 0; michael@0: mHashTable.Enumerate(HashEnum, (void*)this); michael@0: michael@0: mIndex = -1; michael@0: mInitted = true; michael@0: return NS_OK; michael@0: } michael@0: michael@0: #if 0 michael@0: #pragma mark - michael@0: #endif michael@0: michael@0: class nsNamedGroupEnumerator : public nsISimpleEnumerator michael@0: { michael@0: public: michael@0: nsNamedGroupEnumerator(nsTArray* inArray); michael@0: virtual ~nsNamedGroupEnumerator(); michael@0: michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSISIMPLEENUMERATOR michael@0: michael@0: protected: michael@0: michael@0: nsTArray* mGroupArray; michael@0: int32_t mIndex; michael@0: michael@0: }; michael@0: michael@0: nsNamedGroupEnumerator::nsNamedGroupEnumerator(nsTArray* inArray) michael@0: : mGroupArray(inArray) michael@0: , mIndex(-1) michael@0: { michael@0: } michael@0: michael@0: nsNamedGroupEnumerator::~nsNamedGroupEnumerator() michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(nsNamedGroupEnumerator, nsISimpleEnumerator) michael@0: michael@0: /* boolean hasMoreElements (); */ michael@0: NS_IMETHODIMP michael@0: nsNamedGroupEnumerator::HasMoreElements(bool *_retval) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(_retval); michael@0: michael@0: int32_t arrayLen = mGroupArray ? mGroupArray->Length() : 0; michael@0: *_retval = (mIndex < arrayLen - 1); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* nsISupports getNext (); */ michael@0: NS_IMETHODIMP michael@0: nsNamedGroupEnumerator::GetNext(nsISupports **_retval) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(_retval); michael@0: michael@0: if (!mGroupArray) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: mIndex ++; michael@0: if (mIndex >= int32_t(mGroupArray->Length())) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: char16_t *thisGroupName = (char16_t*)mGroupArray->ElementAt(mIndex); michael@0: NS_ASSERTION(thisGroupName, "Bad Element in mGroupArray"); michael@0: michael@0: nsresult rv; michael@0: nsCOMPtr supportsString = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: supportsString->SetData(nsDependentString(thisGroupName)); michael@0: return CallQueryInterface(supportsString, _retval); michael@0: } michael@0: michael@0: #if 0 michael@0: #pragma mark - michael@0: #endif michael@0: michael@0: michael@0: /* Implementation file */ michael@0: NS_IMPL_ISUPPORTS(nsControllerCommandGroup, nsIControllerCommandGroup) michael@0: michael@0: nsControllerCommandGroup::nsControllerCommandGroup() michael@0: { michael@0: } michael@0: michael@0: nsControllerCommandGroup::~nsControllerCommandGroup() michael@0: { michael@0: ClearGroupsHash(); michael@0: } michael@0: michael@0: void michael@0: nsControllerCommandGroup::ClearGroupsHash() michael@0: { michael@0: mGroupsHash.Reset(ClearEnumerator, (void *)this); michael@0: } michael@0: michael@0: #if 0 michael@0: #pragma mark - michael@0: #endif michael@0: michael@0: /* void addCommandToGroup (in DOMString aCommand, in DOMString aGroup); */ michael@0: NS_IMETHODIMP michael@0: nsControllerCommandGroup::AddCommandToGroup(const char * aCommand, const char *aGroup) michael@0: { michael@0: nsCStringKey groupKey(aGroup); michael@0: nsTArray* commandList; michael@0: if ((commandList = (nsTArray *)mGroupsHash.Get(&groupKey)) == nullptr) michael@0: { michael@0: // make this list michael@0: commandList = new nsAutoTArray; michael@0: mGroupsHash.Put(&groupKey, (void *)commandList); michael@0: } michael@0: // add the command to the list. Note that we're not checking for duplicates here michael@0: char* commandString = NS_strdup(aCommand); // we store allocated char16_t* in the array michael@0: if (!commandString) return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: #ifdef DEBUG michael@0: char** appended = michael@0: #endif michael@0: commandList->AppendElement(commandString); michael@0: NS_ASSERTION(appended, "Append failed"); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void removeCommandFromGroup (in DOMString aCommand, in DOMString aGroup); */ michael@0: NS_IMETHODIMP michael@0: nsControllerCommandGroup::RemoveCommandFromGroup(const char * aCommand, const char * aGroup) michael@0: { michael@0: nsCStringKey groupKey(aGroup); michael@0: nsTArray* commandList = (nsTArray *)mGroupsHash.Get(&groupKey); michael@0: if (!commandList) return NS_OK; // no group michael@0: michael@0: uint32_t numEntries = commandList->Length(); michael@0: for (uint32_t i = 0; i < numEntries; i ++) michael@0: { michael@0: char* commandString = commandList->ElementAt(i); michael@0: if (!nsCRT::strcmp(aCommand,commandString)) michael@0: { michael@0: commandList->RemoveElementAt(i); michael@0: nsMemory::Free(commandString); michael@0: break; michael@0: } michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* boolean isCommandInGroup (in DOMString aCommand, in DOMString aGroup); */ michael@0: NS_IMETHODIMP michael@0: nsControllerCommandGroup::IsCommandInGroup(const char * aCommand, const char * aGroup, bool *_retval) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(_retval); michael@0: *_retval = false; michael@0: michael@0: nsCStringKey groupKey(aGroup); michael@0: nsTArray* commandList = (nsTArray *)mGroupsHash.Get(&groupKey); michael@0: if (!commandList) return NS_OK; // no group michael@0: michael@0: uint32_t numEntries = commandList->Length(); michael@0: for (uint32_t i = 0; i < numEntries; i ++) michael@0: { michael@0: char* commandString = commandList->ElementAt(i); michael@0: if (!nsCRT::strcmp(aCommand,commandString)) michael@0: { michael@0: *_retval = true; michael@0: break; michael@0: } michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* nsISimpleEnumerator getGroupsEnumerator (); */ michael@0: NS_IMETHODIMP michael@0: nsControllerCommandGroup::GetGroupsEnumerator(nsISimpleEnumerator **_retval) michael@0: { michael@0: nsGroupsEnumerator* groupsEnum = new nsGroupsEnumerator(mGroupsHash); michael@0: if (!groupsEnum) return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: return groupsEnum->QueryInterface(NS_GET_IID(nsISimpleEnumerator), (void **)_retval); michael@0: } michael@0: michael@0: /* nsISimpleEnumerator getEnumeratorForGroup (in DOMString aGroup); */ michael@0: NS_IMETHODIMP michael@0: nsControllerCommandGroup::GetEnumeratorForGroup(const char * aGroup, nsISimpleEnumerator **_retval) michael@0: { michael@0: nsCStringKey groupKey(aGroup); michael@0: nsTArray* commandList = (nsTArray *)mGroupsHash.Get(&groupKey); // may be null michael@0: michael@0: nsNamedGroupEnumerator* theGroupEnum = new nsNamedGroupEnumerator(commandList); michael@0: if (!theGroupEnum) return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: return theGroupEnum->QueryInterface(NS_GET_IID(nsISimpleEnumerator), (void **)_retval); michael@0: } michael@0: michael@0: #if 0 michael@0: #pragma mark - michael@0: #endif michael@0: michael@0: bool nsControllerCommandGroup::ClearEnumerator(nsHashKey *aKey, void *aData, void* closure) michael@0: { michael@0: nsTArray* commandList = (nsTArray *)aData; michael@0: if (commandList) michael@0: { michael@0: uint32_t numEntries = commandList->Length(); michael@0: for (uint32_t i = 0; i < numEntries; i ++) michael@0: { michael@0: char* commandString = commandList->ElementAt(i); michael@0: nsMemory::Free(commandString); michael@0: } michael@0: michael@0: delete commandList; michael@0: } michael@0: michael@0: return true; michael@0: }