1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3
* The contents of this file are subject to the Mozilla Public
4
* License Version 1.1 (the "License"); you may not use this file
5
* except in compliance with the License. You may obtain a copy of
6
* the License at http://www.mozilla.org/MPL/
8
* Software distributed under the License is distributed on an "AS
9
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10
* implied. See the License for the specific language governing
11
* rights and limitations under the License.
13
* The Original Code is the Mozilla browser.
15
* The Initial Developer of the Original Code is Netscape
16
* Communications Corporation. Portions created by Netscape are
17
* Copyright (C) 2001 Netscape Communications Corporation. All
21
* Adrian Mardare <amardare@qnx.com>
26
#include "nsReadableUtils.h"
27
#include "nsNetUtil.h"
29
#include "nsIServiceManager.h"
30
#include "nsIPlatformCharset.h"
31
#include "nsFilePicker.h"
32
#include "nsILocalFile.h"
34
#include "nsIFileURL.h"
35
#include "nsIStringBundle.h"
36
#include "nsEnumeratorUtils.h"
40
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
42
NS_IMPL_ISUPPORTS1(nsFilePicker, nsIFilePicker)
44
char nsFilePicker::mLastUsedDirectory[PATH_MAX+1] = { 0 };
46
#define MAX_EXTENSION_LENGTH PATH_MAX
48
//-------------------------------------------------------------------------
50
// nsFilePicker constructor
52
//-------------------------------------------------------------------------
53
nsFilePicker::nsFilePicker()
54
: mParentWidget( nsnull )
55
, mUnicodeEncoder(nsnull)
56
, mUnicodeDecoder(nsnull)
58
mDisplayDirectory = do_CreateInstance("@mozilla.org/file/local;1");
59
char *path = getenv( "HOME" );
61
mDisplayDirectory->InitWithNativePath( nsDependentCString(path) );
65
//-------------------------------------------------------------------------
67
// nsFilePicker destructor
69
//-------------------------------------------------------------------------
70
nsFilePicker::~nsFilePicker()
72
NS_IF_RELEASE(mUnicodeEncoder);
73
NS_IF_RELEASE(mUnicodeDecoder);
76
//-------------------------------------------------------------------------
78
// Show - Display the file dialog
80
//-------------------------------------------------------------------------
81
NS_IMETHODIMP nsFilePicker::Show(PRInt16 *aReturnVal)
86
NS_ENSURE_ARG_POINTER(aReturnVal);
88
if (mMode == modeGetFolder) {
89
flags |= Pt_FSR_SELECT_DIRS|Pt_FSR_NO_SELECT_FILES;
92
else if (mMode == modeOpen) {
95
else if (mMode == modeSave) {
96
flags |= Pt_FSR_NO_FCHECK;
99
else if( mMode == modeOpenMultiple ) {
100
flags |= Pt_FSR_MULTIPLE;
104
printf("nsFilePicker::Show() wrong mode");
108
char *title = ConvertToFileSystemCharset(mTitle);
110
title = ToNewCString(mTitle);
112
nsCAutoString initialDir;
113
mDisplayDirectory->GetNativePath(initialDir);
114
// If no display directory, re-use the last one.
115
if(initialDir.IsEmpty()) {
116
// Allocate copy of last used dir.
117
initialDir = mLastUsedDirectory;
120
if( !mDefault.IsEmpty() ) {
121
initialDir.AppendWithConversion( NS_LITERAL_STRING( "/" ) );
122
initialDir.AppendWithConversion( mDefault );
125
char extensionBuffer[MAX_EXTENSION_LENGTH+1] = "*";
126
if( !mFilterList.IsEmpty() ) {
127
char *text = ConvertToFileSystemCharset( mFilterList );
129
extensionBuffer[0] = 0;
131
/* eliminate the ';' and the duplicates */
132
char buffer[MAX_EXTENSION_LENGTH+1], buf[MAX_EXTENSION_LENGTH+1], *q, *delims = "; ", *dummy;
133
strcpy( buffer, text );
134
q = strtok_r( buffer, delims, &dummy );
136
sprintf( buf, "%s ", q );
137
if( !strstr( extensionBuffer, buf ) )
138
strcat( extensionBuffer, buf );
139
q = strtok_r( NULL, delims, &dummy );
142
nsMemory::Free( text );
145
else if (!mDefaultExtension.IsEmpty()) {
146
// Someone was cool and told us what to do
147
char *convertedExt = ConvertToFileSystemCharset(mDefaultExtension);
149
mDefaultExtension.ToCString(extensionBuffer, MAX_EXTENSION_LENGTH);
152
PL_strncpyz(extensionBuffer, convertedExt, MAX_EXTENSION_LENGTH+1);
153
nsMemory::Free( convertedExt );
157
PtFileSelectionInfo_t info;
158
memset( &info, 0, sizeof( info ) );
160
if( PtFileSelection( mParentWidget, NULL, title, initialDir.get(),
161
extensionBuffer, btn1, "&Cancel", "nsd", &info, flags ) ) {
162
if (title) nsMemory::Free( title );
163
return NS_ERROR_FAILURE;
166
*aReturnVal = returnOK;
168
if( info.ret == Pt_FSDIALOG_BTN2 ) {
169
*aReturnVal = returnCancel;
171
else if( mMode != modeOpenMultiple ) {
173
mFile.Append( info.path );
175
if( mMode == modeSave ) {
176
nsCOMPtr<nsILocalFile> file(do_CreateInstance("@mozilla.org/file/local;1"));
177
NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
179
file->InitWithNativePath( mFile );
181
PRBool exists = PR_FALSE;
182
file->Exists(&exists);
184
*aReturnVal = returnReplace;
187
else { /* here mMode is modeOpenMultiple */
188
PtFileSelectorInfo_t *minfo = info.minfo;
190
nsresult rv = NS_NewISupportsArray(getter_AddRefs(mFiles));
191
NS_ENSURE_SUCCESS(rv,rv);
193
for( int i=0; i<minfo->nitems; i++ ) {
194
nsCOMPtr<nsILocalFile> file = do_CreateInstance("@mozilla.org/file/local;1", &rv);
195
NS_ENSURE_SUCCESS(rv,rv);
197
nsCString s ( minfo->multipath[i] );
198
rv = file->InitWithNativePath( s );
199
NS_ENSURE_SUCCESS(rv,rv);
201
rv = mFiles->AppendElement(file);
202
NS_ENSURE_SUCCESS(rv,rv);
205
PtFSFreeInfo( &info ); /* clean the info structure if the multiple mode is set */
209
PL_strncpyz( mLastUsedDirectory, info.path, PATH_MAX+1 );
210
mDisplayDirectory->InitWithNativePath( nsDependentCString(mLastUsedDirectory) );
212
if( title ) nsMemory::Free( title );
216
// TODO: implement filters
221
NS_IMETHODIMP nsFilePicker::GetFile(nsILocalFile **aFile)
223
NS_ENSURE_ARG_POINTER(aFile);
228
nsCOMPtr<nsILocalFile> file(do_CreateInstance("@mozilla.org/file/local;1"));
230
NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
232
file->InitWithNativePath(mFile);
234
NS_ADDREF(*aFile = file);
239
NS_IMETHODIMP nsFilePicker::GetFiles(nsISimpleEnumerator **aFiles)
241
NS_ENSURE_ARG_POINTER(aFiles);
242
return NS_NewArrayEnumerator(aFiles, mFiles);
245
//-------------------------------------------------------------------------
246
NS_IMETHODIMP nsFilePicker::GetFileURL(nsIFileURL **aFileURL)
248
nsCOMPtr<nsILocalFile> file(do_CreateInstance("@mozilla.org/file/local;1"));
249
NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
250
file->InitWithNativePath(mFile);
252
nsCOMPtr<nsIURI> uri;
253
NS_NewFileURI(getter_AddRefs(uri), file);
254
nsCOMPtr<nsIFileURL> fileURL(do_QueryInterface(uri));
255
NS_ENSURE_TRUE(fileURL, NS_ERROR_FAILURE);
257
NS_ADDREF(*aFileURL = fileURL);
262
//-------------------------------------------------------------------------
264
// Get the file + path
266
//-------------------------------------------------------------------------
267
NS_IMETHODIMP nsFilePicker::SetDefaultString(const nsAString& aString)
273
NS_IMETHODIMP nsFilePicker::GetDefaultString(nsAString& aString)
275
return NS_ERROR_FAILURE;
278
//-------------------------------------------------------------------------
280
// The default extension to use for files
282
//-------------------------------------------------------------------------
283
NS_IMETHODIMP nsFilePicker::GetDefaultExtension(nsAString& aExtension)
285
aExtension = mDefaultExtension;
289
NS_IMETHODIMP nsFilePicker::SetDefaultExtension(const nsAString& aExtension)
291
mDefaultExtension = aExtension;
295
//-------------------------------------------------------------------------
297
// Set the display directory
299
//-------------------------------------------------------------------------
300
NS_IMETHODIMP nsFilePicker::SetDisplayDirectory(nsILocalFile *aDirectory)
302
mDisplayDirectory = aDirectory;
306
//-------------------------------------------------------------------------
308
// Get the display directory
310
//-------------------------------------------------------------------------
311
NS_IMETHODIMP nsFilePicker::GetDisplayDirectory(nsILocalFile **aDirectory)
313
*aDirectory = mDisplayDirectory;
314
NS_IF_ADDREF(*aDirectory);
318
//-------------------------------------------------------------------------
319
void nsFilePicker::InitNative(nsIWidget *aParent,
320
const nsAString& aTitle,
323
mParentWidget = (PtWidget_t *)aParent->GetNativeData(NS_NATIVE_WIDGET);
325
mTitle.Append(aTitle);
331
nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter)
333
mFilterList.Append(aFilter);
334
mFilterList.Append(PRUnichar(' '));
340
//-------------------------------------------------------------------------
341
void nsFilePicker::GetFileSystemCharset(nsCString & fileSystemCharset)
343
static nsCAutoString aCharset;
346
if (aCharset.Length() < 1) {
347
nsCOMPtr <nsIPlatformCharset> platformCharset = do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
348
if (NS_SUCCEEDED(rv))
349
rv = platformCharset->GetCharset(kPlatformCharsetSel_FileName, aCharset);
351
NS_ASSERTION(NS_SUCCEEDED(rv), "error getting platform charset");
353
aCharset.Assign(NS_LITERAL_CSTRING("windows-1252"));
355
fileSystemCharset = aCharset;
359
//-------------------------------------------------------------------------
360
char * nsFilePicker::ConvertToFileSystemCharset(const nsAString& inString)
362
char *outString = nsnull;
365
// get file system charset and create a unicode encoder
366
if (nsnull == mUnicodeEncoder) {
367
nsCAutoString fileSystemCharset;
368
GetFileSystemCharset(fileSystemCharset);
370
nsCOMPtr<nsICharsetConverterManager> ccm =
371
do_GetService(kCharsetConverterManagerCID, &rv);
372
if (NS_SUCCEEDED(rv)) {
373
rv = ccm->GetUnicodeEncoderRaw(fileSystemCharset.get(), &mUnicodeEncoder);
377
// converts from unicode to the file system charset
378
if (NS_SUCCEEDED(rv)) {
379
PRInt32 inLength = inString.Length();
381
const nsAFlatString& flatInString = PromiseFlatString(inString);
384
rv = mUnicodeEncoder->GetMaxLength(flatInString.get(), inLength,
386
if (NS_SUCCEEDED(rv)) {
387
outString = NS_STATIC_CAST( char*, nsMemory::Alloc( outLength+1 ) );
388
if (nsnull == outString) {
391
rv = mUnicodeEncoder->Convert(flatInString.get(), &inLength, outString,
393
if (NS_SUCCEEDED(rv)) {
394
outString[outLength] = '\0';
399
return NS_SUCCEEDED(rv) ? outString : nsnull;
402
//-------------------------------------------------------------------------
403
PRUnichar * nsFilePicker::ConvertFromFileSystemCharset(const char *inString)
405
PRUnichar *outString = nsnull;
408
// get file system charset and create a unicode encoder
409
if (nsnull == mUnicodeDecoder) {
410
nsCAutoString fileSystemCharset;
411
GetFileSystemCharset(fileSystemCharset);
413
nsCOMPtr<nsICharsetConverterManager> ccm =
414
do_GetService(kCharsetConverterManagerCID, &rv);
415
if (NS_SUCCEEDED(rv)) {
416
rv = ccm->GetUnicodeDecoderRaw(fileSystemCharset.get(), &mUnicodeDecoder);
420
// converts from the file system charset to unicode
421
if (NS_SUCCEEDED(rv)) {
422
PRInt32 inLength = strlen(inString);
424
rv = mUnicodeDecoder->GetMaxLength(inString, inLength, &outLength);
425
if (NS_SUCCEEDED(rv)) {
426
outString = NS_STATIC_CAST( PRUnichar*, nsMemory::Alloc( (outLength+1) * sizeof( PRUnichar ) ) );
427
if (nsnull == outString) {
430
rv = mUnicodeDecoder->Convert(inString, &inLength, outString, &outLength);
431
if (NS_SUCCEEDED(rv)) {
432
outString[outLength] = 0;
437
NS_ASSERTION(NS_SUCCEEDED(rv), "error charset conversion");
438
return NS_SUCCEEDED(rv) ? outString : nsnull;
441
//-------------------------------------------------------------------------
443
// Set the filter index
445
//-------------------------------------------------------------------------
446
NS_IMETHODIMP nsFilePicker::GetFilterIndex(PRInt32 *aFilterIndex)
451
NS_IMETHODIMP nsFilePicker::SetFilterIndex(PRInt32 aFilterIndex)