Back to index

lightning-sunbird  0.9+nobinonly
nsAutoCompleteMdbResult.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla Communicator client code.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1998
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Joe Hewitt <hewitt@netscape.com> (Original Author)
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "nsAutoCompleteMdbResult.h"
00039 #include "nsCOMPtr.h"
00040 #include "nsCRT.h"
00041 
00042 static void SwapBytes(PRUnichar* aDest, const PRUnichar* aSrc, PRUint32 aLen)
00043 {
00044   for(PRUint32 i = 0; i < aLen; i++)
00045   {
00046     PRUnichar aChar = *aSrc++;
00047     *aDest++ = (0xff & (aChar >> 8)) | (aChar << 8);
00048   }
00049 }
00050 
00051 NS_INTERFACE_MAP_BEGIN(nsAutoCompleteMdbResult)
00052   NS_INTERFACE_MAP_ENTRY(nsIAutoCompleteResult)
00053   NS_INTERFACE_MAP_ENTRY(nsIAutoCompleteBaseResult)
00054   NS_INTERFACE_MAP_ENTRY(nsIAutoCompleteMdbResult)
00055   NS_INTERFACE_MAP_ENTRY(nsIAutoCompleteMdbResult2)
00056   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAutoCompleteResult)
00057 NS_INTERFACE_MAP_END
00058 
00059 NS_IMPL_ADDREF(nsAutoCompleteMdbResult)
00060 NS_IMPL_RELEASE(nsAutoCompleteMdbResult)
00061 
00062 nsAutoCompleteMdbResult::nsAutoCompleteMdbResult() :
00063   mDefaultIndex(-1),
00064   mSearchResult(nsIAutoCompleteResult::RESULT_IGNORED),
00065   mReverseByteOrder(PR_FALSE)
00066 {
00067 }
00068 
00069 nsAutoCompleteMdbResult::~nsAutoCompleteMdbResult()
00070 {
00071 
00072 }
00073 
00076 
00077 NS_IMETHODIMP
00078 nsAutoCompleteMdbResult::GetSearchString(nsAString &aSearchString)
00079 {
00080   aSearchString = mSearchString;
00081   return NS_OK;
00082 }
00083 
00084 NS_IMETHODIMP
00085 nsAutoCompleteMdbResult::GetSearchResult(PRUint16 *aSearchResult)
00086 {
00087   *aSearchResult = mSearchResult;
00088   return NS_OK;
00089 }
00090 
00091 NS_IMETHODIMP
00092 nsAutoCompleteMdbResult::GetDefaultIndex(PRInt32 *aDefaultIndex)
00093 {
00094   *aDefaultIndex = mDefaultIndex;
00095   return NS_OK;
00096 }
00097 
00098 NS_IMETHODIMP
00099 nsAutoCompleteMdbResult::GetErrorDescription(nsAString & aErrorDescription)
00100 {
00101   aErrorDescription = mErrorDescription;
00102   return NS_OK;
00103 }
00104 
00105 NS_IMETHODIMP
00106 nsAutoCompleteMdbResult::GetMatchCount(PRUint32 *aMatchCount)
00107 {
00108   *aMatchCount = mResults.Count();
00109   return NS_OK;
00110 }
00111 
00112 NS_IMETHODIMP
00113 nsAutoCompleteMdbResult::GetValueAt(PRInt32 aIndex, nsAString & _retval)
00114 {
00115   NS_ENSURE_TRUE(aIndex >= 0 && aIndex < mResults.Count(), NS_ERROR_ILLEGAL_VALUE);
00116 
00117   nsIMdbRow *row = mResults.ObjectAt(aIndex);
00118   if (!row) return NS_OK;
00119 
00120   if (mValueType == kUnicharType) {
00121     GetRowValue(row, mValueToken, _retval);
00122   } else if (mValueType == kCharType) {
00123     nsCAutoString value;
00124     GetUTF8RowValue(row, mValueToken, value);
00125     _retval = NS_ConvertUTF8toUCS2(value);
00126   }
00127   
00128   /* // TESTING: return ordinaly labeled values   
00129   char *value = new char(20);
00130   sprintf(value, "foopy (%d)", aIndex);
00131   
00132   nsAutoString result;
00133   result.AssignASCII(value);
00134   _retval = result;*/
00135 
00136   return NS_OK;
00137 }
00138 
00139 NS_IMETHODIMP
00140 nsAutoCompleteMdbResult::GetCommentAt(PRInt32 aIndex, nsAString & _retval)
00141 {
00142   NS_ENSURE_TRUE(aIndex >= 0 && aIndex < mResults.Count(), NS_ERROR_ILLEGAL_VALUE);
00143 
00144   nsIMdbRow *row = mResults.ObjectAt(aIndex);
00145   if (!row) return NS_OK;
00146 
00147   if (mCommentType == kUnicharType) {
00148     GetRowValue(row, mCommentToken, _retval);
00149   } else if (mCommentType == kCharType) {
00150     nsCAutoString value;
00151     GetUTF8RowValue(row, mCommentToken, value);
00152     _retval = NS_ConvertUTF8toUCS2(value);
00153   }
00154 
00155   return NS_OK;
00156 }
00157 
00158 NS_IMETHODIMP
00159 nsAutoCompleteMdbResult::GetStyleAt(PRInt32 aIndex, nsAString & _retval)
00160 {
00161   return NS_ERROR_NOT_IMPLEMENTED;
00162 }
00163 
00166 
00167 NS_IMETHODIMP
00168 nsAutoCompleteMdbResult::SetSearchString(const nsAString &aSearchString)
00169 {
00170   mSearchString.Assign(aSearchString);
00171   return NS_OK;
00172 }
00173 
00174 NS_IMETHODIMP
00175 nsAutoCompleteMdbResult::SetErrorDescription(const nsAString &aErrorDescription)
00176 {
00177   mErrorDescription.Assign(aErrorDescription);
00178   return NS_OK;
00179 }
00180 
00181 NS_IMETHODIMP
00182 nsAutoCompleteMdbResult::SetDefaultIndex(PRInt32 aDefaultIndex)
00183 {
00184   mDefaultIndex = aDefaultIndex;
00185   return NS_OK;
00186 }
00187 
00188 NS_IMETHODIMP
00189 nsAutoCompleteMdbResult::SetSearchResult(PRUint32 aSearchResult)
00190 {
00191   mSearchResult = aSearchResult;
00192   return NS_OK;
00193 }
00194 
00197 
00198 NS_IMETHODIMP
00199 nsAutoCompleteMdbResult::Init(nsIMdbEnv *aEnv, nsIMdbTable *aTable)
00200 {
00201   mEnv = aEnv;
00202   mTable = aTable;
00203   return NS_OK;
00204 }
00205 
00206 NS_IMETHODIMP
00207 nsAutoCompleteMdbResult::SetTokens(mdb_scope aValueToken, PRInt16 aValueType, mdb_scope aCommentToken, PRInt16 aCommentType)
00208 {
00209   mValueToken = aValueToken;
00210   mValueType = aValueType;
00211   mCommentToken = aCommentToken;
00212   mCommentType = aCommentType;
00213   return NS_OK;
00214 }
00215 
00216 NS_IMETHODIMP
00217 nsAutoCompleteMdbResult::AddRow(nsIMdbRow *aRow)
00218 {
00219   mResults.AppendObject(aRow);
00220   return NS_OK;
00221 }
00222 
00223 NS_IMETHODIMP
00224 nsAutoCompleteMdbResult::RemoveValueAt(PRInt32 aRowIndex, PRBool aRemoveFromDb)
00225 {
00226   nsIMdbRow *row = mResults.ObjectAt(aRowIndex);
00227   NS_ENSURE_TRUE(row, NS_ERROR_INVALID_ARG);
00228 
00229   if (aRemoveFromDb && mTable && mEnv) {
00230     // TODO: share this code with nsGlobalHistory::RemovePageInternal(),
00231     // rather than duplicating it here.
00232 
00233     nsIMdbPort *port = nsnull;
00234     mTable->GetPort(mEnv, &port);  // note: doesn't addref
00235 
00236     nsCOMPtr<nsIMdbStore> store = do_QueryInterface(port);
00237     NS_ENSURE_TRUE(store, NS_ERROR_FAILURE);
00238 
00239     mdb_err err = mTable->CutRow(mEnv, row);
00240     NS_ENSURE_TRUE(!err, NS_ERROR_FAILURE);
00241 
00242     row->CutAllColumns(mEnv);
00243 
00244     // We must do a CompressCommit on the store now.  If we don't,
00245     // mork can leave the file in an inconsistent state, which causes it to
00246     // be killed the next time it's opened.
00247 
00248     nsCOMPtr<nsIMdbThumb> thumb;
00249     err = store->CompressCommit(mEnv, getter_AddRefs(thumb));
00250     if (err == 0) {
00251       mdb_count total, current;
00252       mdb_bool done, broken;
00253       do {
00254        err = thumb->DoMore(mEnv, &total, &current, &done, &broken);
00255       } while ((err == 0) && !broken && !done);
00256     }
00257   }
00258 
00259   mResults.RemoveObjectAt(aRowIndex);
00260 
00261   return NS_OK;
00262 }
00263 
00264 NS_IMETHODIMP
00265 nsAutoCompleteMdbResult::GetRowAt(PRUint32 aRowIndex, nsIMdbRow **aRow)
00266 {
00267   *aRow = mResults.ObjectAt(aRowIndex);
00268   return NS_OK;
00269 }
00270 
00271 NS_IMETHODIMP
00272 nsAutoCompleteMdbResult::GetRowValue(nsIMdbRow *aRow, mdb_column aCol, nsAString &aValue)
00273 {
00274   mdbYarn yarn;
00275   mdb_err err = aRow->AliasCellYarn(mEnv, aCol, &yarn);
00276   if (err != 0)
00277     return NS_ERROR_FAILURE;
00278 
00279   aValue.Truncate(0);
00280   if (!yarn.mYarn_Fill)
00281     return NS_OK;
00282   
00283   switch (yarn.mYarn_Form) {
00284     case 0: { // unicode
00285       PRUint32 len = yarn.mYarn_Fill / sizeof(PRUnichar);
00286       if (mReverseByteOrder) {
00287         // The mdb file is other-endian, byte-swap the result
00288         PRUnichar *swapval = new PRUnichar[len];
00289         if (!swapval)
00290           return NS_ERROR_OUT_OF_MEMORY;
00291         SwapBytes(swapval, (const PRUnichar *)yarn.mYarn_Buf, len);
00292         aValue.Assign(swapval, len);
00293         delete swapval;
00294       }
00295       else
00296         aValue.Assign((const PRUnichar *)yarn.mYarn_Buf, len);
00297       break;
00298     }
00299     case 1: // utf 8
00300       aValue.Assign(NS_ConvertUTF8toUCS2((const char*)yarn.mYarn_Buf, yarn.mYarn_Fill));
00301       break;
00302     default:
00303       return NS_ERROR_UNEXPECTED;
00304   }
00305   
00306   return NS_OK;
00307 }
00308 
00309 
00310 nsresult
00311 nsAutoCompleteMdbResult::GetUTF8RowValue(nsIMdbRow *aRow, mdb_column aCol,
00312                                     nsACString& aValue)
00313 {
00314   mdb_err err;
00315   
00316   mdbYarn yarn;
00317   err = aRow->AliasCellYarn(mEnv, aCol, &yarn);
00318   if (err != 0) return NS_ERROR_FAILURE;
00319 
00320   const char* startPtr = (const char*)yarn.mYarn_Buf;
00321   if (startPtr)
00322     aValue.Assign(Substring(startPtr, startPtr + yarn.mYarn_Fill));
00323   else
00324     aValue.Truncate();
00325   
00326   return NS_OK;
00327 }
00328 
00329 nsresult
00330 nsAutoCompleteMdbResult::GetIntRowValue(nsIMdbRow *aRow, mdb_column aCol,
00331                                    PRInt32 *aValue)
00332 {
00333   mdb_err err;
00334   
00335   mdbYarn yarn;
00336   err = aRow->AliasCellYarn(mEnv, aCol, &yarn);
00337   if (err != 0) return NS_ERROR_FAILURE;
00338 
00339   if (yarn.mYarn_Buf)
00340     *aValue = atoi((char *)yarn.mYarn_Buf);
00341   else
00342     *aValue = 0;
00343   
00344   return NS_OK;
00345 }
00346 
00349 
00350 NS_IMETHODIMP
00351 nsAutoCompleteMdbResult::GetReverseByteOrder(PRBool *aReverseByteOrder)
00352 {
00353   *aReverseByteOrder = mReverseByteOrder;
00354   return NS_OK;
00355 }
00356 
00357 NS_IMETHODIMP
00358 nsAutoCompleteMdbResult::SetReverseByteOrder(PRBool aReverseByteOrder)
00359 {
00360   mReverseByteOrder = aReverseByteOrder;
00361   return NS_OK;
00362 }