Back to index

lightning-sunbird  0.9+nobinonly
nsFilePicker.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is the Mozilla browser.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 2001
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Adrian Mardare <amardare@qnx.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 
00041 #include "nsCOMPtr.h"
00042 #include "nsReadableUtils.h"
00043 #include "nsNetUtil.h"
00044 #include "nsWindow.h"
00045 #include "nsIServiceManager.h"
00046 #include "nsIPlatformCharset.h"
00047 #include "nsFilePicker.h"
00048 #include "nsILocalFile.h"
00049 #include "nsIURL.h"
00050 #include "nsIFileURL.h"
00051 #include "nsIStringBundle.h"
00052 #include "nsEnumeratorUtils.h"
00053 #include "nsCRT.h"
00054 
00055 
00056 static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
00057 
00058 NS_IMPL_ISUPPORTS1(nsFilePicker, nsIFilePicker)
00059 
00060 char nsFilePicker::mLastUsedDirectory[PATH_MAX+1] = { 0 };
00061 
00062 #define MAX_EXTENSION_LENGTH PATH_MAX
00063 
00064 //-------------------------------------------------------------------------
00065 //
00066 // nsFilePicker constructor
00067 //
00068 //-------------------------------------------------------------------------
00069 nsFilePicker::nsFilePicker()
00070   : mParentWidget(nsnull)
00071   , mUnicodeEncoder(nsnull)
00072   , mUnicodeDecoder(nsnull)
00073 {
00074   char *path = getenv("HOME");
00075   if (path) {
00076     nsCOMPtr<nsILocalFile> displayDirectory = do_CreateInstance("@mozilla.org/file/local;1");
00077     if (displayDirectory) {
00078       nsresult rv = displayDirectory->InitWithNativePath(nsDependentCString(path));
00079       PRBool cond;
00080       if (NS_SUCCEEDED(rv) &&
00081           NS_SUCCEEDED(displayDirectory->Exists(&cond)) &&
00082           cond &&
00083           NS_SUCCEEDED(displayDirectory->IsDirectory(&cond)) &&
00084           cond)
00085         mDisplayDirectory = displayDirectory;
00086     }
00087   }
00088 }
00089 
00090 //-------------------------------------------------------------------------
00091 //
00092 // nsFilePicker destructor
00093 //
00094 //-------------------------------------------------------------------------
00095 nsFilePicker::~nsFilePicker()
00096 {
00097   NS_IF_RELEASE(mUnicodeEncoder);
00098   NS_IF_RELEASE(mUnicodeDecoder);
00099 }
00100 
00101 //-------------------------------------------------------------------------
00102 //
00103 // Show - Display the file dialog
00104 //
00105 //-------------------------------------------------------------------------
00106 NS_IMETHODIMP nsFilePicker::Show(PRInt16 *aReturnVal)
00107 {
00108        PRInt32 flags = 0;
00109        char *btn1;
00110 
00111        NS_ENSURE_ARG_POINTER(aReturnVal);
00112 
00113   if (mMode == modeGetFolder) {
00114               flags |= Pt_FSR_SELECT_DIRS|Pt_FSR_NO_SELECT_FILES;
00115               btn1 = "&Select";
00116   }
00117   else if (mMode == modeOpen) {
00118               btn1 = "&Open";
00119   }
00120   else if (mMode == modeSave) {
00121               flags |= Pt_FSR_NO_FCHECK;
00122               btn1 = "&Save";
00123   }
00124        else if( mMode == modeOpenMultiple ) {
00125               flags |= Pt_FSR_MULTIPLE;
00126               btn1 = "&Select";
00127               }
00128   else {
00129     printf("nsFilePicker::Show() wrong mode");
00130     return PR_FALSE;
00131   }
00132 
00133   char *title = ToNewUTF8String( mTitle );
00134 
00135   nsCAutoString initialDir;
00136   if (mDisplayDirectory)
00137     mDisplayDirectory->GetNativePath(initialDir);
00138   // If no display directory, re-use the last one.
00139   if(initialDir.IsEmpty()) {
00140     // Allocate copy of last used dir.
00141     initialDir = mLastUsedDirectory;
00142   }
00143 
00144   if( !mDefault.IsEmpty() ) {
00145     initialDir.AppendWithConversion( NS_LITERAL_STRING( "/" ) );
00146     initialDir.AppendWithConversion( mDefault );
00147   }
00148 
00149        char extensionBuffer[MAX_EXTENSION_LENGTH+1] = "*";
00150        if( !mFilterList.IsEmpty() ) {
00151               char *text = ToNewUTF8String( mFilterList );
00152               if( text ) {
00153                      extensionBuffer[0] = 0;
00154 
00155                      /* eliminate the ';' and the duplicates */
00156                      char buffer[MAX_EXTENSION_LENGTH+1], buf[MAX_EXTENSION_LENGTH+1], *q, *delims = "; ", *dummy;
00157                      strcpy( buffer, text );
00158                      q = strtok_r( buffer, delims, &dummy );
00159                      while( q ) {
00160                             sprintf( buf, "%s ", q );
00161                             if( !strstr( extensionBuffer, buf ) )
00162                                    strcat( extensionBuffer, buf );
00163                             q = strtok_r( NULL, delims, &dummy );
00164                             }
00165 
00166                      nsMemory::Free( text );
00167                      }
00168               }
00169        else if (!mDefaultExtension.IsEmpty()) {
00170               // Someone was cool and told us what to do
00171               char *convertedExt = ToNewUTF8String( mDefaultExtension );
00172               if (!convertedExt) {
00173                      mDefaultExtension.ToCString(extensionBuffer, MAX_EXTENSION_LENGTH);
00174                      }
00175               else {
00176                      PL_strncpyz(extensionBuffer, convertedExt, MAX_EXTENSION_LENGTH+1);
00177                      nsMemory::Free( convertedExt );
00178                      }
00179               }
00180 
00181        PtFileSelectionInfo_t info;
00182        memset( &info, 0, sizeof( info ) );
00183 
00184        if( PtFileSelection( mParentWidget, NULL, title, initialDir.get(),
00185               extensionBuffer, btn1, "&Cancel", "nsd", &info, flags ) ) {
00186                      if (title) nsMemory::Free( title );
00187                      return NS_ERROR_FAILURE;
00188                      }
00189 
00190        *aReturnVal = returnOK;
00191 
00192        if( info.ret == Pt_FSDIALOG_BTN2 ) {
00193               *aReturnVal = returnCancel;
00194               }
00195        else if( mMode != modeOpenMultiple ) {
00196               mFile.SetLength(0);
00197               mFile.Append( info.path );
00198 
00199               if( mMode == modeSave ) {
00200                      nsCOMPtr<nsILocalFile> file(do_CreateInstance("@mozilla.org/file/local;1"));
00201                      NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
00202 
00203                      file->InitWithNativePath( mFile );
00204                      
00205                      PRBool exists = PR_FALSE;
00206                      file->Exists(&exists);
00207                      if (exists)
00208                             *aReturnVal = returnReplace;
00209                      }
00210               }
00211        else { /* here mMode is modeOpenMultiple */
00212               PtFileSelectorInfo_t *minfo = info.minfo;
00213               if( minfo ) {
00214                      nsresult rv = NS_NewISupportsArray(getter_AddRefs(mFiles));
00215                      NS_ENSURE_SUCCESS(rv,rv);
00216 
00217                      for( int i=0; i<minfo->nitems; i++ ) {
00218                             nsCOMPtr<nsILocalFile> file = do_CreateInstance("@mozilla.org/file/local;1", &rv);
00219                             NS_ENSURE_SUCCESS(rv,rv);
00220        
00221                             nsCString s ( minfo->multipath[i] );
00222                             rv = file->InitWithNativePath( s );
00223                             NS_ENSURE_SUCCESS(rv,rv);
00224        
00225                             rv = mFiles->AppendElement(file);
00226                             NS_ENSURE_SUCCESS(rv,rv);
00227                             }
00228 
00229                      PtFSFreeInfo( &info ); /* clean the info structure if the multiple mode is set */
00230                      }
00231               }
00232 
00233   PL_strncpyz( mLastUsedDirectory, info.path, PATH_MAX+1 );
00234   if (!mDisplayDirectory)
00235     mDisplayDirectory = do_CreateInstance("@mozilla.org/file/local;1");
00236   if (mDisplayDirectory)
00237     mDisplayDirectory->InitWithNativePath( nsDependentCString(mLastUsedDirectory) );
00238 
00239   if( title ) nsMemory::Free( title );
00240               
00241   return NS_OK;
00242 
00243 // TODO: implement filters
00244 }
00245 
00246 
00247 
00248 NS_IMETHODIMP nsFilePicker::GetFile(nsILocalFile **aFile)
00249 {
00250   NS_ENSURE_ARG_POINTER(aFile);
00251 
00252   if (mFile.IsEmpty())
00253       return NS_OK;
00254 
00255   nsCOMPtr<nsILocalFile> file(do_CreateInstance("@mozilla.org/file/local;1"));
00256     
00257   NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
00258 
00259   file->InitWithNativePath(mFile);
00260 
00261   NS_ADDREF(*aFile = file);
00262 
00263   return NS_OK;
00264 }
00265 
00266 NS_IMETHODIMP nsFilePicker::GetFiles(nsISimpleEnumerator **aFiles)
00267 {
00268        NS_ENSURE_ARG_POINTER(aFiles);
00269        return NS_NewArrayEnumerator(aFiles, mFiles);
00270 }
00271 
00272 //-------------------------------------------------------------------------
00273 NS_IMETHODIMP nsFilePicker::GetFileURL(nsIFileURL **aFileURL)
00274 {
00275   nsCOMPtr<nsILocalFile> file(do_CreateInstance("@mozilla.org/file/local;1"));
00276   NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
00277   file->InitWithNativePath(mFile);
00278 
00279   nsCOMPtr<nsIURI> uri;
00280   NS_NewFileURI(getter_AddRefs(uri), file);
00281   nsCOMPtr<nsIFileURL> fileURL(do_QueryInterface(uri));
00282   NS_ENSURE_TRUE(fileURL, NS_ERROR_FAILURE);
00283   
00284   NS_ADDREF(*aFileURL = fileURL);
00285 
00286   return NS_OK;
00287 }
00288 
00289 //-------------------------------------------------------------------------
00290 //
00291 // Get the file + path
00292 //
00293 //-------------------------------------------------------------------------
00294 NS_IMETHODIMP nsFilePicker::SetDefaultString(const nsAString& aString)
00295 {
00296   mDefault = aString;
00297   return NS_OK;
00298 }
00299 
00300 NS_IMETHODIMP nsFilePicker::GetDefaultString(nsAString& aString)
00301 {
00302   return NS_ERROR_FAILURE;
00303 }
00304 
00305 //-------------------------------------------------------------------------
00306 //
00307 // The default extension to use for files
00308 //
00309 //-------------------------------------------------------------------------
00310 NS_IMETHODIMP nsFilePicker::GetDefaultExtension(nsAString& aExtension)
00311 {
00312   aExtension = mDefaultExtension;
00313   return NS_OK;
00314 }
00315 
00316 NS_IMETHODIMP nsFilePicker::SetDefaultExtension(const nsAString& aExtension)
00317 {
00318        mDefaultExtension = aExtension;
00319   return NS_OK;
00320 }
00321 
00322 //-------------------------------------------------------------------------
00323 void nsFilePicker::InitNative(nsIWidget *aParent,
00324                               const nsAString& aTitle,
00325                               PRInt16 aMode)
00326 {
00327        mParentWidget = (PtWidget_t *)aParent->GetNativeData(NS_NATIVE_WIDGET);
00328   mTitle.SetLength(0);
00329   mTitle.Append(aTitle);
00330   mMode = aMode;
00331 }
00332 
00333 
00334 NS_IMETHODIMP
00335 nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter)
00336 {
00337   mFilterList.Append(aFilter);
00338        mFilterList.Append(PRUnichar(' '));
00339 
00340   return NS_OK;
00341 }
00342 
00343 
00344 //-------------------------------------------------------------------------
00345 //
00346 // Set the filter index
00347 //
00348 //-------------------------------------------------------------------------
00349 NS_IMETHODIMP nsFilePicker::GetFilterIndex(PRInt32 *aFilterIndex)
00350 {
00351   return NS_OK;
00352 }
00353 
00354 NS_IMETHODIMP nsFilePicker::SetFilterIndex(PRInt32 aFilterIndex)
00355 {
00356   return NS_OK;
00357 }