diff --git a/mozilla/toolkit/components/Makefile.in b/mozilla/toolkit/components/Makefile.in new file mode 100644 index 00000000000..306770fda7f --- /dev/null +++ b/mozilla/toolkit/components/Makefile.in @@ -0,0 +1,10 @@ +DEPTH = ../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +DIRS = autocomplete satchel build + +include $(topsrcdir)/config/rules.mk diff --git a/mozilla/toolkit/components/autocomplete/Makefile.in b/mozilla/toolkit/components/autocomplete/Makefile.in new file mode 100644 index 00000000000..7c7decc23c4 --- /dev/null +++ b/mozilla/toolkit/components/autocomplete/Makefile.in @@ -0,0 +1,10 @@ +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +DIRS = public src + +include $(topsrcdir)/config/rules.mk diff --git a/mozilla/toolkit/components/autocomplete/public/Makefile.in b/mozilla/toolkit/components/autocomplete/public/Makefile.in new file mode 100644 index 00000000000..e5b803a9d14 --- /dev/null +++ b/mozilla/toolkit/components/autocomplete/public/Makefile.in @@ -0,0 +1,40 @@ +# +# The contents of this file are subject to the Netscape Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/NPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# Joe Hewitt (Original Author) +# + +DEPTH=../../../.. +topsrcdir=@top_srcdir@ +srcdir=@srcdir@ +VPATH=@srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = toolkitcomps +XPIDL_MODULE = autocomplete + +XPIDLSRCS = nsIAutoCompleteController.idl \ + nsIAutoCompleteInput.idl \ + nsIAutoCompletePopup.idl \ + nsIAutoCompleteSearch.idl \ + nsIAutoCompleteResult.idl \ + $(NULL) + +EXPORTS = nsIAutoCompleteResultTypes.h + +include $(topsrcdir)/config/rules.mk diff --git a/mozilla/toolkit/components/autocomplete/public/nsIAutoCompleteController.idl b/mozilla/toolkit/components/autocomplete/public/nsIAutoCompleteController.idl new file mode 100644 index 00000000000..62b87e723a7 --- /dev/null +++ b/mozilla/toolkit/components/autocomplete/public/nsIAutoCompleteController.idl @@ -0,0 +1,128 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Joe Hewitt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +interface nsIAutoCompleteInput; + +[scriptable, uuid(75866768-ED00-4ff4-B950-485449A67A88)] +interface nsIAutoCompleteController : nsISupports +{ + /* + * Possible values for the searchStatus attribute + */ + const unsigned short STATUS_NONE = 1; + const unsigned short STATUS_SEARCHING = 2; + const unsigned short STATUS_COMPLETE_NO_MATCH = 3; + const unsigned short STATUS_COMPLETE_MATCH = 4; + + /* + * Possible key navigation values + */ + const unsigned short KEY_UP = 1; + const unsigned short KEY_DOWN = 2; + const unsigned short KEY_LEFT = 3; + const unsigned short KEY_RIGHT = 4; + const unsigned short KEY_PAGE_UP = 5; + const unsigned short KEY_PAGE_DOWN = 6; + const unsigned short KEY_HOME = 7; + const unsigned short KEY_END = 8; + + /* + * State which indicates the status of possible ongoing searches + */ + readonly attribute unsigned short searchStatus; + + /* + * The number of matches + */ + readonly attribute unsigned long matchCount; + + /* + * Begin conducting autocomplete behavior on a given input object + */ + void attachToInput(in nsIAutoCompleteInput input); + + /* + * Detach conductor from the widget it is currently attached to + */ + void detachFromInput(); + + /* + * Notify the controller that the user has changed text in the textbox. This includes all + * means of changing the text value, including typing a character, backspacing, deleting, or + * pasting in an entirely new value. + */ + void handleText(); + + /* + * Notify the controller that the user wishes to enter the current text + * + * @return True if the controller wishes to prevent event propagation and default event + */ + boolean handleEnter(); + + /* + * Notify the controller that the user wishes to revert autocomplete + * + * @return True if the controller wishes to prevent event propagation and default event + */ + boolean handleEscape(); + + /* + * Notify the controller of the following key navigation events: + * up, down, left, right, page up, page down + * + * @return True if the controller wishes to prevent event propagation and default event + */ + boolean handleKeyNavigation(in unsigned short key); + + /* + * Get the value of the result at a given index in the last completed search + */ + AString getValueAt(in long index); + + /* + * Get the comment of the result at a given index in the last completed search + */ + AString getCommentAt(in long index); + + /* + * Get a the style hint for the result at a given index in the last completed search + */ + AString getStyleAt(in long index); +}; diff --git a/mozilla/toolkit/components/autocomplete/public/nsIAutoCompleteInput.idl b/mozilla/toolkit/components/autocomplete/public/nsIAutoCompleteInput.idl new file mode 100644 index 00000000000..001406f86f8 --- /dev/null +++ b/mozilla/toolkit/components/autocomplete/public/nsIAutoCompleteInput.idl @@ -0,0 +1,142 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Joe Hewitt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +interface nsIAutoCompletePopup; + +[scriptable, uuid(3B6E2742-B136-4588-A6DF-699B9585AF60)] +interface nsIAutoCompleteInput : nsISupports +{ + /* + * The result view that will be used to display results + */ + readonly attribute nsIAutoCompletePopup popup; + + /* + * Indicates if the popup is currently open + */ + attribute boolean popupOpen; + + /* + * Option to disable autocomplete functionality + */ + attribute boolean disableAutoComplete; + + /* + * If a search result has its defaultIndex set, this will optionally + * try to complete the text in the textbox to the entire text of the + * result at the default index as the user types + */ + attribute boolean completeDefaultIndex; + + /* + * Option for completing to the default result whenever the user hits + * enter or the textbox loses focus + */ + attribute boolean forceComplete; + + /* + * Option to open the popup only after a certain number of results are available + */ + attribute unsigned long minResultsForPopup; + + /* + * Option to show a second column in the popup which contains + * the comment for each autocomplete result + */ + attribute unsigned long showCommentColumn; + + /* + * Number of milliseconds after a keystroke before a search begins + */ + attribute unsigned long timeout; + + /* + * An extra parameter to configure searches with. + */ + attribute AString searchParam; + + /* + * The number of autocomplete session to search + */ + readonly attribute unsigned long searchCount; + + /* + * Get the name of one of the autocomplete search session objects + */ + ACString getSearchAt(in unsigned long index); + + /* + * The value of text in the autocomplete textbox + */ + attribute AString textValue; + + /* + * Report the starting index of the cursor in the textbox + */ + readonly attribute long selectionStart; + + /* + * Report the ending index of the cursor in the textbox + */ + readonly attribute long selectionEnd; + + /* + * Select a range of text in the autocomplete textbox + */ + void selectTextRange(in long startIndex, in long endIndex); + + /* + * Notification that the search concluded successfully + */ + void onSearchComplete(); + + /* + * Notification that the user selected and entered a result item + * + * @return True if the user wishes to prevent the enter + */ + boolean onTextEntered(); + + /* + * Notification that the user cancelled the autocomplete session + * + * @return True if the user wishes to prevent the revert + */ + boolean onTextReverted(); +}; diff --git a/mozilla/toolkit/components/autocomplete/public/nsIAutoCompletePopup.idl b/mozilla/toolkit/components/autocomplete/public/nsIAutoCompletePopup.idl new file mode 100644 index 00000000000..ac8425e6fc9 --- /dev/null +++ b/mozilla/toolkit/components/autocomplete/public/nsIAutoCompletePopup.idl @@ -0,0 +1,96 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Joe Hewitt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +interface nsIAutoCompleteInput; + +[scriptable, uuid(65F6CD46-22EC-4329-BB3B-BCD1103F2204)] +interface nsIAutoCompletePopup : nsISupports +{ + /* + * The input object that the popup is currently bound to + */ + readonly attribute nsIAutoCompleteInput input; + + /* + * An alternative value to be used when text is entered, rather than the + * value of the selected item + */ + readonly attribute AString overrideValue; + + /* + * The index of the result item that is currently selected + */ + attribute long selectedIndex; + + /* + * Indicates if the popup is currently open + */ + readonly attribute boolean popupOpen; + + /* + * Bind the popup to an input object and display it with the given coordinates + * + * @param input - The input object that the popup will be bound to + * @param x - The x coordinate to display the popup at + * @param y - The y coordinate to display the popup at + * @param width - The width that the popup should size itself to + */ + void openPopup(in nsIAutoCompleteInput input, in long x, in long y, in long width); + + /* + * Close the popup and detach from the bound input + */ + void closePopup(); + + /* + * Instruct the result view to repaint itself to reflect the most current + * underlying data + */ + void invalidate(); + + /* + * Change the selection relative to the current selection and make sure + * the newly selected row is visible + * + * @param reverse - Select a row above the current selection + * @param page - Select a row that is a full visible page from the current selection + * @return The currently selected result item index + */ + void selectBy(in boolean reverse, in boolean page); +}; diff --git a/mozilla/toolkit/components/autocomplete/public/nsIAutoCompleteResult.idl b/mozilla/toolkit/components/autocomplete/public/nsIAutoCompleteResult.idl new file mode 100644 index 00000000000..5851d181c74 --- /dev/null +++ b/mozilla/toolkit/components/autocomplete/public/nsIAutoCompleteResult.idl @@ -0,0 +1,90 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Joe Hewitt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +[scriptable, uuid(44864910-332C-46b0-A4F9-14A301DBCA80)] +interface nsIAutoCompleteResult : nsISupports +{ + /** + * Possible values for the searchResult attribute + */ + const unsigned short RESULT_IGNORED = 1; /* indicates invalid searchString */ + const unsigned short RESULT_FAILURE = 2; /* indicates failure */ + const unsigned short RESULT_NOMATCH = 3; /* indicates success with no matches */ + const unsigned short RESULT_SUCCESS = 4; /* indicates success with matches */ + + /** + * The original search string + */ + readonly attribute AString searchString; + + /** + * The result of the search + */ + readonly attribute unsigned short searchResult; + + /** + * Index of the default item that should be entered if none is selected + */ + readonly attribute long defaultIndex; + + /** + * A string describing the cause of a search failure + */ + readonly attribute AString errorDescription; + + /** + * The number of matches + */ + readonly attribute unsigned long matchCount; + + /** + * Get the value of the result at the given index + */ + AString getValueAt(in long index); + + /** + * Get the comment of the result at the given index + */ + AString getCommentAt(in long index); + + /** + * Get the style hint for the result at the given index + */ + AString getStyleAt(in long index); +}; diff --git a/mozilla/toolkit/components/autocomplete/public/nsIAutoCompleteResultTypes.h b/mozilla/toolkit/components/autocomplete/public/nsIAutoCompleteResultTypes.h new file mode 100644 index 00000000000..da593075c8f --- /dev/null +++ b/mozilla/toolkit/components/autocomplete/public/nsIAutoCompleteResultTypes.h @@ -0,0 +1,74 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Joe Hewitt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __nsIAutoCompleteResultTypes__ +#define __nsIAutoCompleteResultTypes__ + +#include "nsIAutoCompleteResult.h" +#include "nsString.h" +#include "nsVoidArray.h" +#include "mdb.h" + +class nsIAutoCompleteBaseResult : public nsIAutoCompleteResult +{ +public: + NS_IMETHOD SetSearchString(const nsAString &aSearchString) = 0; + NS_IMETHOD SetErrorDescription(const nsAString &aErrorDescription) = 0; + NS_IMETHOD SetDefaultIndex(PRInt32 aDefaultIndex) = 0; + NS_IMETHOD SetSearchResult(PRUint32 aSearchResult) = 0; +}; + +class nsIAutoCompleteMdbResult : public nsIAutoCompleteBaseResult +{ +public: + enum eDataType { + kUnicharType, + kCharType, + kIntType + }; + + NS_IMETHOD Init(nsIMdbEnv *aEnv, nsIMdbTable *aTable) = 0; + NS_IMETHOD SetTokens(mdb_scope aValueToken, eDataType aValueType, mdb_scope aCommentToken, eDataType aCommentType) = 0; + NS_IMETHOD AddRow(nsIMdbRow *aRow) = 0; + NS_IMETHOD RemoveRowAt(PRUint32 aRowIndex) = 0; + NS_IMETHOD GetRowAt(PRUint32 aRowIndex, nsIMdbRow **aRow) = 0; + NS_IMETHOD GetRowValue(nsIMdbRow *aRow, mdb_column aCol, nsAString &aValue) = 0; + NS_IMETHOD GetRowValue(nsIMdbRow *aRow, mdb_column aCol, nsACString &aValue) = 0; + NS_IMETHOD GetRowValue(nsIMdbRow *aRow, mdb_column aCol, PRInt32 *aValue) = 0; +}; + +#endif // __nsIAutoCompleteResultTypes__ diff --git a/mozilla/toolkit/components/autocomplete/public/nsIAutoCompleteSearch.idl b/mozilla/toolkit/components/autocomplete/public/nsIAutoCompleteSearch.idl new file mode 100644 index 00000000000..f024d591ffc --- /dev/null +++ b/mozilla/toolkit/components/autocomplete/public/nsIAutoCompleteSearch.idl @@ -0,0 +1,76 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Joe Hewitt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +interface nsIAutoCompleteResult; +interface nsIAutoCompleteObserver; + +[scriptable, uuid(DE8DB85F-C1DE-4d87-94BA-7844890F91FE)] +interface nsIAutoCompleteSearch : nsISupports +{ + /* + * Search for a given string and notify a listener (either synchronously + * or asynchronously) of the result + * + * @param searchString - The string to search for + * @param searchParam - An extra parameter + * @param previousResult - A previous result to use for faster searchinig + * @param listener - A listener to notify when the search is complete + */ + void startSearch(in AString searchString, + in AString searchParam, + in nsIAutoCompleteResult previousResult, + in nsIAutoCompleteObserver listener); + + /* + * Stop an asynchronous search that is in progress + */ + void stopSearch(); +}; + +[scriptable, uuid(18C36504-9A4C-4ac3-8494-BD05E00AE27F)] +interface nsIAutoCompleteObserver : nsISupports +{ + /* + * Called when a search is complete and the results are ready + * + * @param search - The search object that processed this search + * @param result - The search result object + */ + void onSearchResult(in nsIAutoCompleteSearch search, in nsIAutoCompleteResult result); +}; \ No newline at end of file diff --git a/mozilla/toolkit/components/autocomplete/src/Makefile.in b/mozilla/toolkit/components/autocomplete/src/Makefile.in new file mode 100644 index 00000000000..b10508ba44b --- /dev/null +++ b/mozilla/toolkit/components/autocomplete/src/Makefile.in @@ -0,0 +1,43 @@ +# +# The contents of this file are subject to the Netscape Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/NPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# Joe Hewitt (Original Author) +# + +DEPTH=../../../.. +topsrcdir=@top_srcdir@ +srcdir=@srcdir@ +VPATH=@srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = toolkitcomps +LIBRARY_NAME = autocomplete_s +FORCE_STATIC_LIB = 1 + +REQUIRES = xpcom \ + string \ + dom \ + layout \ + mork \ + $(NULL) + +CPPSRCS = nsAutoCompleteController.cpp \ + nsAutoCompleteMdbResult.cpp \ + $(NULL) + +include $(topsrcdir)/config/rules.mk diff --git a/mozilla/toolkit/components/autocomplete/src/nsAutoCompleteController.cpp b/mozilla/toolkit/components/autocomplete/src/nsAutoCompleteController.cpp new file mode 100644 index 00000000000..f57ae8e601e --- /dev/null +++ b/mozilla/toolkit/components/autocomplete/src/nsAutoCompleteController.cpp @@ -0,0 +1,1000 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Joe Hewitt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsAutoCompleteController.h" + +#include "nsIServiceManager.h" +#include "nsIDOMKeyEvent.h" +#include "nsIDOMNode.h" +#include "nsIDOMEventTarget.h" +#include "nsIAtomService.h" +#include "nsReadableUtils.h" + +static const char *kAutoCompleteSearchCID = "@mozilla.org/autocomplete/search;1?name="; + +static const char *kCompleteConcatSeparator = " >> "; + +NS_IMPL_ISUPPORTS4(nsAutoCompleteController, nsIAutoCompleteController, nsIAutoCompleteObserver, nsITimerCallback, nsITreeView) + +nsAutoCompleteController::nsAutoCompleteController() : + mNeedToComplete(PR_FALSE), + mEnterAfterSearch(PR_FALSE), + mDefaultIndexCompleted(PR_FALSE), + mBackspaced(PR_FALSE), + mSearchStatus(0), + mRowCount(0), + mSearchesOngoing(0) +{ + NS_INIT_ISUPPORTS(); + + mSearches = do_CreateInstance("@mozilla.org/supports-array;1"); + mResults = do_CreateInstance("@mozilla.org/supports-array;1"); +} + +nsAutoCompleteController::~nsAutoCompleteController() +{ + DetachFromInput(); +} + +//////////////////////////////////////////////////////////////////////// +//// nsIAutoCompleteController + +NS_IMETHODIMP +nsAutoCompleteController::GetSearchStatus(PRUint16 *aSearchStatus) +{ + *aSearchStatus = mSearchStatus; + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::GetMatchCount(PRUint32 *aMatchCount) +{ + *aMatchCount = mRowCount; + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::AttachToInput(nsIAutoCompleteInput *aInput) +{ + if (!aInput) + return NS_ERROR_ILLEGAL_VALUE; + + if (mInput) + DetachFromInput(); + + mInput = aInput; + + // reset all search state members to default values + mSearchString.Truncate(0); + mEnterAfterSearch = PR_FALSE; + mNeedToComplete = PR_FALSE; + mDefaultIndexCompleted = PR_FALSE; + mBackspaced = PR_FALSE; + mSearchStatus = nsIAutoCompleteController::STATUS_NONE; + mRowCount = 0; + mSearchesOngoing = 0; + + // initialize our list of search objects + PRUint32 searchCount; + mInput->GetSearchCount(&searchCount); + mResults->SizeTo(searchCount); + mSearches->SizeTo(searchCount); + + const char *searchCID = kAutoCompleteSearchCID; + + for (PRUint32 i = 0; i < searchCount; ++i) { + // Use the search name to create the contract id string for the search service + nsCAutoString searchName; + mInput->GetSearchAt(i, searchName); + nsCAutoString cid(searchCID); + cid.Append(searchName); + + // Use the created cid to get a pointer to the search service and store it for later + nsIAutoCompleteSearch* search = nsnull; + CallGetService(cid.get(), &search); + if (search) + mSearches->AppendElement(search); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::DetachFromInput() +{ + if (mInput) { + ClearSearchTimer(); + ClearResults(); + ClosePopup(); + + // release refcounted and allocated members + mInput = nsnull; + mSearches->Clear(); + mSearchString.Truncate(0); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::HandleText() +{ + // Stop current search in case it's async. + StopSearch(); + // Stop the queued up search on a timer + ClearSearchTimer(); + + PRBool disabled; + mInput->GetDisableAutoComplete(&disabled); + NS_ENSURE_TRUE(!disabled, NS_OK;); + + mNeedToComplete = PR_TRUE; + + nsAutoString newValue; + mInput->GetTextValue(newValue); + + // Don't search again if the new string is the same as the last search + if (newValue.Length() > 0 && newValue.Equals(mSearchString)) + return NS_OK; + + // Determine if the user has removed text from the end (probably by backspacing) + if (newValue.Length() < mSearchString.Length() && + Substring(mSearchString, 0, newValue.Length()).Equals(newValue)) + { + // We need to throw away previous results so we don't try to search through them again + ClearResults(); + mBackspaced = PR_TRUE; + } else + mBackspaced = PR_FALSE; + + mSearchString = newValue; + + // Don't search if the value is empty + if (newValue.Length() == 0) { + ClosePopup(); + return NS_OK; + } + + // Kick off the search, but only if the cursor is at the end of the textbox + PRBool selectionStart; + mInput->GetSelectionStart(&selectionStart); + PRBool selectionEnd; + mInput->GetSelectionEnd(&selectionEnd); + + if (selectionStart == selectionEnd && selectionStart == mSearchString.Length()) + StartSearchTimer(); + + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::HandleEnter(PRBool *_retval) +{ + // allow the event through unless there is something selected in the popup + mInput->GetPopupOpen(_retval); + if (*_retval) { + nsCOMPtr popup; + mInput->GetPopup(getter_AddRefs(popup)); + PRInt32 selectedIndex; + popup->GetSelectedIndex(&selectedIndex); + *_retval = selectedIndex >= 0; + } + + ClearSearchTimer(); + EnterMatch(); + + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::HandleEscape(PRBool *_retval) +{ + // allow the event through if the popup is closed + mInput->GetPopupOpen(_retval); + + ClearSearchTimer(); + RevertTextValue(); + ClosePopup(); + + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::HandleKeyNavigation(PRUint16 aKey, PRBool *_retval) +{ + // By default, don't cancel the event + *_retval = PR_FALSE; + + mNeedToComplete = PR_FALSE; + + nsCOMPtr popup; + mInput->GetPopup(getter_AddRefs(popup)); + NS_ENSURE_TRUE(popup != nsnull, NS_ERROR_FAILURE); + + if (aKey == nsIAutoCompleteController::KEY_UP || + aKey == nsIAutoCompleteController::KEY_DOWN || + aKey == nsIAutoCompleteController::KEY_PAGE_UP || + aKey == nsIAutoCompleteController::KEY_PAGE_DOWN) + { + // Prevent the input from handling up/down events, as it may move + // the cursor to home/end on some systems + *_retval = PR_TRUE; + + PRBool isOpen; + mInput->GetPopupOpen(&isOpen); + if (isOpen) { + PRBool reverse = aKey == nsIAutoCompleteController::KEY_UP || + aKey == nsIAutoCompleteController::KEY_PAGE_UP ? PR_TRUE : PR_FALSE; + PRBool page = aKey == nsIAutoCompleteController::KEY_PAGE_UP || + aKey == nsIAutoCompleteController::KEY_PAGE_DOWN ? PR_TRUE : PR_FALSE; + + // Instruct the result view to scroll by the given amount and direction + popup->SelectBy(reverse, page); + + // Fill in the value of the textbox with whatever is selected in the popup + PRInt32 selectedIndex; + popup->GetSelectedIndex(&selectedIndex); + if (selectedIndex >= 0) { + // A result is selected, so fill in its value + nsAutoString value; + if (NS_SUCCEEDED(GetResultValueAt(selectedIndex, PR_TRUE, value))) + CompleteValue(value); + } else { + // Nothing is selected, so fill in the last typed value + mInput->SetTextValue(mSearchString); + mInput->SelectTextRange(mSearchString.Length(), mSearchString.Length()); + } + } else { + // Open the popup if there has been a previous search, or else kick off a new search + PRUint32 resultCount; + mResults->Count(&resultCount); + if (resultCount) { + if (mRowCount) { + OpenPopup(); + } + } else + StartSearchTimer(); + } + } else if (aKey == nsIAutoCompleteController::KEY_LEFT || + aKey == nsIAutoCompleteController::KEY_RIGHT) + { + // When the user arrows to the side, close the popup + ClearSearchTimer(); + ClosePopup(); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::GetValueAt(PRInt32 aIndex, nsAString & _retval) +{ + GetResultValueAt(aIndex, PR_FALSE, _retval); + + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::GetCommentAt(PRInt32 aIndex, nsAString & _retval) +{ + PRInt32 searchIndex; + PRInt32 rowIndex; + RowIndexToSearch(aIndex, &searchIndex, &rowIndex); + NS_ENSURE_TRUE(searchIndex >= 0 && rowIndex >= 0, NS_ERROR_FAILURE); + + nsCOMPtr result; + mResults->GetElementAt(searchIndex, getter_AddRefs(result)); + NS_ENSURE_TRUE(result, NS_ERROR_FAILURE); + + result->GetCommentAt(rowIndex, _retval); + + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::GetStyleAt(PRInt32 aIndex, nsAString & _retval) +{ + PRInt32 searchIndex; + PRInt32 rowIndex; + RowIndexToSearch(aIndex, &searchIndex, &rowIndex); + NS_ENSURE_TRUE(searchIndex >= 0 && rowIndex >= 0, NS_ERROR_FAILURE); + + nsCOMPtr result; + mResults->GetElementAt(searchIndex, getter_AddRefs(result)); + NS_ENSURE_TRUE(result, NS_ERROR_FAILURE); + + result->GetStyleAt(rowIndex, _retval); + + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +//// nsIAutoCompleteObserver + +NS_IMETHODIMP +nsAutoCompleteController::OnSearchResult(nsIAutoCompleteSearch *aSearch, nsIAutoCompleteResult* aResult) +{ + // look up the index of the search which is returning + PRUint32 count; + mSearches->Count(&count); + for (PRUint32 i = 0; i < count; ++i) { + nsCOMPtr search; + mSearches->GetElementAt(i, getter_AddRefs(search)); + if (search == aSearch) { + ProcessResult(i, aResult); + } + } + + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +//// nsITimerCallback + +NS_IMETHODIMP +nsAutoCompleteController::Notify(nsITimer *timer) +{ + mTimer = nsnull; + StartSearch(); + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +// nsITreeView + +NS_IMETHODIMP +nsAutoCompleteController::GetRowCount(PRInt32 *aRowCount) +{ + *aRowCount = mRowCount; + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::GetRowProperties(PRInt32 index, nsISupportsArray *properties) +{ + // XXX This is a hack because the tree doesn't seem to be painting the selected row + // the normal way. Please remove this ASAP. + PRInt32 currentIndex; + mSelection->GetCurrentIndex(¤tIndex); + + if (index == currentIndex) { + nsCOMPtr atomSvc = do_GetService("@mozilla.org/atom-service;1"); + nsCOMPtr atom; + atomSvc->GetAtom(NS_LITERAL_STRING("menuactive").get(), getter_AddRefs(atom)); + properties->AppendElement(atom); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::GetCellProperties(PRInt32 row, const PRUnichar *colID, nsISupportsArray *properties) +{ + GetRowProperties(row, properties); + + if (row >= 0) { + nsAutoString className; + GetStyleAt(row, className); + if (!className.IsEmpty()) { + nsCOMPtr atomSvc = do_GetService("@mozilla.org/atom-service;1"); + nsCOMPtr atom; + atomSvc->GetAtom(className.get(), getter_AddRefs(atom)); + properties->AppendElement(atom); + } + } + + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::GetColumnProperties(const PRUnichar *colID, nsIDOMElement *colElt, nsISupportsArray *properties) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::GetImageSrc(PRInt32 row, const PRUnichar *colID, nsAString& _retval) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::GetProgressMode(PRInt32 row, const PRUnichar *colID, PRInt32* _retval) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::GetCellValue(PRInt32 row, const PRUnichar *colID, nsAString& _retval) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::GetCellText(PRInt32 row, const PRUnichar *colID, nsAString& _retval) +{ + nsDependentString columnId(colID); + + if (columnId.Equals(NS_LITERAL_STRING("treecolAutoCompleteValue"))) + GetValueAt(row, _retval); + else if(columnId.Equals(NS_LITERAL_STRING("treecolAutoCompleteComment"))) + GetCommentAt(row, _retval); + + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::IsContainer(PRInt32 index, PRBool *_retval) +{ + *_retval = PR_FALSE; + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::IsContainerOpen(PRInt32 index, PRBool *_retval) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::IsContainerEmpty(PRInt32 index, PRBool *_retval) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::GetLevel(PRInt32 index, PRInt32 *_retval) +{ + *_retval = 0; + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::GetParentIndex(PRInt32 rowIndex, PRInt32 *_retval) +{ + *_retval = 0; + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::HasNextSibling(PRInt32 rowIndex, PRInt32 afterIndex, PRBool *_retval) +{ + *_retval = PR_FALSE; + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::ToggleOpenState(PRInt32 index) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::SetTree(nsITreeBoxObject *tree) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::GetSelection(nsITreeSelection * *aSelection) +{ + *aSelection = mSelection; + NS_IF_ADDREF(*aSelection); + return NS_OK; +} + +NS_IMETHODIMP nsAutoCompleteController::SetSelection(nsITreeSelection * aSelection) +{ + mSelection = aSelection; + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::SelectionChanged() +{ + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::SetCellText(PRInt32 row, const PRUnichar *colID, const PRUnichar *value) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::CycleHeader(const PRUnichar *colID, nsIDOMElement *elt) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::CycleCell(PRInt32 row, const PRUnichar *colID) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::IsEditable(PRInt32 row, const PRUnichar *colID, PRBool *_retval) +{ + *_retval = PR_FALSE; + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::IsSeparator(PRInt32 index, PRBool *_retval) +{ + *_retval = PR_FALSE; + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::IsSorted(PRBool *_retval) +{ + *_retval = PR_FALSE; + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::CanDropOn(PRInt32 index, PRBool *_retval) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::CanDropBeforeAfter(PRInt32 index, PRBool before, PRBool *_retval) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::Drop(PRInt32 row, PRInt32 orientation) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::PerformAction(const PRUnichar *action) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::PerformActionOnRow(const PRUnichar *action, PRInt32 row) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteController::PerformActionOnCell(const PRUnichar *action, PRInt32 row, const PRUnichar *colID) +{ + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +//// nsAutoCompleteController + +nsresult +nsAutoCompleteController::OpenPopup() +{ + PRUint32 minResults; + mInput->GetMinResultsForPopup(&minResults); + if (mRowCount >= minResults) + return mInput->SetPopupOpen(PR_TRUE); + + return NS_OK; +} + +nsresult +nsAutoCompleteController::ClosePopup() +{ + nsCOMPtr popup; + mInput->GetPopup(getter_AddRefs(popup)); + NS_ENSURE_TRUE(popup != nsnull, NS_ERROR_FAILURE); + popup->SetSelectedIndex(-1); + + return mInput->SetPopupOpen(PR_FALSE); +} + +nsresult +nsAutoCompleteController::StartSearch() +{ + mSearchStatus = nsIAutoCompleteController::STATUS_SEARCHING; + mDefaultIndexCompleted = PR_FALSE; + + PRUint32 count; + mSearches->Count(&count); + mSearchesOngoing = count; + + PRUint32 searchesFailed = 0; + for (PRUint32 i = 0; i < count; ++i) { + nsCOMPtr search; + mSearches->GetElementAt(i, getter_AddRefs(search)); + nsCOMPtr result; + mResults->GetElementAt(i, getter_AddRefs(result)); + + if (result) { + PRUint16 searchResult; + result->GetSearchResult(&searchResult); + if (searchResult != nsIAutoCompleteResult::RESULT_SUCCESS) + result = nsnull; + } + + nsAutoString searchParam; + mInput->GetSearchParam(searchParam); + + nsresult rv = search->StartSearch(mSearchString, searchParam, result, NS_STATIC_CAST(nsIAutoCompleteObserver *, this)); + if (NS_FAILED(rv)) { + ++searchesFailed; + --mSearchesOngoing; + } + } + + if (searchesFailed == count) { + PostSearchCleanup(); + } + return NS_OK; +} + +nsresult +nsAutoCompleteController::StopSearch() +{ + // Stop the timer if there is one + ClearSearchTimer(); + + // Stop any ongoing asynchronous searches + if (mSearchStatus == nsIAutoCompleteController::STATUS_SEARCHING) { + PRUint32 count; + mSearches->Count(&count); + + for (PRUint32 i = 0; i < count; ++i) { + nsCOMPtr search; + mSearches->GetElementAt(i, getter_AddRefs(search)); + search->StopSearch(); + } + } + return NS_OK; +} + +nsresult +nsAutoCompleteController::StartSearchTimer() +{ + PRUint32 timeout; + mInput->GetTimeout(&timeout); + + mTimer = do_CreateInstance("@mozilla.org/timer;1"); + mTimer->InitWithCallback(this, 0, timeout); + return NS_OK; +} + +nsresult +nsAutoCompleteController::ClearSearchTimer() +{ + if (mTimer) { + mTimer->Cancel(); + mTimer = nsnull; + } + return NS_OK; +} + +nsresult +nsAutoCompleteController::EnterMatch() +{ + // If a search is still ongoing, bail out of this function + // and let the search finish, and tell it to come back here when it's done + if (mSearchStatus == nsIAutoCompleteController::STATUS_SEARCHING) { + mEnterAfterSearch = PR_TRUE; + return NS_OK; + } else + mEnterAfterSearch = PR_FALSE; + + nsCOMPtr popup; + mInput->GetPopup(getter_AddRefs(popup)); + NS_ENSURE_TRUE(popup != nsnull, NS_ERROR_FAILURE); + + PRBool forceComplete; + mInput->GetForceComplete(&forceComplete); + + // Ask the popup if it wants to enter a special value into the textbox + nsAutoString value; + popup->GetOverrideValue(value); + if (value.IsEmpty()) { + // If a row is selected in the popup, enter it into the textbox + PRInt32 selectedIndex; + popup->GetSelectedIndex(&selectedIndex); + if (selectedIndex >= 0) + GetResultValueAt(selectedIndex, PR_TRUE, value); + + if (forceComplete && value.IsEmpty()) { + // Since nothing was selected, and forceComplete is specified, that means + // we have to find find the first default match and enter it instead + PRUint32 count; + mResults->Count(&count); + for (PRUint32 i = 0; i < count; ++i) { + nsCOMPtr result; + mResults->GetElementAt(i, getter_AddRefs(result)); + + if (result) { + PRInt32 defaultIndex; + result->GetDefaultIndex(&defaultIndex); + if (defaultIndex >= 0) { + result->GetValueAt(defaultIndex, value); + break; + } + } + } + } + } + + if (!value.IsEmpty()) { + mInput->SetTextValue(value); + mInput->SelectTextRange(-1, -1); + mSearchString = value; + } + + ClosePopup(); + + PRBool cancel; + mInput->OnTextEntered(&cancel); + + return NS_OK; +} + +nsresult +nsAutoCompleteController::RevertTextValue() +{ + nsAutoString oldValue(mSearchString); + + PRBool cancel = PR_FALSE; + mInput->OnTextReverted(&cancel); + + if (!cancel) + mInput->SetTextValue(oldValue); + + nsAutoString value; + mInput->GetTextValue(value); + mSearchString.Assign(value); + + mNeedToComplete = PR_FALSE; + return NS_OK; +} + +nsresult +nsAutoCompleteController::ProcessResult(PRInt32 aSearchIndex, nsIAutoCompleteResult *aResult) +{ + // If this is the first search to return, we should clear out the previous cached results + PRUint32 searchCount; + mSearches->Count(&searchCount); + if (mSearchesOngoing == searchCount) + ClearResults(); + + --mSearchesOngoing; + + // Cache the result + mResults->AppendElement(aResult); + + // If the search failed, increase the match count to include the error description + PRUint16 result = 0; + if (aResult) + aResult->GetSearchResult(&result); + if (result == nsIAutoCompleteResult::RESULT_FAILURE) { + nsAutoString error; + aResult->GetErrorDescription(error); + if (!error.IsEmpty()) + ++mRowCount; + } else if (result == nsIAutoCompleteResult::RESULT_SUCCESS) { + // Increase the match count for all matches in this result + PRUint32 matchCount = 0; + aResult->GetMatchCount(&matchCount); + mRowCount += matchCount; + + // Try to autocomplete the default index for this search + CompleteDefaultIndex(aSearchIndex); + } + + // Refresh the popup view to display the new search results + nsCOMPtr popup; + mInput->GetPopup(getter_AddRefs(popup)); + NS_ENSURE_TRUE(popup != nsnull, NS_ERROR_FAILURE); + popup->Invalidate(); + + // Make sure the popup is open, if necessary, since we now + // have at least one search result ready to display + if (mRowCount) + OpenPopup(); + else + ClosePopup(); + + // If this is the last search to return, cleanup + if (mSearchesOngoing == 0) + PostSearchCleanup(); + + return NS_OK; +} + +nsresult +nsAutoCompleteController::PostSearchCleanup() +{ + if (mRowCount) { + OpenPopup(); + mSearchStatus = nsIAutoCompleteController::STATUS_COMPLETE_MATCH; + } else { + mSearchStatus = nsIAutoCompleteController::STATUS_COMPLETE_NO_MATCH; + ClosePopup(); + } + + // notify the input that the search is complete + mInput->OnSearchComplete(); + + // if mEnterAfterSearch was set, then the user hit enter while the search was ongoing, + // so we need to enter a match now that the search is done + if (mEnterAfterSearch) + EnterMatch(); + + return NS_OK; +} + +nsresult +nsAutoCompleteController::ClearResults() +{ + mRowCount = 0; + mResults->Clear(); + return NS_OK; +} + +nsresult +nsAutoCompleteController::CompleteDefaultIndex(PRInt32 aSearchIndex) +{ + if (mDefaultIndexCompleted || mEnterAfterSearch || mBackspaced || mRowCount == 0 || mSearchString.Length() == 0) + return NS_OK; + + PRBool shouldComplete; + mInput->GetCompleteDefaultIndex(&shouldComplete); + if (!shouldComplete) + return NS_OK; + + nsCOMPtr search; + mSearches->GetElementAt(aSearchIndex, getter_AddRefs(search)); + nsCOMPtr result; + mResults->GetElementAt(aSearchIndex, getter_AddRefs(result)); + NS_ENSURE_TRUE(result != nsnull, NS_ERROR_FAILURE); + + // The search must explicitly provide a default index in order + // for us to be able to complete + PRInt32 defaultIndex; + result->GetDefaultIndex(&defaultIndex); + NS_ENSURE_TRUE(defaultIndex >= 0, NS_OK); + + nsAutoString resultValue; + result->GetValueAt(defaultIndex, resultValue); + CompleteValue(resultValue); + + mDefaultIndexCompleted = PR_TRUE; + + return NS_OK; +} + +nsresult +nsAutoCompleteController::CompleteValue(nsString &aValue) +{ + PRInt32 findIndex = aValue.Find(mSearchString, PR_FALSE); + if (findIndex == 0) { + // The textbox value matches the beginning of the default value, so we can just + // append the latter portion + mInput->SetTextValue(aValue); + mInput->SelectTextRange(mSearchString.Length(), aValue.Length()); + } else { + mInput->SetTextValue(mSearchString + Substring(aValue, mSearchString.Length()+findIndex, aValue.Length())); + mInput->SelectTextRange(mSearchString.Length(), -1); + + // XXX There might be a pref someday for doing it this way instead. + // The textbox value does not match the beginning of the default value, so we + // have to append the entire default value + // mInput->SetTextValue(mSearchString + NS_ConvertUTF8toUCS2(kCompleteConcatSeparator) + aValue); + // mInput->SelectTextRange(mSearchString.Length(), -1); + } + + return NS_OK; +} + +nsresult +nsAutoCompleteController::GetResultValueAt(PRInt32 aIndex, PRBool aValueOnly, nsAString & _retval) +{ + NS_ENSURE_TRUE(aIndex >= 0 && aIndex < mRowCount, NS_ERROR_ILLEGAL_VALUE); + + PRInt32 searchIndex; + PRInt32 rowIndex; + RowIndexToSearch(aIndex, &searchIndex, &rowIndex); + NS_ENSURE_TRUE(searchIndex >= 0 && rowIndex >= 0, NS_ERROR_FAILURE); + + nsCOMPtr result; + mResults->GetElementAt(searchIndex, getter_AddRefs(result)); + NS_ENSURE_TRUE(result != nsnull, NS_ERROR_FAILURE); + + PRUint16 searchResult; + result->GetSearchResult(&searchResult); + + if (searchResult == nsIAutoCompleteResult::RESULT_FAILURE) { + if (aValueOnly) + return NS_ERROR_FAILURE; + else + result->GetErrorDescription(_retval); + } else if (searchResult == nsIAutoCompleteResult::RESULT_SUCCESS) { + result->GetValueAt(rowIndex, _retval); + } + + return NS_OK; +} + +nsresult +nsAutoCompleteController::RowIndexToSearch(PRInt32 aRowIndex, PRInt32 *aSearchIndex, PRInt32 *aItemIndex) +{ + *aSearchIndex = -1; + *aItemIndex = -1; + + PRUint32 count; + mSearches->Count(&count); + PRUint32 index = 0; + for (PRUint32 i = 0; i < count; ++i) { + nsCOMPtr result; + mResults->GetElementAt(i, getter_AddRefs(result)); + if (!result) + continue; + + PRUint16 searchResult; + result->GetSearchResult(&searchResult); + + PRUint32 rowCount; + if (searchResult == nsIAutoCompleteResult::RESULT_FAILURE) { + nsAutoString error; + result->GetErrorDescription(error); + if (!error.IsEmpty()) + rowCount = 1; + } else if (searchResult == nsIAutoCompleteResult::RESULT_SUCCESS) { + result->GetMatchCount(&rowCount); + } + + if (index + rowCount-1 >= aRowIndex) { + *aSearchIndex = i; + *aItemIndex = aRowIndex - index; + return NS_OK; + } + + index += rowCount; + } + + return NS_OK; +} diff --git a/mozilla/toolkit/components/autocomplete/src/nsAutoCompleteController.h b/mozilla/toolkit/components/autocomplete/src/nsAutoCompleteController.h new file mode 100644 index 00000000000..982facdf7c7 --- /dev/null +++ b/mozilla/toolkit/components/autocomplete/src/nsAutoCompleteController.h @@ -0,0 +1,112 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Joe Hewitt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __nsAutoCompleteController__ +#define __nsAutoCompleteController__ + +#include "nsIAutoCompleteController.h" + +#include "nsIAutoCompleteInput.h" +#include "nsIAutoCompletePopup.h" +#include "nsIAutoCompleteResult.h" +#include "nsIAutoCompleteSearch.h" +#include "nsString.h" +#include "nsITreeView.h" +#include "nsITreeSelection.h" +#include "nsISupportsArray.h" +#include "nsITimer.h" + +class nsAutoCompleteController : public nsIAutoCompleteController, + public nsIAutoCompleteObserver, + public nsITimerCallback, + public nsITreeView +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIAUTOCOMPLETECONTROLLER + NS_DECL_NSIAUTOCOMPLETEOBSERVER + NS_DECL_NSITREEVIEW + NS_DECL_NSITIMERCALLBACK + + nsAutoCompleteController(); + virtual ~nsAutoCompleteController(); + +protected: + nsresult OpenPopup(); + nsresult ClosePopup(); + + nsresult StartSearch(); + nsresult StopSearch(); + + nsresult StartSearchTimer(); + nsresult ClearSearchTimer(); + + nsresult ProcessResult(PRInt32 aSearchIndex, nsIAutoCompleteResult *aResult); + nsresult PostSearchCleanup(); + + nsresult EnterMatch(); + nsresult RevertTextValue(); + + nsresult CompleteDefaultIndex(PRInt32 aSearchIndex); + nsresult CompleteValue(nsString &aValue); + nsresult GetResultValueAt(PRInt32 aIndex, PRBool aValueOnly, nsAString & _retval); + + nsresult ClearResults(); + + nsresult RowIndexToSearch(PRInt32 aRowIndex, PRInt32 *aSearchIndex, PRInt32 *aItemIndex); + + // members ////////////////////////////////////////// + + nsCOMPtr mInput; + + nsCOMPtr mSearches; + nsCOMPtr mResults; + + nsCOMPtr mTimer; + nsCOMPtr mSelection; + + nsString mSearchString; + PRPackedBool mEnterAfterSearch; + PRPackedBool mNeedToComplete; + PRPackedBool mDefaultIndexCompleted; + PRPackedBool mBackspaced; + PRUint16 mSearchStatus; + PRUint32 mRowCount; + PRUint32 mSearchesOngoing; +}; + +#endif __nsAutoCompleteController__ \ No newline at end of file diff --git a/mozilla/toolkit/components/autocomplete/src/nsAutoCompleteMdbResult.cpp b/mozilla/toolkit/components/autocomplete/src/nsAutoCompleteMdbResult.cpp new file mode 100644 index 00000000000..c90cc6a2b20 --- /dev/null +++ b/mozilla/toolkit/components/autocomplete/src/nsAutoCompleteMdbResult.cpp @@ -0,0 +1,279 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Joe Hewitt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsAutoCompleteMdbResult.h" +#include "nsCOMPtr.h" +#include "nsCRT.h" + +NS_IMPL_ISUPPORTS1(nsAutoCompleteMdbResult, nsIAutoCompleteResult) + +nsAutoCompleteMdbResult::nsAutoCompleteMdbResult() : + mDefaultIndex(-1), + mSearchResult(nsIAutoCompleteResult::RESULT_IGNORED) +{ + NS_INIT_ISUPPORTS(); +} + +nsAutoCompleteMdbResult::~nsAutoCompleteMdbResult() +{ + +} + +//////////////////////////////////////////////////////////////////////// +//// nsIAutoCompleteResult + +NS_IMETHODIMP +nsAutoCompleteMdbResult::GetSearchString(nsAString &aSearchString) +{ + aSearchString = mSearchString; + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteMdbResult::GetSearchResult(PRUint16 *aSearchResult) +{ + *aSearchResult = mSearchResult; + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteMdbResult::GetDefaultIndex(PRInt32 *aDefaultIndex) +{ + *aDefaultIndex = mDefaultIndex; + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteMdbResult::GetErrorDescription(nsAString & aErrorDescription) +{ + aErrorDescription = mErrorDescription; + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteMdbResult::GetMatchCount(PRUint32 *aMatchCount) +{ + *aMatchCount = mResults.Count(); + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteMdbResult::GetValueAt(PRInt32 aIndex, nsAString & _retval) +{ + NS_ENSURE_TRUE(aIndex >= 0 && aIndex < mResults.Count(), NS_ERROR_ILLEGAL_VALUE); + + nsIMdbRow *row = NS_STATIC_CAST(nsIMdbRow *, mResults.ElementAt(aIndex)); + if (!row) return NS_OK; + + if (mValueType == kUnicharType) { + GetRowValue(row, mValueToken, _retval); + } else if (mValueType == kCharType) { + nsCAutoString value; + GetRowValue(row, mValueToken, value); + _retval = NS_ConvertUTF8toUCS2(value); + } + + /* // TESTING: return ordinaly labeled values + char *value = new char(20); + sprintf(value, "foopy (%d)", aIndex); + + nsAutoString result; + result.AssignWithConversion(value); + _retval = result;*/ + + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteMdbResult::GetCommentAt(PRInt32 aIndex, nsAString & _retval) +{ + NS_ENSURE_TRUE(aIndex >= 0 && aIndex < mResults.Count(), NS_ERROR_ILLEGAL_VALUE); + + nsIMdbRow *row = NS_STATIC_CAST(nsIMdbRow *, mResults.ElementAt(aIndex)); + if (!row) return NS_OK; + + if (mCommentType == kUnicharType) { + GetRowValue(row, mCommentToken, _retval); + } else if (mCommentType == kCharType) { + nsCAutoString value; + GetRowValue(row, mCommentToken, value); + _retval = NS_ConvertUTF8toUCS2(value); + } + + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsAutoCompleteMdbResult::GetStyleAt(PRInt32 aIndex, nsAString & _retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +//////////////////////////////////////////////////////////////////////// +//// nsIAutoCompleteBaseResult + +NS_IMETHODIMP +nsAutoCompleteMdbResult::SetSearchString(const nsAString &aSearchString) +{ + mSearchString.Assign(aSearchString); + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteMdbResult::SetErrorDescription(const nsAString &aErrorDescription) +{ + mErrorDescription.Assign(aErrorDescription); + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteMdbResult::SetDefaultIndex(PRInt32 aDefaultIndex) +{ + mDefaultIndex = aDefaultIndex; + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteMdbResult::SetSearchResult(PRUint32 aSearchResult) +{ + mSearchResult = aSearchResult; + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +//// nsIAutoCompleteMdbResult + +NS_IMETHODIMP +nsAutoCompleteMdbResult::Init(nsIMdbEnv *aEnv, nsIMdbTable *aTable) +{ + mEnv = aEnv; + mTable = aTable; + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteMdbResult::SetTokens(mdb_scope aValueToken, eDataType aValueType, mdb_scope aCommentToken, eDataType aCommentType) +{ + mValueToken = aValueToken; + mValueType = aValueType; + mCommentToken = aCommentToken; + mCommentType = aCommentType; + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteMdbResult::AddRow(nsIMdbRow *aRow) +{ + mResults.AppendElement((void *)aRow); + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteMdbResult::RemoveRowAt(PRUint32 aRowIndex) +{ + mResults.RemoveElementAt(aRowIndex); + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteMdbResult::GetRowAt(PRUint32 aRowIndex, nsIMdbRow **aRow) +{ + *aRow = (nsIMdbRow *)mResults.ElementAt(aRowIndex); + return NS_OK; +} + +NS_IMETHODIMP +nsAutoCompleteMdbResult::GetRowValue(nsIMdbRow *aRow, mdb_column aCol, nsAString &aValue) +{ + mdbYarn yarn; + mdb_err err = aRow->AliasCellYarn(mEnv, aCol, &yarn); + if (err != 0) + return NS_ERROR_FAILURE; + + aValue.Truncate(0); + if (!yarn.mYarn_Fill) + return NS_OK; + + switch (yarn.mYarn_Form) { + case 0: // unicode + aValue.Assign((const PRUnichar *)yarn.mYarn_Buf, yarn.mYarn_Fill/sizeof(PRUnichar)); + break; + case 1: // utf 8 + aValue.Assign(NS_ConvertUTF8toUCS2((const char*)yarn.mYarn_Buf, yarn.mYarn_Fill)); + break; + default: + return NS_ERROR_UNEXPECTED; + } + + return NS_OK; +} + + +nsresult +nsAutoCompleteMdbResult::GetRowValue(nsIMdbRow *aRow, mdb_column aCol, nsACString& aValue) +{ + mdb_err err; + + mdbYarn yarn; + err = aRow->AliasCellYarn(mEnv, aCol, &yarn); + if (err != 0) return NS_ERROR_FAILURE; + + const char* startPtr = (const char*)yarn.mYarn_Buf; + if (startPtr) + aValue.Assign(Substring(startPtr, startPtr + yarn.mYarn_Fill)); + else + aValue.Truncate(); + + return NS_OK; +} + +nsresult +nsAutoCompleteMdbResult::GetRowValue(nsIMdbRow *aRow, mdb_column aCol, PRInt32 *aValue) +{ + mdb_err err; + + mdbYarn yarn; + err = aRow->AliasCellYarn(mEnv, aCol, &yarn); + if (err != 0) return NS_ERROR_FAILURE; + + if (yarn.mYarn_Buf) + *aValue = atoi((char *)yarn.mYarn_Buf); + else + *aValue = 0; + + return NS_OK; +} diff --git a/mozilla/toolkit/components/autocomplete/src/nsAutoCompleteMdbResult.h b/mozilla/toolkit/components/autocomplete/src/nsAutoCompleteMdbResult.h new file mode 100644 index 00000000000..b06ccdf754b --- /dev/null +++ b/mozilla/toolkit/components/autocomplete/src/nsAutoCompleteMdbResult.h @@ -0,0 +1,89 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Joe Hewitt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __nsAutoCompleteResultBase__ +#define __nsAutoCompleteResultBase__ + +#include "nsIAutoCompleteResult.h" +#include "nsIAutoCompleteResultTypes.h" +#include "nsString.h" +#include "nsVoidArray.h" +#include "mdb.h" + +class nsAutoCompleteMdbResult : public nsIAutoCompleteMdbResult +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIAUTOCOMPLETERESULT + + nsAutoCompleteMdbResult(); + virtual ~nsAutoCompleteMdbResult(); + + // nsIAutoCompleteBaseResult + NS_IMETHOD SetSearchString(const nsAString &aSearchString); + NS_IMETHOD SetErrorDescription(const nsAString &aErrorDescription); + NS_IMETHOD SetDefaultIndex(PRInt32 aDefaultIndex); + NS_IMETHOD SetSearchResult(PRUint32 aSearchResult); + + // nsIAutoCompleteMdbResult + NS_IMETHOD Init(nsIMdbEnv *aEnv, nsIMdbTable *aTable); + NS_IMETHOD SetTokens(mdb_scope aValueToken, eDataType aValueType, mdb_scope aCommentToken, eDataType aCommentType); + NS_IMETHOD AddRow(nsIMdbRow *aRow); + NS_IMETHOD RemoveRowAt(PRUint32 aRowIndex); + NS_IMETHOD GetRowAt(PRUint32 aRowIndex, nsIMdbRow **aRow); + NS_IMETHOD GetRowValue(nsIMdbRow *aRow, mdb_column aCol, nsAString &aValue); + NS_IMETHOD GetRowValue(nsIMdbRow *aRow, mdb_column aCol, nsACString &aValue); + NS_IMETHOD GetRowValue(nsIMdbRow *aRow, mdb_column aCol, PRInt32 *aValue); + +protected: + nsAutoVoidArray mResults; + + nsAutoString mSearchString; + nsAutoString mErrorDescription; + PRInt32 mDefaultIndex; + PRUint32 mSearchResult; + + nsIMdbEnv *mEnv; + nsIMdbTable *mTable; + + mdb_scope mValueToken; + eDataType mValueType; + mdb_scope mCommentToken; + eDataType mCommentType; +}; + +#endif // __nsAutoCompleteResultBase__ diff --git a/mozilla/toolkit/components/build/Makefile.in b/mozilla/toolkit/components/build/Makefile.in new file mode 100644 index 00000000000..691d2add9e7 --- /dev/null +++ b/mozilla/toolkit/components/build/Makefile.in @@ -0,0 +1,66 @@ +# +# The contents of this file are subject to the Netscape Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/NPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# + +DEPTH=../../.. +topsrcdir=@top_srcdir@ +srcdir=@srcdir@ +VPATH=@srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = toolkitcomps +LIBRARY_NAME = toolkitcomps +EXPORT_LIBRARY = 1 +FORCE_SHARED_LIB = 1 +IS_COMPONENT = 1 + +REQUIRES = xpcom \ + string \ + layout \ + dom \ + mork \ + docshell \ + $(NULL) + +EXPORTS = nsToolkitCompsCID.h + +CPPSRCS = nsModule.cpp \ + $(NULL) + +LOCAL_INCLUDES = \ + -I$(srcdir)/../autocomplete/src \ + -I$(srcdir)/../satchel/src \ + +SHARED_LIBRARY_LIBS = \ + $(DIST)/lib/$(LIB_PREFIX)autocomplete_s.$(LIB_SUFFIX) \ + $(DIST)/lib/$(LIB_PREFIX)satchel_s.$(LIB_SUFFIX) \ + $(NULL) + +EXTRA_DSO_LIBS = gkgfx + +EXTRA_DSO_LDOPTS += \ + $(EXTRA_DSO_LIBS) \ + $(MOZ_UNICHARUTIL_LIBS) \ + $(MOZ_COMPONENT_LIBS) \ + $(MOZ_JS_LIBS) \ + $(NULL) + +include $(topsrcdir)/config/rules.mk diff --git a/mozilla/toolkit/components/build/nsModule.cpp b/mozilla/toolkit/components/build/nsModule.cpp new file mode 100644 index 00000000000..e39ef5f454f --- /dev/null +++ b/mozilla/toolkit/components/build/nsModule.cpp @@ -0,0 +1,91 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Joe Hewitt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsIGenericFactory.h" + +#include "nsToolkitCompsCID.h" +#include "nsAutoCompleteController.h" +#include "nsAutoCompleteMdbResult.h" +#include "nsFormHistory.h" +#include "nsFormFillController.h" + +///////////////////////////////////////////////////////////////////////////// + +NS_GENERIC_FACTORY_CONSTRUCTOR(nsAutoCompleteController) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsAutoCompleteMdbResult) +NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsFormHistory, nsFormHistory::GetInstance); +NS_GENERIC_FACTORY_CONSTRUCTOR(nsFormFillController) + +///////////////////////////////////////////////////////////////////////////// +//// Module Destructor + +static void PR_CALLBACK nsToolkitCompModuleDtor(nsIModule* self) +{ + nsFormHistory::ReleaseInstance(); +} + +///////////////////////////////////////////////////////////////////////////// + +static const nsModuleComponentInfo components[] = +{ + { "AutoComplete Controller", + NS_AUTOCOMPLETECONTROLLER_CID, + NS_AUTOCOMPLETECONTROLLER_CONTRACTID, + nsAutoCompleteControllerConstructor }, + + { "AutoComplete Mdb Result", + NS_AUTOCOMPLETEMDBRESULT_CID, + NS_AUTOCOMPLETEMDBRESULT_CONTRACTID, + nsAutoCompleteMdbResultConstructor }, + + { "HTML Form History", + NS_FORMHISTORY_CID, + NS_FORMHISTORY_CONTRACTID, + nsFormHistoryConstructor }, + + { "HTML Form Fill Controller", + NS_FORMFILLCONTROLLER_CID, + "@mozilla.org/satchel/form-fill-controller;1", + nsFormFillControllerConstructor }, + + { "HTML Form History AutoComplete", + NS_FORMFILLCONTROLLER_CID, + NS_FORMHISTORYAUTOCOMPLETE_CONTRACTID, + nsFormFillControllerConstructor } +}; + +NS_IMPL_NSGETMODULE_WITH_DTOR(nsToolkitCompsModule, components, nsToolkitCompModuleDtor) diff --git a/mozilla/toolkit/components/build/nsToolkitCompsCID.h b/mozilla/toolkit/components/build/nsToolkitCompsCID.h new file mode 100644 index 00000000000..09361de6911 --- /dev/null +++ b/mozilla/toolkit/components/build/nsToolkitCompsCID.h @@ -0,0 +1,69 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Joe Hewitt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#define NS_AUTOCOMPLETECONTROLLER_CONTRACTID \ + "@mozilla.org/autocomplete/controller;1" + +#define NS_AUTOCOMPLETEMDBRESULT_CONTRACTID \ + "@mozilla.org/autocomplete/mdb-result;1" + +#define NS_FORMHISTORY_CONTRACTID \ + "@mozilla.org/satchel/form-history;1" + +#define NS_FORMFILLCONTROLLER_CONTRACTID \ + "@mozilla.org/satchel/form-fill-controller;1" + +#define NS_FORMHISTORYAUTOCOMPLETE_CONTRACTID \ + "@mozilla.org/autocomplete/search;1?name=form-history" + +///////////////////////////////////////////////////////////////////////////// + +// {F6D5EBBD-34F4-487d-9D10-3D34123E3EB9} +#define NS_AUTOCOMPLETECONTROLLER_CID \ +{ 0xf6d5ebbd, 0x34f4, 0x487d, { 0x9d, 0x10, 0x3d, 0x34, 0x12, 0x3e, 0x3e, 0xb9 } } + +// {7A6F70B6-2BBD-44b5-9304-501352D44AB5} +#define NS_AUTOCOMPLETEMDBRESULT_CID \ +{ 0x7a6f70b6, 0x2bbd, 0x44b5, { 0x93, 0x4, 0x50, 0x13, 0x52, 0xd4, 0x4a, 0xb5 } } + +// {895DB6C7-DBDF-40ea-9F64-B175033243DC} +#define NS_FORMFILLCONTROLLER_CID \ +{ 0x895db6c7, 0xdbdf, 0x40ea, { 0x9f, 0x64, 0xb1, 0x75, 0x3, 0x32, 0x43, 0xdc } } + +// {A2059C0E-5A58-4c55-AB7C-26F0557546EF} +#define NS_FORMHISTORY_CID \ +{ 0xa2059c0e, 0x5a58, 0x4c55, { 0xab, 0x7c, 0x26, 0xf0, 0x55, 0x75, 0x46, 0xef } } diff --git a/mozilla/toolkit/components/satchel/Makefile.in b/mozilla/toolkit/components/satchel/Makefile.in new file mode 100644 index 00000000000..7c7decc23c4 --- /dev/null +++ b/mozilla/toolkit/components/satchel/Makefile.in @@ -0,0 +1,10 @@ +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +DIRS = public src + +include $(topsrcdir)/config/rules.mk diff --git a/mozilla/toolkit/components/satchel/public/Makefile.in b/mozilla/toolkit/components/satchel/public/Makefile.in new file mode 100644 index 00000000000..2cb7e74b374 --- /dev/null +++ b/mozilla/toolkit/components/satchel/public/Makefile.in @@ -0,0 +1,35 @@ +# +# The contents of this file are subject to the Netscape Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/NPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# Joe Hewitt (Original Author) +# + +DEPTH=../../../.. +topsrcdir=@top_srcdir@ +srcdir=@srcdir@ +VPATH=@srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = toolkitcomps +XPIDL_MODULE = satchel + +XPIDLSRCS = nsIFormFillController.idl \ + nsIFormHistory.idl \ + $(NULL) + +include $(topsrcdir)/config/rules.mk diff --git a/mozilla/toolkit/components/satchel/public/nsIFormFillController.idl b/mozilla/toolkit/components/satchel/public/nsIFormFillController.idl new file mode 100644 index 00000000000..cb5dffd53e8 --- /dev/null +++ b/mozilla/toolkit/components/satchel/public/nsIFormFillController.idl @@ -0,0 +1,69 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Joe Hewitt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +interface nsIDocShell; +interface nsIAutoCompletePopup; + +/* + * nsIFormFillController is an interface for controlling form fill behavior + * on HTML documents. Any number of docShells can be controller concurrently. + * While a docShell is attached, all HTML documents that are loaded within it + * will have a focus listener attached that will listen for when a text input + * is focused. When this happens, the input will be bound to the + * global nsIAutoCompleteController service. + */ + +[scriptable, uuid(872F07F3-ED11-47c6-B7CF-246DB53379FB)] +interface nsIFormFillController : nsISupports +{ + /* + * Start controlling form fill behavior for the given browser + * + * @param docShell - The docShell to attach to + * @param popup - The popup to show when autocomplete results are available + */ + void attachToBrowser(in nsIDocShell docShell, in nsIAutoCompletePopup popup); + + /* + * Stop controlling form fill behavior for the given browser + * + * @param docShell - The docShell to detach from + */ + void detachFromBrowser(in nsIDocShell docShell); +}; diff --git a/mozilla/toolkit/components/satchel/public/nsIFormHistory.idl b/mozilla/toolkit/components/satchel/public/nsIFormHistory.idl new file mode 100644 index 00000000000..e4b2d1635db --- /dev/null +++ b/mozilla/toolkit/components/satchel/public/nsIFormHistory.idl @@ -0,0 +1,87 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Joe Hewitt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +[scriptable, uuid(48E227EC-1897-418f-A40B-C15EA18BBC4A)] +interface nsIFormHistory : nsISupports +{ + /** + * The total number of rows in the form history. + */ + readonly attribute unsigned long rowCount; + + /** + * Gets the name and value at a position in the form history. + */ + void getEntryAt(in unsigned long index, out AString name, out AString value); + + /** + * Gets just the name at a position in the form history. + */ + void getNameAt(in unsigned long index, out AString name); + + /** + * Gets just the value at a position in the form history. + */ + void getValueAt(in unsigned long index, out AString value); + + /** + * Appends a name and value pair to the end of the form history. + */ + void addEntry(in AString name, in AString value); + + /** + * Removes the entry at a position. + */ + void removeEntryAt(in unsigned long index); + + /** + * Removes all entries that are paired with a name. + */ + void removeEntriesForName(in AString name); + + /** + * Removes all entries in the entire form history. + */ + void removeAllEntries(); + + /** + * Gets whether a name and value pair exists in the form history. + */ + boolean entryExists(in AString name, in AString value); +}; diff --git a/mozilla/toolkit/components/satchel/src/Makefile.in b/mozilla/toolkit/components/satchel/src/Makefile.in new file mode 100644 index 00000000000..5252cc5acd6 --- /dev/null +++ b/mozilla/toolkit/components/satchel/src/Makefile.in @@ -0,0 +1,53 @@ +# +# The contents of this file are subject to the Netscape Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/NPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# Joe Hewitt (Original Author) +# + +DEPTH=../../../.. +topsrcdir=@top_srcdir@ +srcdir=@srcdir@ +VPATH=@srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = toolkitcomps +LIBRARY_NAME = satchel_s +FORCE_STATIC_LIB = 1 + +REQUIRES = xpcom \ + string \ + autocomplete \ + uriloader \ + dom \ + layout \ + docshell \ + gfx \ + necko \ + widget \ + content \ + view \ + locale \ + mork \ + unicharutil \ + $(NULL) + +CPPSRCS = nsFormFillController.cpp \ + nsFormHistory.cpp \ + $(NULL) + +include $(topsrcdir)/config/rules.mk diff --git a/mozilla/toolkit/components/satchel/src/nsFormFillController.cpp b/mozilla/toolkit/components/satchel/src/nsFormFillController.cpp new file mode 100644 index 00000000000..a74da01e105 --- /dev/null +++ b/mozilla/toolkit/components/satchel/src/nsFormFillController.cpp @@ -0,0 +1,697 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Joe Hewitt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsFormFillController.h" + +#include "nsFormFillResult.h" +#include "nsFormHistory.h" +#include "nsIAutoCompleteResultTypes.h" +#include "nsString.h" +#include "nsReadableUtils.h" +#include "nsIServiceManager.h" +#include "nsIInterfaceRequestor.h" +#include "nsIDocShellTreeItem.h" +#include "nsIChromeEventHandler.h" +#include "nsPIDOMWindow.h" +#include "nsIWebNavigation.h" +#include "nsIContentViewer.h" +#include "nsIDOMEventTarget.h" +#include "nsIDOMKeyEvent.h" +#include "nsIDOMDocument.h" +#include "nsIDOMElement.h" +#include "nsIDOMNSHTMLInputElement.h" +#include "nsIScriptGlobalObject.h" +#include "nsIContent.h" +#include "nsIPresShell.h" +#include "nsIPresContext.h" +#include "nsIView.h" +#include "nsIFrame.h" +#include "nsIWidget.h" +#include "nsRect.h" + +NS_INTERFACE_MAP_BEGIN(nsFormFillController) + NS_INTERFACE_MAP_ENTRY(nsIFormFillController) + NS_INTERFACE_MAP_ENTRY(nsIAutoCompleteInput) + NS_INTERFACE_MAP_ENTRY(nsIAutoCompleteSearch) + NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener) + NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIFormFillController) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMFocusListener) +NS_INTERFACE_MAP_END + +NS_IMPL_ADDREF(nsFormFillController); +NS_IMPL_RELEASE(nsFormFillController); + +nsFormFillController::nsFormFillController() : + mTimeout(50), + mMinResultsForPopup(1), + mDisableAutoComplete(PR_FALSE), + mCompleteDefaultIndex(PR_FALSE), + mForceComplete(PR_FALSE) +{ + NS_INIT_ISUPPORTS(); + + mController = do_GetService("@mozilla.org/autocomplete/controller;1"); + + mDocShells = do_CreateInstance("@mozilla.org/supports-array;1"); + mPopups = do_CreateInstance("@mozilla.org/supports-array;1"); +} + +nsFormFillController::~nsFormFillController() +{ + // Remove ourselves as a focus listener from all cached docShells + PRUint32 count; + mDocShells->Count(&count); + for (PRUint32 i = 0; i < count; ++i) { + nsCOMPtr docShell; + mDocShells->GetElementAt(i, getter_AddRefs(docShell)); + nsCOMPtr domWindow = GetWindowForDocShell(docShell); + RemoveFocusListener(domWindow); + } +} + +//////////////////////////////////////////////////////////////////////// + +nsRect& +GetScreenOrigin(nsIDOMElement* aElement) +{ + nsRect* rect = new nsRect(0,0,0,0); + nsSize size; + + nsCOMPtr content = do_QueryInterface(aElement); + nsCOMPtr doc; + content->GetDocument(*getter_AddRefs(doc)); + + if (doc) { + // Get Presentation shell 0 + nsCOMPtr presShell; + doc->GetShellAt(0, getter_AddRefs(presShell)); + + if (presShell) { + nsCOMPtr presContext; + presShell->GetPresContext(getter_AddRefs(presContext)); + + if (presContext) { + // Get the scale from that Presentation Context + float scale; + presContext->GetTwipsToPixels(&scale); + + nsIFrame* frame; + nsresult rv = presShell->GetPrimaryFrameFor(content, &frame); + + nsIView* view; + nsPoint offset; + frame->GetOffsetFromView(presContext, offset, &view); + if (view) { + nscoord dummy; + nsCOMPtr widget; + rv = view->GetOffsetFromWidget(&dummy, &dummy, *getter_AddRefs(widget)); + if (widget) { + nsRect oldBox(0,0,0,0); + widget->WidgetToScreen(oldBox, *rect); + } + + nscoord viewX = 0, viewY = 0; + view->GetPosition(&viewX, &viewY); + + rect->x += NSTwipsToIntPixels(offset.x+viewX, scale); + rect->y += NSTwipsToIntPixels(offset.y+viewY, scale); + } + + frame->GetSize(size); + rect->width = NSTwipsToIntPixels(size.width, scale); + rect->height = NSTwipsToIntPixels(size.height, scale); + } + } + } + + return *rect; +} + +//////////////////////////////////////////////////////////////////////// +//// nsIFormFillController + +NS_IMETHODIMP +nsFormFillController::AttachToBrowser(nsIDocShell *aDocShell, nsIAutoCompletePopup *aPopup) +{ + NS_ENSURE_TRUE(aDocShell && aPopup, NS_ERROR_ILLEGAL_VALUE); + + mDocShells->AppendElement(aDocShell); + mPopups->AppendElement(aPopup); + + printf("AttachToBrowser\n"); + + // Listen for focus events on the domWindow of the docShell + nsCOMPtr domWindow = GetWindowForDocShell(aDocShell); + AddFocusListener(domWindow); + + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::DetachFromBrowser(nsIDocShell *aDocShell) +{ + PRInt32 index = GetIndexOfDocShell(aDocShell); + NS_ENSURE_TRUE(index >= 0, NS_ERROR_FAILURE); + + // Stop listening for focus events on the domWindow of the docShell + nsCOMPtr docShell; + mDocShells->GetElementAt(index, getter_AddRefs(docShell)); + nsCOMPtr domWindow = GetWindowForDocShell(docShell); + RemoveFocusListener(domWindow); + + mDocShells->RemoveElementAt(index); + mPopups->RemoveElementAt(index); + + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +//// nsIAutoCompleteInput + +NS_IMETHODIMP +nsFormFillController::GetPopup(nsIAutoCompletePopup **aPopup) +{ + *aPopup = mFocusedPopup; + NS_IF_ADDREF(*aPopup); + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::GetPopupOpen(PRBool *aPopupOpen) +{ + if (mFocusedPopup) + mFocusedPopup->GetPopupOpen(aPopupOpen); + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::SetPopupOpen(PRBool aPopupOpen) +{ + if (aPopupOpen) { + nsRect popupRect = GetScreenOrigin(mFocusedInput); + if (mFocusedPopup) + mFocusedPopup->OpenPopup(this, popupRect.x, popupRect.y+popupRect.height, popupRect.width); + } else { + mFocusedPopup->ClosePopup(); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::GetDisableAutoComplete(PRBool *aDisableAutoComplete) +{ + *aDisableAutoComplete = mDisableAutoComplete; + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::SetDisableAutoComplete(PRBool aDisableAutoComplete) +{ + mDisableAutoComplete = aDisableAutoComplete; + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::GetCompleteDefaultIndex(PRBool *aCompleteDefaultIndex) +{ + *aCompleteDefaultIndex = mCompleteDefaultIndex; + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::SetCompleteDefaultIndex(PRBool aCompleteDefaultIndex) +{ + mCompleteDefaultIndex = aCompleteDefaultIndex; + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::GetForceComplete(PRBool *aForceComplete) +{ + *aForceComplete = mForceComplete; + return NS_OK; +} + +NS_IMETHODIMP nsFormFillController::SetForceComplete(PRBool aForceComplete) +{ + mForceComplete = aForceComplete; + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::GetMinResultsForPopup(PRUint32 *aMinResultsForPopup) +{ + *aMinResultsForPopup = mMinResultsForPopup; + return NS_OK; +} + +NS_IMETHODIMP nsFormFillController::SetMinResultsForPopup(PRUint32 aMinResultsForPopup) +{ + mMinResultsForPopup = aMinResultsForPopup; + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::GetShowCommentColumn(PRUint32 *aShowCommentColumn) +{ + *aShowCommentColumn = PR_FALSE; + return NS_OK; +} + +NS_IMETHODIMP nsFormFillController::SetShowCommentColumn(PRUint32 aShowCommentColumn) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsFormFillController::GetTimeout(PRUint32 *aTimeout) +{ + *aTimeout = mTimeout; + return NS_OK; +} + +NS_IMETHODIMP nsFormFillController::SetTimeout(PRUint32 aTimeout) +{ + mTimeout = aTimeout; + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::SetSearchParam(const nsAString &aSearchParam) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsFormFillController::GetSearchParam(nsAString &aSearchParam) +{ + mFocusedInput->GetName(aSearchParam); + if (aSearchParam.IsEmpty()) + mFocusedInput->GetId(aSearchParam); + + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::GetSearchCount(PRUint32 *aSearchCount) +{ + *aSearchCount = 1; + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::GetSearchAt(PRUint32 index, nsACString & _retval) +{ + _retval.Assign("form-history"); + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::GetTextValue(nsAString & aTextValue) +{ + mFocusedInput->GetValue(aTextValue); + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::SetTextValue(const nsAString & aTextValue) +{ + mFocusedInput->SetValue(aTextValue); + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::GetSelectionStart(PRInt32 *aSelectionStart) +{ + nsCOMPtr input = do_QueryInterface(mFocusedInput); + if (input) + input->GetSelectionStart(aSelectionStart); + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::GetSelectionEnd(PRInt32 *aSelectionEnd) +{ + nsCOMPtr input = do_QueryInterface(mFocusedInput); + if (input) + input->GetSelectionEnd(aSelectionEnd); + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::SelectTextRange(PRInt32 aStartIndex, PRInt32 aEndIndex) +{ + nsCOMPtr input = do_QueryInterface(mFocusedInput); + if (input) + input->SetSelectionRange(aStartIndex, aEndIndex); + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::OnSearchComplete() +{ + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::OnTextEntered(PRBool *_retval) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::OnTextReverted(PRBool *_retval) +{ + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +//// nsIAutoCompleteSearch + + +NS_IMETHODIMP +nsFormFillController::StartSearch(const nsAString &aSearchString, const nsAString &aSearchParam, + nsIAutoCompleteResult *aPreviousResult, nsIAutoCompleteObserver *aListener) +{ + nsFormHistory *history = nsFormHistory::GetInstance(); + + nsIAutoCompleteMdbResult *result = nsnull; + history->AutoCompleteSearch(aSearchParam, aSearchString, NS_STATIC_CAST(nsIAutoCompleteMdbResult *, aPreviousResult), &result); + + NS_IF_RELEASE(history); + + aListener->OnSearchResult(this, result); + + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::StopSearch() +{ + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +//// nsIDOMEventListener + +NS_IMETHODIMP +nsFormFillController::HandleEvent(nsIDOMEvent* aEvent) +{ + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +//// nsIDOMFocusListener + +NS_IMETHODIMP +nsFormFillController::Focus(nsIDOMEvent* aEvent) +{ + nsCOMPtr target; + aEvent->GetTarget(getter_AddRefs(target)); + + nsCOMPtr input = do_QueryInterface(target); + if (input) { + nsAutoString type; + input->GetType(type); + if (type.Equals(NS_LITERAL_STRING("text"))) + StartControllingInput(input); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::Blur(nsIDOMEvent* aEvent) +{ + if (mFocusedInput) + StopControllingInput(); + + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +//// nsIDOMKeyListener + +NS_IMETHODIMP +nsFormFillController::KeyDown(nsIDOMEvent* aEvent) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::KeyUp(nsIDOMEvent* aEvent) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::KeyPress(nsIDOMEvent* aEvent) +{ + nsCOMPtr keyEvent = do_QueryInterface(aEvent); + + PRBool cancel = PR_FALSE; + + PRUint32 c; + keyEvent->GetCharCode(&c); + + if (c) { + mController->HandleText(); + } else { + PRUint32 k; + keyEvent->GetKeyCode(&k); + switch (k) { + case nsIDOMKeyEvent::DOM_VK_BACK_SPACE: + case nsIDOMKeyEvent::DOM_VK_DELETE: + mController->HandleText(); + break; + case nsIDOMKeyEvent::DOM_VK_UP: + mController->HandleKeyNavigation(nsIAutoCompleteController::KEY_UP, &cancel); + break; + case nsIDOMKeyEvent::DOM_VK_DOWN: + mController->HandleKeyNavigation(nsIAutoCompleteController::KEY_DOWN, &cancel); + break; + case nsIDOMKeyEvent::DOM_VK_LEFT: + mController->HandleKeyNavigation(nsIAutoCompleteController::KEY_LEFT, &cancel); + break; + case nsIDOMKeyEvent::DOM_VK_RIGHT: + mController->HandleKeyNavigation(nsIAutoCompleteController::KEY_RIGHT, &cancel); + break; + case nsIDOMKeyEvent::DOM_VK_PAGE_UP: + mController->HandleKeyNavigation(nsIAutoCompleteController::KEY_PAGE_UP, &cancel); + break; + case nsIDOMKeyEvent::DOM_VK_PAGE_DOWN: + mController->HandleKeyNavigation(nsIAutoCompleteController::KEY_PAGE_DOWN, &cancel); + break; + case nsIDOMKeyEvent::DOM_VK_ESCAPE: + mController->HandleEscape(&cancel); + break; + case nsIDOMKeyEvent::DOM_VK_RETURN: + mController->HandleEnter(&cancel); + break; + } + } + + if (cancel) { + aEvent->StopPropagation(); + aEvent->PreventDefault(); + } + + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +//// nsFormFillController + +void +nsFormFillController::AddFocusListener(nsIDOMWindow *aWindow) +{ + if (!aWindow) + return; + + nsCOMPtr privateDOMWindow(do_QueryInterface(aWindow)); + nsCOMPtr chromeEventHandler; + if (privateDOMWindow) + privateDOMWindow->GetChromeEventHandler(getter_AddRefs(chromeEventHandler)); + nsCOMPtr target(do_QueryInterface(chromeEventHandler)); + + if (target) + target->AddEventListener(NS_LITERAL_STRING("focus"), + NS_STATIC_CAST(nsIDOMFocusListener *, this), + PR_TRUE); +} + +void +nsFormFillController::RemoveFocusListener(nsIDOMWindow *aWindow) +{ + StopControllingInput(); + + nsCOMPtr privateDOMWindow(do_QueryInterface(aWindow)); + nsCOMPtr chromeEventHandler; + if (privateDOMWindow) + privateDOMWindow->GetChromeEventHandler(getter_AddRefs(chromeEventHandler)); + nsCOMPtr target(do_QueryInterface(chromeEventHandler)); + + target->RemoveEventListener(NS_LITERAL_STRING("focus"), + NS_STATIC_CAST(nsIDOMFocusListener *, this), + PR_TRUE); +} + +void +nsFormFillController::AddKeyListener(nsIDOMHTMLInputElement *aInput) +{ + if (aInput) { + mFocusedInput = aInput; + + nsCOMPtr target = do_QueryInterface(aInput); + target->AddEventListener(NS_LITERAL_STRING("keypress"), + NS_STATIC_CAST(nsIDOMKeyListener *, this), + PR_TRUE); + } +} + +void +nsFormFillController::RemoveKeyListener() +{ + if (mFocusedInput) { + nsCOMPtr target = do_QueryInterface(mFocusedInput); + target->RemoveEventListener(NS_LITERAL_STRING("keypress"), + NS_STATIC_CAST(nsIDOMKeyListener *, this), + PR_TRUE); + + mFocusedInput = nsnull; + } +} + +void +nsFormFillController::StartControllingInput(nsIDOMHTMLInputElement *aInput) +{ + // Make sure we're not still attached to an input + StopControllingInput(); + + // Find the currently focused docShell + nsCOMPtr docShell = GetDocShellForInput(aInput); + PRInt32 index = GetIndexOfDocShell(docShell); + if (index < 0) + return; + + // Cache the popup for the focused docShell + mPopups->GetElementAt(index, getter_AddRefs(mFocusedPopup)); + + // Start listening for key events + AddKeyListener(aInput); + + // Now we are the autocomplete controller's bitch + mController->AttachToInput(this); +} + +void +nsFormFillController::StopControllingInput() +{ + RemoveKeyListener(); + + mController->DetachFromInput(); + + mFocusedInput = nsnull; + mFocusedPopup = nsnull; +} + +nsIDocShell * +nsFormFillController::GetDocShellForInput(nsIDOMHTMLInputElement *aInput) +{ + nsCOMPtr domDoc; + aInput->GetOwnerDocument(getter_AddRefs(domDoc)); + nsCOMPtr doc = do_QueryInterface(domDoc); + + nsCOMPtr ourGlobal; + doc->GetScriptGlobalObject(getter_AddRefs(ourGlobal)); + nsCOMPtr domWindow = do_QueryInterface(ourGlobal); + + nsCOMPtr ifreq(do_QueryInterface(domWindow)); + NS_ENSURE_TRUE(ifreq, NS_OK); + nsCOMPtr webNav; + ifreq->GetInterface(NS_GET_IID(nsIWebNavigation), getter_AddRefs(webNav)); + nsCOMPtr docShell = do_QueryInterface(webNav); + return docShell; +} + +nsIDOMWindow * +nsFormFillController::GetWindowForDocShell(nsIDocShell *aDocShell) +{ + nsCOMPtr contentViewer; + aDocShell->GetContentViewer(getter_AddRefs(contentViewer)); + NS_ENSURE_TRUE(contentViewer, nsnull); + + nsCOMPtr domDoc; + contentViewer->GetDOMDocument(getter_AddRefs(domDoc)); + nsCOMPtr doc = do_QueryInterface(domDoc); + NS_ENSURE_TRUE(doc, nsnull); + + nsCOMPtr global; + doc->GetScriptGlobalObject(getter_AddRefs(global)); + NS_ENSURE_TRUE(global, nsnull); + + nsCOMPtr domWindow = do_QueryInterface(global); + return domWindow; +} + +PRInt32 +nsFormFillController::GetIndexOfDocShell(nsIDocShell *aDocShell) +{ + // Loop through our cached docShells looking for the given docShell + PRUint32 count; + mDocShells->Count(&count); + for (PRUint32 i = 0; i < count; ++i) { + nsCOMPtr docShell; + mDocShells->GetElementAt(i, getter_AddRefs(docShell)); + if (docShell == aDocShell) + return i; + } + + // Recursively check the parent docShell of this one + nsCOMPtr treeItem = do_QueryInterface(aDocShell); + nsCOMPtr parentItem; + treeItem->GetParent(getter_AddRefs(parentItem)); + if (parentItem) { + nsCOMPtr parentShell = do_QueryInterface(parentItem); + return GetIndexOfDocShell(parentShell); + } + + return -1; +} + diff --git a/mozilla/toolkit/components/satchel/src/nsFormFillController.h b/mozilla/toolkit/components/satchel/src/nsFormFillController.h new file mode 100644 index 00000000000..505c424add9 --- /dev/null +++ b/mozilla/toolkit/components/satchel/src/nsFormFillController.h @@ -0,0 +1,114 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Joe Hewitt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __nsFormFillController__ +#define __nsFormFillController__ + +#include "nsIFormFillController.h" +#include "nsIAutoCompleteInput.h" +#include "nsIAutoCompleteSearch.h" +#include "nsIAutoCompleteController.h" +#include "nsIAutoCompletePopup.h" +#include "nsIDOMFocusListener.h" +#include "nsIDOMKeyListener.h" +#include "nsCOMPtr.h" +#include "nsISupportsArray.h" +#include "nsIDocShell.h" +#include "nsIDOMWindow.h" +#include "nsIDOMHTMLInputElement.h" +#include "nsFormHistory.h" + +class nsFormFillController : public nsIFormFillController, + public nsIAutoCompleteInput, + public nsIAutoCompleteSearch, + public nsIDOMFocusListener, + public nsIDOMKeyListener +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIFORMFILLCONTROLLER + NS_DECL_NSIAUTOCOMPLETESEARCH + NS_DECL_NSIAUTOCOMPLETEINPUT + + // nsIDOMEventListener + NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent); + + // nsIDOMFocusListener + NS_IMETHOD Focus(nsIDOMEvent* aEvent); + NS_IMETHOD Blur(nsIDOMEvent* aEvent); + + // nsIDOMKeyListener + NS_IMETHOD KeyDown(nsIDOMEvent* aKeyEvent); + NS_IMETHOD KeyUp(nsIDOMEvent* aKeyEvent); + NS_IMETHOD KeyPress(nsIDOMEvent* aKeyEvent); + + nsFormFillController(); + virtual ~nsFormFillController(); + +protected: + void AddFocusListener(nsIDOMWindow *aWindow); + void RemoveFocusListener(nsIDOMWindow *aWindow); + + void AddKeyListener(nsIDOMHTMLInputElement *aInput); + void RemoveKeyListener(); + + void StartControllingInput(nsIDOMHTMLInputElement *aInput); + void StopControllingInput(); + + PRBool RowMatch(nsFormHistory *aHistory, PRUint32 aIndex, const nsAString &aInputName, const nsAString &aInputValue); + + inline nsIDocShell *GetDocShellForInput(nsIDOMHTMLInputElement *aInput); + inline nsIDOMWindow *GetWindowForDocShell(nsIDocShell *aDocShell); + inline PRInt32 GetIndexOfDocShell(nsIDocShell *aDocShell); + + // members ////////////////////////////////////////// + + nsCOMPtr mController; + nsCOMPtr mFocusedInput; + nsCOMPtr mFocusedPopup; + + nsCOMPtr mDocShells; + nsCOMPtr mPopups; + + PRUint32 mTimeout; + PRUint32 mMinResultsForPopup; + PRPackedBool mDisableAutoComplete; + PRPackedBool mCompleteDefaultIndex; + PRPackedBool mForceComplete; +}; + +#endif // __nsFormFillController__ diff --git a/mozilla/toolkit/components/satchel/src/nsFormHistory.cpp b/mozilla/toolkit/components/satchel/src/nsFormHistory.cpp new file mode 100644 index 00000000000..edc17ba5351 --- /dev/null +++ b/mozilla/toolkit/components/satchel/src/nsFormHistory.cpp @@ -0,0 +1,721 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Joe Hewitt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsFormHistory.h" + +#include "nsIServiceManager.h" +#include "nsIObserverService.h" +#include "nsICategoryManager.h" +#include "nsIDirectoryService.h" +#include "nsAppDirectoryServiceDefs.h" +#include "nsMorkCID.h" +#include "nsIMDBFactoryFactory.h" +#include "nsQuickSort.h" +#include "nsCRT.h" +#include "nsString.h" +#include "nsUnicharUtils.h" +#include "nsReadableUtils.h" +#include "nsIContent.h" +#include "nsIDOMNode.h" +#include "nsIDOMHTMLFormElement.h" +#include "nsIDOMHTMLInputElement.h" +#include "nsIDOMHTMLCollection.h" + +static const char *kFormHistoryFileName = "formhistory.dat"; + +NS_INTERFACE_MAP_BEGIN(nsFormHistory) + NS_INTERFACE_MAP_ENTRY(nsIFormHistory) + NS_INTERFACE_MAP_ENTRY(nsIObserver) + NS_INTERFACE_MAP_ENTRY(nsIFormSubmitObserver) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver) +NS_INTERFACE_MAP_END_THREADSAFE + +NS_IMPL_THREADSAFE_ADDREF(nsFormHistory); +NS_IMPL_THREADSAFE_RELEASE(nsFormHistory); + +mdb_column nsFormHistory::kToken_ValueColumn = 0; +mdb_column nsFormHistory::kToken_NameColumn = 0; + +nsFormHistory::nsFormHistory() : + mEnv(nsnull), + mStore(nsnull), + mTable(nsnull) +{ + NS_INIT_ISUPPORTS(); +} + +nsFormHistory::~nsFormHistory() +{ + CloseDatabase(); +} + +nsresult +nsFormHistory::Init() +{ + gFormHistory = this; + + nsCOMPtr service = do_GetService("@mozilla.org/observer-service;1"); + if (service) + service->AddObserver(this, NS_FORMSUBMIT_SUBJECT, PR_TRUE); + + return NS_OK; +} + +nsIMdbFactory *nsFormHistory::gMdbFactory = nsnull; +nsFormHistory *nsFormHistory::gFormHistory = nsnull; + +nsFormHistory * +nsFormHistory::GetInstance() +{ + if (!gFormHistory) { + gFormHistory = new nsFormHistory(); + if (!gFormHistory) + return nsnull; + + NS_ADDREF(gFormHistory); // addref for the global + + if (NS_FAILED(gFormHistory->Init())) { + NS_RELEASE(gFormHistory); + + return nsnull; + } + } + + NS_ADDREF(gFormHistory); // addref for the getter + + return gFormHistory; +} + + +void +nsFormHistory::ReleaseInstance() +{ + NS_IF_RELEASE(gFormHistory); +} + +//////////////////////////////////////////////////////////////////////// +//// nsIFormHistory + +NS_IMETHODIMP +nsFormHistory::GetRowCount(PRUint32 *aRowCount) +{ + nsresult rv = OpenDatabase(); // lazily ensure that the database is open + NS_ENSURE_SUCCESS(rv, rv); + + mdb_err err = mTable->GetCount(mEnv, aRowCount); + NS_ENSURE_TRUE(!err, NS_ERROR_FAILURE); + + return NS_OK; +} + +NS_IMETHODIMP +nsFormHistory::GetEntryAt(PRUint32 aIndex, nsAString &aName, nsAString &aValue) +{ + nsresult rv = OpenDatabase(); // lazily ensure that the database is open + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr row; + mdb_err err = mTable->PosToRow(mEnv, aIndex, getter_AddRefs(row)); + NS_ENSURE_TRUE(!err, NS_ERROR_FAILURE); + + GetRowValue(row, kToken_NameColumn, aName); + GetRowValue(row, kToken_ValueColumn, aValue); + + return NS_OK; +} + +NS_IMETHODIMP +nsFormHistory::GetNameAt(PRUint32 aIndex, nsAString &aName) +{ + nsresult rv = OpenDatabase(); // lazily ensure that the database is open + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr row; + mdb_err err = mTable->PosToRow(mEnv, aIndex, getter_AddRefs(row)); + NS_ENSURE_TRUE(!err, NS_ERROR_FAILURE); + + GetRowValue(row, kToken_NameColumn, aName); + + return NS_OK; +} + +NS_IMETHODIMP +nsFormHistory::GetValueAt(PRUint32 aIndex, nsAString &aValue) +{ + nsresult rv = OpenDatabase(); // lazily ensure that the database is open + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr row; + mdb_err err = mTable->PosToRow(mEnv, aIndex, getter_AddRefs(row)); + NS_ENSURE_TRUE(!err, NS_ERROR_FAILURE); + + GetRowValue(row, kToken_ValueColumn, aValue); + + return NS_OK; +} + +NS_IMETHODIMP +nsFormHistory::AddEntry(const nsAString &aName, const nsAString &aValue) +{ + nsCOMPtr row; + AppendRow(aName, aValue, getter_AddRefs(row)); + return NS_OK; +} + +NS_IMETHODIMP +nsFormHistory::RemoveEntryAt(PRUint32 index) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsFormHistory::RemoveEntriesForName(const nsAString & name) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsFormHistory::RemoveAllEntries() +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsFormHistory::EntryExists(const nsAString &aName, const nsAString &aValue, PRBool *_retval) +{ + // Unfortunately we have to do a brute force search through the database + // because mork didn't bother to implement any indexing functionality + + *_retval = PR_FALSE; + + nsresult rv = OpenDatabase(); // lazily ensure that the database is open + NS_ENSURE_SUCCESS(rv, rv); + + // Get a cursor to iterate through all rows in the database + nsCOMPtr rowCursor; + mdb_err err = mTable->GetTableRowCursor(mEnv, -1, getter_AddRefs(rowCursor)); + NS_ENSURE_TRUE(!err, NS_ERROR_FAILURE); + + nsIMdbRow *row = nsnull; + mdb_pos pos; + do { + rowCursor->NextRow(mEnv, &row, &pos); + NS_ENSURE_TRUE(row != nsnull, NS_ERROR_FAILURE); + + // Check if the name and value combination match this row + nsAutoString name; + GetRowValue(row, kToken_NameColumn, name); + if (Compare(name, aName, nsCaseInsensitiveStringComparator()) == 0) { + nsAutoString value; + GetRowValue(row, kToken_ValueColumn, value); + if (Compare(value, aValue, nsCaseInsensitiveStringComparator()) == 0) { + *_retval = PR_TRUE; + break; + } + } + } while (row); + + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +//// nsIObserver + +NS_IMETHODIMP +nsFormHistory::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData) +{ + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +//// nsIFormSubmitObserver + +NS_IMETHODIMP +nsFormHistory::Notify(nsIContent* aFormNode, nsIDOMWindowInternal* aWindow, nsIURI* aActionURL, PRBool* aCancelSubmit) +{ + nsresult rv = OpenDatabase(); // lazily ensure that the database is open + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr formElt = do_QueryInterface(aFormNode); + NS_ENSURE_TRUE(formElt, NS_ERROR_FAILURE); + + nsCOMPtr elts; + formElt->GetElements(getter_AddRefs(elts)); + + const char *textString = "text"; + + PRUint32 length; + elts->GetLength(&length); + for (PRUint32 i = 0; i < length; ++i) { + nsCOMPtr node; + elts->Item(i, getter_AddRefs(node)); + nsCOMPtr inputElt = do_QueryInterface(node); + if (inputElt) { + // Filter only inputs that are of type "text" + nsAutoString type; + inputElt->GetType(type); + if (type.EqualsIgnoreCase(textString)) { + // If this input has a name/id and value, add it to the database + nsAutoString value; + inputElt->GetValue(value); + if (!value.IsEmpty()) { + nsAutoString name; + inputElt->GetName(name); + if (name.IsEmpty()) + inputElt->GetId(name); + + if (!name.IsEmpty()) + AppendRow(name, value, nsnull); + } + } + } + } + + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +//// Database I/O + +nsresult +nsFormHistory::OpenDatabase() +{ + if (mStore) + return NS_OK; + + // Get a handle to the database file + nsCOMPtr historyFile; + nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(historyFile)); + NS_ENSURE_SUCCESS(rv, rv); + historyFile->Append(NS_ConvertUTF8toUCS2(kFormHistoryFileName)); + + // Get an Mdb Factory + static NS_DEFINE_CID(kMorkCID, NS_MORK_CID); + nsCOMPtr mdbFactory; + rv = nsComponentManager::CreateInstance(kMorkCID, nsnull, NS_GET_IID(nsIMdbFactoryFactory), getter_AddRefs(mdbFactory)); + NS_ENSURE_SUCCESS(rv, rv); + rv = mdbFactory->GetMdbFactory(&gMdbFactory); + NS_ENSURE_SUCCESS(rv, rv); + + // Create the Mdb environment + mdb_err err = gMdbFactory->MakeEnv(nsnull, &mEnv); + NS_ASSERTION(err == 0, "ERROR: Unable to create Form History mdb"); + mEnv->SetAutoClear(PR_TRUE); + NS_ENSURE_TRUE(!err, NS_ERROR_FAILURE); + + nsCAutoString filePath; + historyFile->GetNativePath(filePath); + PRBool exists = PR_TRUE; + historyFile->Exists(&exists); + + if (!exists || NS_FAILED(rv = OpenExistingFile(filePath.get()))) { + // If the file doesn't exist, or we fail trying to open it, + // then make sure it is deleted and then create an empty database file + historyFile->Remove(PR_FALSE); + rv = CreateNewFile(filePath.get()); + } + NS_ENSURE_SUCCESS(rv, rv); + + // Get the initial size of the file, needed later for Commit + historyFile->GetFileSize(&mFileSizeOnDisk); + + /* // TESTING: Add a row to the database + nsAutoString foopy; + foopy.AssignWithConversion("foopy"); + nsAutoString oogly; + oogly.AssignWithConversion("oogly"); + AppendRow(foopy, oogly, nsnull); + Flush(); */ + + /* // TESTING: Dump the contents of the database + PRUint32 count = 0; + mdb_err err = mTable->GetCount(mEnv, &count); + printf("%d rows in form history\n", count); + + for (mdb_pos pos = count - 1; pos >= 0; --pos) { + nsCOMPtr row; + err = mTable->PosToRow(mEnv, pos, getter_AddRefs(row)); + + nsAutoString name; + GetRowValue(row, kToken_NameColumn, name); + nsAutoString value; + GetRowValue(row, kToken_ValueColumn, value); + printf("ROW: %s - %s\n", ToNewCString(name), ToNewCString(value)); + } */ + + return NS_OK; +} + +nsresult +nsFormHistory::OpenExistingFile(const char *aPath) +{ + nsCOMPtr oldFile; + nsIMdbHeap* dbHeap = 0; + mdb_err err = gMdbFactory->OpenOldFile(mEnv, dbHeap, aPath, mdbBool_kFalse, getter_AddRefs(oldFile)); + NS_ENSURE_TRUE(!err && oldFile, NS_ERROR_FAILURE); + + mdb_bool canOpen = 0; + mdbYarn outFormat = {nsnull, 0, 0, 0, 0, nsnull}; + err = gMdbFactory->CanOpenFilePort(mEnv, oldFile, &canOpen, &outFormat); + NS_ENSURE_TRUE(!err && canOpen, NS_ERROR_FAILURE); + + nsCOMPtr thumb; + mdbOpenPolicy policy = {{0, 0}, 0, 0}; + err = gMdbFactory->OpenFileStore(mEnv, dbHeap, oldFile, &policy, getter_AddRefs(thumb)); + NS_ENSURE_TRUE(!err && thumb, NS_ERROR_FAILURE); + + PRBool done; + UseThumb(thumb, &done); + + if (err == 0 && done) + err = gMdbFactory->ThumbToOpenStore(mEnv, thumb, &mStore); + NS_ENSURE_TRUE(!err, NS_ERROR_FAILURE); + + nsresult rv = CreateTokens(); + NS_ENSURE_SUCCESS(rv, rv); + + mdbOid oid = {kToken_RowScope, 1}; + err = mStore->GetTable(mEnv, &oid, &mTable); + NS_ENSURE_TRUE(!err, NS_ERROR_FAILURE); + if (!mTable) { + NS_WARNING("ERROR: Form history file is corrupt, now deleting it."); + return NS_ERROR_FAILURE; + } + + return err ? NS_ERROR_FAILURE : NS_OK; +} + +nsresult +nsFormHistory::CreateNewFile(const char *aPath) +{ + nsIMdbHeap* dbHeap = 0; + nsCOMPtr newFile; + mdb_err err = gMdbFactory->CreateNewFile(mEnv, dbHeap, aPath, getter_AddRefs(newFile)); + NS_ENSURE_TRUE(!err && newFile, NS_ERROR_FAILURE); + + mdbOpenPolicy policy = {{0, 0}, 0, 0}; + err = gMdbFactory->CreateNewFileStore(mEnv, dbHeap, newFile, &policy, &mStore); + NS_ENSURE_TRUE(!err, NS_ERROR_FAILURE); + + nsresult rv = CreateTokens(); + NS_ENSURE_SUCCESS(rv, rv); + + // Create the one and only table in the database + err = mStore->NewTable(mEnv, kToken_RowScope, kToken_Kind, PR_TRUE, nsnull, &mTable); + NS_ENSURE_TRUE(!err && mTable, NS_ERROR_FAILURE); + + // Force a commit now to get it written out. + nsCOMPtr thumb; + err = mStore->LargeCommit(mEnv, getter_AddRefs(thumb)); + NS_ENSURE_TRUE(!err, NS_ERROR_FAILURE); + + PRBool done; + err = UseThumb(thumb, &done); + + return err || !done ? NS_ERROR_FAILURE : NS_OK; +} + +nsresult +nsFormHistory::CloseDatabase() +{ + Flush(); + + if (mTable) + mTable->Release(); + + if (mStore) + mStore->Release(); + + if (mEnv) + mEnv->Release(); + + mTable = nsnull; + mEnv = nsnull; + mStore = nsnull; + + return NS_OK; +} + +nsresult +nsFormHistory::CreateTokens() +{ + mdb_err err; + + if (!mStore) + return NS_ERROR_NOT_INITIALIZED; + + err = mStore->StringToToken(mEnv, "ns:formhistory:db:row:scope:formhistory:all", &kToken_RowScope); + if (err != 0) return NS_ERROR_FAILURE; + + err = mStore->StringToToken(mEnv, "ns:formhistory:db:table:kind:formhistory", &kToken_Kind); + if (err != 0) return NS_ERROR_FAILURE; + + err = mStore->StringToToken(mEnv, "Value", &kToken_ValueColumn); + if (err != 0) return NS_ERROR_FAILURE; + + err = mStore->StringToToken(mEnv, "Name", &kToken_NameColumn); + if (err != 0) return NS_ERROR_FAILURE; + + return NS_OK; +} + +nsresult +nsFormHistory::Flush() +{ + if (!mStore || !mTable) + return NS_OK; + + mdb_err err; + + nsCOMPtr thumb; + err = mStore->LargeCommit(mEnv, getter_AddRefs(thumb)); + + if (err == 0) + err = UseThumb(thumb, nsnull); + + return err ? NS_ERROR_FAILURE : NS_OK; +} + +mdb_err +nsFormHistory::UseThumb(nsIMdbThumb *aThumb, PRBool *aDone) +{ + mdb_count total; + mdb_count current; + mdb_bool done; + mdb_bool broken; + mdb_err err; + + do { + err = aThumb->DoMore(mEnv, &total, ¤t, &done, &broken); + } while ((err == 0) && !broken && !done); + + if (aDone) + *aDone = done; + + return err ? NS_ERROR_FAILURE : NS_OK; +} + +nsresult +nsFormHistory::AppendRow(const nsAString &aName, const nsAString &aValue, nsIMdbRow **aResult) +{ + if (!mTable) + return NS_ERROR_NOT_INITIALIZED; + + PRBool exists; + EntryExists(aName, aValue, &exists); + printf("duplicate (%d) for %s - %s\n", exists, ToNewCString(aName), ToNewCString(aValue)); + if (exists) + return NS_OK; + + mdbOid rowId; + rowId.mOid_Scope = kToken_RowScope; + rowId.mOid_Id = mdb_id(-1); + + nsCOMPtr row; + mdb_err err = mTable->NewRow(mEnv, &rowId, getter_AddRefs(row)); + if (err != 0) + return NS_ERROR_FAILURE; + + SetRowValue(row, kToken_NameColumn, aName); + SetRowValue(row, kToken_ValueColumn, aValue); + + if (aResult) { + *aResult = row; + NS_ADDREF(*aResult); + } + + return NS_OK; +} + +nsresult +nsFormHistory::SetRowValue(nsIMdbRow *aRow, mdb_column aCol, const nsAString &aValue) +{ + PRInt32 len = aValue.Length() * sizeof(PRUnichar); + + mdbYarn yarn = {(void *)ToNewUnicode(aValue), len, len, 0, 0, nsnull}; + mdb_err err = aRow->AddColumn(mEnv, aCol, &yarn); + + return err ? NS_ERROR_FAILURE : NS_OK; +} + +nsresult +nsFormHistory::GetRowValue(nsIMdbRow *aRow, mdb_column aCol, nsAString &aValue) +{ + mdbYarn yarn; + mdb_err err = aRow->AliasCellYarn(mEnv, aCol, &yarn); + if (err != 0) + return NS_ERROR_FAILURE; + + aValue.Truncate(0); + if (!yarn.mYarn_Fill) + return NS_OK; + + switch (yarn.mYarn_Form) { + case 0: // unicode + aValue.Assign((const PRUnichar *)yarn.mYarn_Buf, yarn.mYarn_Fill/sizeof(PRUnichar)); + break; + default: + return NS_ERROR_UNEXPECTED; + } + + return NS_OK; +} + +nsresult +nsFormHistory::AutoCompleteSearch(const nsAString &aInputName, + const nsAString &aInputValue, + nsIAutoCompleteMdbResult *aPrevResult, + nsIAutoCompleteMdbResult **aResult) +{ + nsresult rv = OpenDatabase(); // lazily ensure that the database is open + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr result; + + if (aPrevResult) { + result = aPrevResult; + + PRUint32 rowCount; + result->GetMatchCount(&rowCount); + + for (PRInt32 i = rowCount-1; i >= 0; --i) { + nsIMdbRow *row; + result->GetRowAt(i, &row); + if (!RowMatch(row, aInputName, aInputValue, nsnull)) + result->RemoveRowAt(i); + } + } else { + result = do_CreateInstance("@mozilla.org/autocomplete/mdb-result;1"); + + result->SetSearchString(aInputValue); + result->Init(mEnv, mTable); + result->SetTokens(kToken_ValueColumn, nsIAutoCompleteMdbResult::kUnicharType, nsnull, nsIAutoCompleteMdbResult::kUnicharType); + + // Get a cursor to iterate through all rows in the database + nsCOMPtr rowCursor; + mdb_err err = mTable->GetTableRowCursor(mEnv, -1, getter_AddRefs(rowCursor)); + NS_ENSURE_TRUE(!err, NS_ERROR_FAILURE); + + // Store only the matching values + nsAutoVoidArray matchingValues; + nsAutoVoidArray matchingRows; + + nsIMdbRow *row = nsnull; + mdb_pos pos; + do { + rowCursor->NextRow(mEnv, &row, &pos); + if (!row) + break; + + PRUnichar *value = 0; // We will own the allocated string value + if (RowMatch(row, aInputName, aInputValue, &value)) { + matchingRows.AppendElement(row); + matchingValues.AppendElement(value); + } + } while (row); + + // Turn auto array into flat array for quick sort, now that we + // know how many items there are + PRUint32 count = matchingRows.Count(); + PRUint32* items = new PRUint32[count]; + PRUint32 i; + for (i = 0; i < count; ++i) + items[i] = i; + + NS_QuickSort(items, count, sizeof(nsIMdbRow*), + SortComparison, &matchingValues); + + for (i = 0; i < count; ++i) { + // Place the sorted result into the autocomplete result + result->AddRow((nsIMdbRow *)matchingRows[items[i]]); + + // Free up these strings we owned. + delete (PRUnichar *) matchingValues[i]; + } + + delete[] items; + + PRUint32 matchCount; + result->GetMatchCount(&matchCount); + if (matchCount > 0) { + result->SetSearchResult(nsIAutoCompleteResult::RESULT_SUCCESS); + result->SetDefaultIndex(0); + } else { + result->SetSearchResult(nsIAutoCompleteResult::RESULT_NOMATCH); + result->SetDefaultIndex(-1); + } + } + + *aResult = result; + NS_IF_ADDREF(*aResult); + + return NS_OK; +} + +int PR_CALLBACK +nsFormHistory::SortComparison(const void *v1, const void *v2, void *closureVoid) +{ + PRUint32 *index1 = (PRUint32 *)v1; + PRUint32 *index2 = (PRUint32 *)v2; + nsAutoVoidArray *array = (nsAutoVoidArray *)closureVoid; + + PRUnichar *s1 = (PRUnichar *)array->ElementAt(*index1); + PRUnichar *s2 = (PRUnichar *)array->ElementAt(*index2); + + return nsCRT::strcmp(s1, s2); +} + +PRBool +nsFormHistory::RowMatch(nsIMdbRow *aRow, const nsAString &aInputName, const nsAString &aInputValue, PRUnichar **aValue) +{ + nsAutoString name, value; + GetRowValue(aRow, kToken_NameColumn, name); + GetRowValue(aRow, kToken_ValueColumn, value); + + if (name.Equals(aInputName)) { + if (value.Length() != aInputValue.Length() && // ignore exact matches + Compare(Substring(value, 0, aInputValue.Length()), aInputValue, nsCaseInsensitiveStringComparator()) == 0) + { + if (aValue) + *aValue = ToNewUnicode(value); + return PR_TRUE; + } + } + + return PR_FALSE; +} diff --git a/mozilla/toolkit/components/satchel/src/nsFormHistory.h b/mozilla/toolkit/components/satchel/src/nsFormHistory.h new file mode 100644 index 00000000000..ebaacd2cb6c --- /dev/null +++ b/mozilla/toolkit/components/satchel/src/nsFormHistory.h @@ -0,0 +1,108 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Joe Hewitt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __nsFormHistory__ +#define __nsFormHistory__ + +#include "nsIFormHistory.h" +#include "nsIAutoCompleteResultTypes.h" +#include "nsIFormSubmitObserver.h" +#include "nsString.h" +#include "nsCOMPtr.h" +#include "nsIObserver.h" +#include "nsWeakReference.h" +#include "mdb.h" + +class nsFormHistory : public nsIFormHistory, + public nsIObserver, + public nsIFormSubmitObserver, + public nsSupportsWeakReference +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIFORMHISTORY + NS_DECL_NSIOBSERVER + + // nsIFormSubmitObserver + NS_IMETHOD Notify(nsIContent* formNode, nsIDOMWindowInternal* window, nsIURI* actionURL, PRBool* cancelSubmit); + + nsFormHistory(); + virtual ~nsFormHistory(); + nsresult Init(); + + static nsFormHistory *GetInstance(); + static void ReleaseInstance(void); + + nsresult AutoCompleteSearch(const nsAString &aInputName, const nsAString &aInputValue, + nsIAutoCompleteMdbResult *aPrevResult, nsIAutoCompleteMdbResult **aNewResult); + + static mdb_column kToken_ValueColumn; + static mdb_column kToken_NameColumn; + +protected: + // Database I/O + nsresult OpenDatabase(); + nsresult OpenExistingFile(const char *aPath); + nsresult CreateNewFile(const char *aPath); + nsresult CloseDatabase(); + nsresult CreateTokens(); + nsresult Flush(); + + mdb_err UseThumb(nsIMdbThumb *aThumb, PRBool *aDone); + + nsresult AppendRow(const nsAString &aValue, const nsAString &aName, nsIMdbRow **aResult); + nsresult SetRowValue(nsIMdbRow *aRow, mdb_column aCol, const nsAString &aValue); + nsresult GetRowValue(nsIMdbRow *aRow, mdb_column aCol, nsAString &aValue); + + PRBool RowMatch(nsIMdbRow *aRow, const nsAString &aInputName, const nsAString &aInputValue, PRUnichar **aValue); + + PR_STATIC_CALLBACK(int) SortComparison(const void *v1, const void *v2, void *closureVoid); + + static nsFormHistory *gFormHistory; + static nsIMdbFactory *gMdbFactory; + + nsIMdbEnv* mEnv; + nsIMdbStore* mStore; + nsIMdbTable* mTable; + PRInt64 mFileSizeOnDisk; + + // database tokens + mdb_scope kToken_RowScope; + mdb_kind kToken_Kind; +}; + +#endif // __nsFormHistory__ diff --git a/mozilla/toolkit/components/satchel/towel b/mozilla/toolkit/components/satchel/towel new file mode 100644 index 00000000000..f748ff69509 --- /dev/null +++ b/mozilla/toolkit/components/satchel/towel @@ -0,0 +1,5 @@ +"Any man who can hitch the length and breadth of the galaxy, rough it, +slum it, struggle against terrible odds, win through, and still knows +where his towel is is clearly a man to be reckoned with." + + - Douglas Adams \ No newline at end of file