Adding new files for C++ rewrite of filepicker. Not part of the build.

This commit is contained in:
bryner%netscape.com 2001-11-01 07:54:40 +00:00
Родитель 64680b4760
Коммит 0ac7672293
6 изменённых файлов: 1340 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,52 @@
#! gmake
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla 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/MPL/
#
# 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.
# Portions created by the Initial Developer are Copyright (C) 2001
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Brian Ryner <bryner@netscape.com>
#
# 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 MPL, 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 MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = filepicker
XPIDL_MODULE = filepicker
XPIDLSRCS = nsIFileView.idl
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,47 @@
#!nmake
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla 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/MPL/
#
# 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):
# Brian Ryner <bryner@netscape.com>
#
# 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 MPL, 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 MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH=..\..\..\..
MODULE= filepicker
include <$(DEPTH)\config\config.mak>
XPIDLSRCS= .\nsIFileView.idl
include <$(DEPTH)\config\rules.mak>

Просмотреть файл

@ -0,0 +1,66 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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):
* Brian Ryner <bryner@netscape.com>
*
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIFile;
[scriptable, uuid(60b320d2-1dd2-11b2-bd73-dc3575f78ddd)]
interface nsIFileView : nsISupports
{
const short sortName = 0;
const short sortSize = 1;
const short sortDate = 2;
attribute boolean showHiddenFiles;
attribute boolean showOnlyDirectories;
readonly attribute short sortType;
readonly attribute boolean reverseSort;
void sort(in short sortType, in boolean reverseSort);
void setDirectory(in nsIFile directory);
void setFilter(in wstring filterString);
nsIFile getSelectedFile();
};
%{C++
#define NS_FILEVIEW_CONTRACTID "@mozilla.org/filepicker/fileview;1"
%}

Просмотреть файл

@ -0,0 +1,761 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 Communicationsm Corporation.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Ryner <bryner@netscape.com>
*
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIFileView.h"
#include "nsIOutlinerView.h"
#include "nsIGenericFactory.h"
#include "nsIOutlinerSelection.h"
#include "nsIOutlinerBoxObject.h"
#include "nsIFile.h"
#include "nsString.h"
#include "nsReadableUtils.h"
#include "prmem.h"
#include "nsPrintfCString.h"
#include "nsVoidArray.h"
#include "nsIDateTimeFormat.h"
#include "nsDateTimeFormatCID.h"
#include "nsQuickSort.h"
#include "nsWildCard.h"
#define NS_FILEVIEW_CID { 0xa5570462, 0x1dd1, 0x11b2, \
{ 0x9d, 0x19, 0xdf, 0x30, 0xa2, 0x7f, 0xbd, 0xc4 } }
static NS_DEFINE_CID(kDateTimeFormatCID, NS_DATETIMEFORMAT_CID);
class nsFileView : public nsIFileView,
public nsIOutlinerView
{
public:
nsFileView();
nsresult Init();
NS_DECL_ISUPPORTS
NS_DECL_NSIFILEVIEW
NS_DECL_NSIOUTLINERVIEW
protected:
virtual ~nsFileView();
PRInt32 FilterFiles();
void ReverseArray(nsISupportsArray* aArray);
void SortArray(nsISupportsArray* aArray);
void SortInternal();
nsCOMPtr<nsISupportsArray> mFileList;
nsCOMPtr<nsISupportsArray> mDirList;
nsCOMPtr<nsISupportsArray> mFilteredFiles;
nsCOMPtr<nsIFile> mDirectoryPath;
nsCOMPtr<nsIOutlinerBoxObject> mOutliner;
nsCOMPtr<nsIOutlinerSelection> mSelection;
nsCOMPtr<nsIAtom> mDirectoryAtom;
nsCOMPtr<nsIAtom> mFileAtom;
nsCOMPtr<nsIDateTimeFormat> mDateFormatter;
PRInt16 mSortType;
PRInt32 mTotalRows;
nsVoidArray mCurrentFilters;
PRPackedBool mShowHiddenFiles;
PRPackedBool mDirectoryFilter;
PRPackedBool mReverseSort;
};
// Factory constructor
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsFileView, Init)
static nsModuleComponentInfo components[] =
{
{ "nsFileView", NS_FILEVIEW_CID,
NS_FILEVIEW_CONTRACTID, nsFileViewConstructor }
};
NS_IMPL_NSGETMODULE(nsFileViewModule, components);
nsFileView::nsFileView() :
mSortType(-1),
mTotalRows(0),
mShowHiddenFiles(PR_FALSE),
mDirectoryFilter(PR_FALSE),
mReverseSort(PR_FALSE)
{
NS_INIT_ISUPPORTS();
}
nsFileView::~nsFileView()
{
PRInt32 count = mCurrentFilters.Count();
for (PRInt32 i = 0; i < count; ++i)
PR_Free(mCurrentFilters[i]);
}
nsresult
nsFileView::Init()
{
mDirectoryAtom = NS_NewAtom("directory");
mFileAtom = NS_NewAtom("file");
NS_NewISupportsArray(getter_AddRefs(mFileList));
NS_NewISupportsArray(getter_AddRefs(mDirList));
NS_NewISupportsArray(getter_AddRefs(mFilteredFiles));
mDateFormatter = do_CreateInstance(kDateTimeFormatCID);
return NS_OK;
}
// nsISupports implementation
NS_INTERFACE_MAP_BEGIN(nsFileView)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIFileView)
NS_INTERFACE_MAP_ENTRY(nsIFileView)
NS_INTERFACE_MAP_ENTRY(nsIOutlinerView)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsFileView)
NS_IMPL_RELEASE(nsFileView)
// nsIFileView implementation
NS_IMETHODIMP
nsFileView::SetShowHiddenFiles(PRBool aShowHidden)
{
mShowHiddenFiles = aShowHidden;
// This could be better optimized, but since the hidden
// file functionality is not currently used, this will be fine.
SetDirectory(mDirectoryPath);
return NS_OK;
}
NS_IMETHODIMP
nsFileView::GetShowHiddenFiles(PRBool* aShowHidden)
{
*aShowHidden = mShowHiddenFiles;
return NS_OK;
}
NS_IMETHODIMP
nsFileView::SetShowOnlyDirectories(PRBool aOnlyDirs)
{
if (aOnlyDirs == mDirectoryFilter)
return NS_OK;
mDirectoryFilter = aOnlyDirs;
PRUint32 dirCount;
mDirList->Count(&dirCount);
if (mDirectoryFilter) {
PRInt32 rowDiff = mTotalRows - dirCount;
mFilteredFiles->Clear();
mTotalRows = dirCount;
if (mOutliner)
mOutliner->RowCountChanged(mTotalRows, -rowDiff);
} else {
// Run the filter again to get the file list back
PRInt32 rowsAdded = FilterFiles();
if (rowsAdded)
mOutliner->RowCountChanged(dirCount, rowsAdded);
}
return NS_OK;
}
NS_IMETHODIMP
nsFileView::GetShowOnlyDirectories(PRBool* aOnlyDirs)
{
*aOnlyDirs = mDirectoryFilter;
return NS_OK;
}
NS_IMETHODIMP
nsFileView::GetSortType(PRInt16* aSortType)
{
*aSortType = mSortType;
return NS_OK;
}
NS_IMETHODIMP
nsFileView::GetReverseSort(PRBool* aReverseSort)
{
*aReverseSort = mReverseSort;
return NS_OK;
}
NS_IMETHODIMP
nsFileView::Sort(PRInt16 aSortType, PRBool aReverseSort)
{
if (aSortType == mSortType) {
if (aReverseSort != mReverseSort) {
mReverseSort = aReverseSort;
ReverseArray(mDirList);
ReverseArray(mFilteredFiles);
} else
return NS_OK;
} else {
mSortType = aSortType;
mReverseSort = aReverseSort;
SortInternal();
}
if (mOutliner)
mOutliner->Invalidate();
return NS_OK;
}
NS_IMETHODIMP
nsFileView::SetDirectory(nsIFile* aDirectory)
{
mDirectoryPath = aDirectory;
mFileList->Clear();
mDirList->Clear();
nsCOMPtr<nsISimpleEnumerator> dirEntries;
mDirectoryPath->GetDirectoryEntries(getter_AddRefs(dirEntries));
PRBool hasMore = PR_FALSE;
PRInt32 dirCount = 0, fileCount = 0;
while (NS_SUCCEEDED(dirEntries->HasMoreElements(&hasMore)) && hasMore) {
nsCOMPtr<nsISupports> nextItem;
dirEntries->GetNext(getter_AddRefs(nextItem));
nsCOMPtr<nsIFile> theFile = do_QueryInterface(nextItem);
PRBool isDirectory;
theFile->IsDirectory(&isDirectory);
if (isDirectory) {
PRBool isHidden;
theFile->IsHidden(&isHidden);
if (mShowHiddenFiles || !isHidden) {
mDirList->AppendElement(theFile);
++dirCount;
}
}
else {
mFileList->AppendElement(theFile);
++fileCount;
}
}
PRInt32 oldRows = mTotalRows;
FilterFiles();
SortInternal();
if (mOutliner) {
mOutliner->RowCountChanged(0, -oldRows);
mOutliner->RowCountChanged(0, mTotalRows);
}
return NS_OK;
}
NS_IMETHODIMP
nsFileView::SetFilter(const PRUnichar* aFilterString)
{
PRInt32 filterCount = mCurrentFilters.Count();
for (PRInt32 i = 0; i < filterCount; ++i)
PR_Free(mCurrentFilters[i]);
mCurrentFilters.Clear();
const PRUnichar* chr, *aPos = aFilterString;
for (chr = aFilterString; *chr; ++chr) {
if (*chr == ';') {
PRUnichar* aNewString = nsCRT::strndup(aPos, (chr - aPos));
mCurrentFilters.AppendElement(aNewString);
// ; will be followed by a space, and then the next filter
chr += 2;
aPos = chr;
}
}
if ((aPos < chr) && *aPos) {
PRUnichar* aNewString = nsCRT::strndup(aPos, (chr - aPos));
mCurrentFilters.AppendElement(aNewString);
}
mFilteredFiles->Clear();
PRUint32 dirCount;
mDirList->Count(&dirCount);
PRInt32 oldFileRows = mTotalRows - dirCount;
PRInt32 newFileRows = FilterFiles();
SortArray(mFilteredFiles);
if (mReverseSort)
ReverseArray(mFilteredFiles);
if (mOutliner) {
mOutliner->RowCountChanged(dirCount, newFileRows - oldFileRows);
PRInt32 commonRange = PR_MIN(newFileRows, oldFileRows);
if (commonRange)
mOutliner->InvalidateRange(dirCount, dirCount + commonRange);
}
return NS_OK;
}
NS_IMETHODIMP
nsFileView::GetSelectedFile(nsIFile** aFile)
{
*aFile = nsnull;
PRInt32 currentIndex;
mSelection->GetCurrentIndex(&currentIndex);
if (0 <= currentIndex) {
PRUint32 dirCount;
mDirList->Count(&dirCount);
if (currentIndex < (PRInt32) dirCount) {
nsCOMPtr<nsISupports> elem = dont_AddRef(mDirList->ElementAt(currentIndex));
CallQueryInterface(elem, aFile);
} else {
PRUint32 fileCount;
mFilteredFiles->Count(&fileCount);
if ((currentIndex - dirCount) < fileCount) {
nsCOMPtr<nsISupports> elem = dont_AddRef(mFilteredFiles->ElementAt(currentIndex - dirCount));
CallQueryInterface(elem, aFile);
}
}
}
return NS_OK;
}
// nsIOutlinerView implementation
NS_IMETHODIMP
nsFileView::GetRowCount(PRInt32* aRowCount)
{
*aRowCount = mTotalRows;
return NS_OK;
}
NS_IMETHODIMP
nsFileView::GetSelection(nsIOutlinerSelection** aSelection)
{
*aSelection = mSelection;
NS_IF_ADDREF(*aSelection);
return NS_OK;
}
NS_IMETHODIMP
nsFileView::SetSelection(nsIOutlinerSelection* aSelection)
{
mSelection = aSelection;
return NS_OK;
}
NS_IMETHODIMP
nsFileView::GetRowProperties(PRInt32 aIndex,
nsISupportsArray* aProperties)
{
return NS_OK;
}
NS_IMETHODIMP
nsFileView::GetCellProperties(PRInt32 aRow, const PRUnichar* aColID,
nsISupportsArray* aProperties)
{
PRUint32 dirCount;
mDirList->Count(&dirCount);
PRUint32 fileCount;
mFilteredFiles->Count(&fileCount);
if (aRow < (PRInt32) dirCount)
aProperties->AppendElement(mDirectoryAtom);
else if ((aRow - dirCount) < fileCount)
aProperties->AppendElement(mFileAtom);
return NS_OK;
}
NS_IMETHODIMP
nsFileView::GetColumnProperties(const PRUnichar* aColID,
nsIDOMElement* aColElement,
nsISupportsArray* aProperties)
{
return NS_OK;
}
NS_IMETHODIMP
nsFileView::IsContainer(PRInt32 aIndex, PRBool* aIsContainer)
{
*aIsContainer = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsFileView::IsContainerOpen(PRInt32 aIndex, PRBool* aIsOpen)
{
*aIsOpen = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsFileView::IsContainerEmpty(PRInt32 aIndex, PRBool* aIsEmpty)
{
*aIsEmpty = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsFileView::IsSeparator(PRInt32 aIndex, PRBool* aIsSeparator)
{
*aIsSeparator = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsFileView::IsSorted(PRBool* aIsSorted)
{
*aIsSorted = (mSortType >= 0);
return NS_OK;
}
NS_IMETHODIMP
nsFileView::CanDropOn(PRInt32 aIndex, PRBool* aCanDrop)
{
*aCanDrop = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsFileView::CanDropBeforeAfter(PRInt32 aIndex, PRBool aBefore,
PRBool* aCanDrop)
{
*aCanDrop = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsFileView::Drop(PRInt32 aRow, PRInt32 aOrientation)
{
return NS_OK;
}
NS_IMETHODIMP
nsFileView::GetParentIndex(PRInt32 aRowIndex, PRInt32* aParentIndex)
{
*aParentIndex = -1;
return NS_OK;
}
NS_IMETHODIMP
nsFileView::HasNextSibling(PRInt32 aRowIndex, PRInt32 aAfterIndex,
PRBool* aHasSibling)
{
*aHasSibling = (aAfterIndex < (mTotalRows - 1));
return NS_OK;
}
NS_IMETHODIMP
nsFileView::GetLevel(PRInt32 aIndex, PRInt32* aLevel)
{
*aLevel = 0;
return NS_OK;
}
NS_IMETHODIMP
nsFileView::GetCellText(PRInt32 aRow, const PRUnichar* aColID,
PRUnichar** aCellText)
{
PRUint32 dirCount, fileCount;
mDirList->Count(&dirCount);
mFilteredFiles->Count(&fileCount);
PRBool isDirectory;
nsCOMPtr<nsIFile> curFile;
if (aRow < (PRInt32) dirCount) {
isDirectory = PR_TRUE;
curFile = do_QueryElementAt(mDirList, aRow);
} else if ((aRow - dirCount) < fileCount) {
isDirectory = PR_FALSE;
curFile = do_QueryElementAt(mFilteredFiles, aRow - dirCount);
} else {
// invalid row
*aCellText = ToNewUnicode(NS_LITERAL_STRING(""));
return NS_OK;
}
if (NS_LITERAL_STRING("FilenameColumn").Equals(aColID)) {
curFile->GetUnicodeLeafName(aCellText);
} else if (NS_LITERAL_STRING("LastModifiedColumn").Equals(aColID)) {
PRInt64 lastModDate;
curFile->GetLastModificationDate(&lastModDate);
nsAutoString dateString;
mDateFormatter->FormatPRTime(nsnull, kDateFormatShort, kTimeFormatSeconds,
lastModDate * 1000, dateString);
*aCellText = ToNewUnicode(dateString);
} else if (NS_LITERAL_STRING("FileSizeColumn").Equals(aColID)) {
if (isDirectory)
*aCellText = ToNewUnicode(NS_LITERAL_STRING(""));
else {
PRInt64 fileSize;
curFile->GetFileSize(&fileSize);
*aCellText = ToNewUnicode(nsPrintfCString("%lld", fileSize));
}
} else
*aCellText = ToNewUnicode(NS_LITERAL_STRING(""));
return NS_OK;
}
NS_IMETHODIMP
nsFileView::SetOutliner(nsIOutlinerBoxObject* aOutliner)
{
mOutliner = aOutliner;
return NS_OK;
}
NS_IMETHODIMP
nsFileView::ToggleOpenState(PRInt32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsFileView::CycleHeader(const PRUnichar* aColID, nsIDOMElement* aElement)
{
return NS_OK;
}
NS_IMETHODIMP
nsFileView::SelectionChanged()
{
return NS_OK;
}
NS_IMETHODIMP
nsFileView::CycleCell(PRInt32 aRow, const PRUnichar* aColID)
{
return NS_OK;
}
NS_IMETHODIMP
nsFileView::IsEditable(PRInt32 aRow, const PRUnichar* aColID,
PRBool* aIsEditable)
{
*aIsEditable = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsFileView::SetCellText(PRInt32 aRow, const PRUnichar* aColID,
const PRUnichar* aValue)
{
return NS_OK;
}
NS_IMETHODIMP
nsFileView::PerformAction(const PRUnichar* aAction)
{
return NS_OK;
}
NS_IMETHODIMP
nsFileView::PerformActionOnRow(const PRUnichar* aAction, PRInt32 aRow)
{
return NS_OK;
}
NS_IMETHODIMP
nsFileView::PerformActionOnCell(const PRUnichar* aAction, PRInt32 aRow,
const PRUnichar* aColID)
{
return NS_OK;
}
// Private methods
PRInt32
nsFileView::FilterFiles()
{
PRUint32 count = 0, filteredFiles = 0;
mFileList->Count(&count);
mFilteredFiles->Clear();
PRInt32 filterCount = mCurrentFilters.Count();
for (PRUint32 i = 0; i < count; ++i) {
nsCOMPtr<nsIFile> aFile = do_QueryElementAt(mFileList, i);
PRBool isHidden = PR_FALSE;
if (!mShowHiddenFiles)
aFile->IsHidden(&isHidden);
nsXPIDLString unicodeLeafName;
aFile->GetUnicodeLeafName(getter_Copies(unicodeLeafName));
if (!isHidden) {
for (PRInt32 i = 0; i < filterCount; ++i) {
if (NS_WildCardMatch(unicodeLeafName.get(),
(const PRUnichar*) mCurrentFilters.ElementAt(i),
PR_TRUE) == MATCH) {
mFilteredFiles->AppendElement(aFile);
++filteredFiles;
break;
}
}
}
}
mDirList->Count(&count);
mTotalRows = count + filteredFiles;
return filteredFiles;
}
void
nsFileView::ReverseArray(nsISupportsArray* aArray)
{
PRUint32 count;
aArray->Count(&count);
for (PRUint32 i = 0; i < count/2; ++i) {
nsCOMPtr<nsISupports> element = dont_AddRef(aArray->ElementAt(i));
nsCOMPtr<nsISupports> element2 = dont_AddRef(aArray->ElementAt(count-i-1));
aArray->ReplaceElementAt(element2, i);
aArray->ReplaceElementAt(element, count-i-1);
}
}
PR_STATIC_CALLBACK(int)
SortNameCallback(const void* aElement1, const void* aElement2, void* aContext)
{
nsIFile* file1 = *NS_STATIC_CAST(nsIFile* const *, aElement1);
nsIFile* file2 = *NS_STATIC_CAST(nsIFile* const *, aElement2);
nsXPIDLString leafName1, leafName2;
file1->GetUnicodeLeafName(getter_Copies(leafName1));
file2->GetUnicodeLeafName(getter_Copies(leafName2));
return nsCRT::strcmp(leafName1.get(), leafName2.get());
}
PR_STATIC_CALLBACK(int)
SortSizeCallback(const void* aElement1, const void* aElement2, void* aContext)
{
nsIFile* file1 = *NS_STATIC_CAST(nsIFile* const *, aElement1);
nsIFile* file2 = *NS_STATIC_CAST(nsIFile* const *, aElement2);
PRInt64 size1, size2;
file1->GetFileSize(&size1);
file2->GetFileSize(&size2);
if (LL_EQ(size1, size2))
return 0;
return (LL_CMP(size1, <, size2) ? -1 : 1);
}
PR_STATIC_CALLBACK(int)
SortDateCallback(const void* aElement1, const void* aElement2, void* aContext)
{
nsIFile* file1 = *NS_STATIC_CAST(nsIFile* const *, aElement1);
nsIFile* file2 = *NS_STATIC_CAST(nsIFile* const *, aElement2);
PRInt64 date1, date2;
file1->GetLastModificationDate(&date1);
file2->GetLastModificationDate(&date2);
if (LL_EQ(date1, date2))
return 0;
return (LL_CMP(date1, <, date2) ? -1 : 1);
}
void
nsFileView::SortArray(nsISupportsArray* aArray)
{
// We assume the array to be in filesystem order, which
// for our purposes, is completely unordered.
int (*compareFunc)(const void*, const void*, void*);
switch (mSortType) {
case sortName:
compareFunc = SortNameCallback;
break;
case sortSize:
compareFunc = SortSizeCallback;
break;
case sortDate:
compareFunc = SortDateCallback;
break;
default:
return;
}
PRUint32 count;
aArray->Count(&count);
// each item will have an additional refcount while
// the array is alive.
nsIFile** array = new nsIFile*[count];
PRUint32 i;
for (i = 0; i < count; ++i) {
nsCOMPtr<nsISupports> item = aArray->ElementAt(i);
CallQueryInterface(item, &(array[i]));
}
NS_QuickSort(array, count, sizeof(nsIFile*), compareFunc, nsnull);
for (i = 0; i < count; ++i) {
aArray->ReplaceElementAt(array[i], i);
NS_RELEASE(array[i]);
}
delete[] array;
}
void
nsFileView::SortInternal()
{
SortArray(mDirList);
SortArray(mFilteredFiles);
if (mReverseSort) {
ReverseArray(mDirList);
ReverseArray(mFilteredFiles);
}
}

Просмотреть файл

@ -0,0 +1,296 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 ***** */
/* *
*
*
* shexp.c: shell-like wildcard match routines
*
* See shexp.h for public documentation.
*
* Rob McCool
*
*/
#include "nsWildCard.h"
#include "nsCRT.h"
#include "plstr.h"
#include "prmem.h"
/* ----------------------------- shexp_valid ------------------------------ */
static int
_valid_subexp(PRUnichar *expr, PRUnichar stop)
{
register int x,y,t;
int nsc,np,tld;
x=0;nsc=0;tld=0;
while(expr[x] && (expr[x] != stop)) {
switch(expr[x]) {
case '~':
if(tld) return INVALID_SXP;
else ++tld;
case '*':
case '?':
case '^':
case '$':
++nsc;
break;
case '[':
++nsc;
if((!expr[++x]) || (expr[x] == ']'))
return INVALID_SXP;
for(++x;expr[x] && (expr[x] != ']');++x)
if(expr[x] == '\\')
if(!expr[++x])
return INVALID_SXP;
if(!expr[x])
return INVALID_SXP;
break;
case '(':
++nsc;np = 0;
while(1) {
if(expr[++x] == ')')
return INVALID_SXP;
for(y=x;(expr[y]) && (expr[y] != '|') && (expr[y] != ')');++y)
if(expr[y] == '\\')
if(!expr[++y])
return INVALID_SXP;
if(!expr[y])
return INVALID_SXP;
if(expr[y] == '|')
++np;
t = _valid_subexp(&expr[x],expr[y]);
if(t == INVALID_SXP)
return INVALID_SXP;
x+=t;
if(expr[x] == ')') {
if(!np)
return INVALID_SXP;
break;
}
}
break;
case ')':
case ']':
return INVALID_SXP;
case '\\':
if(!expr[++x])
return INVALID_SXP;
default:
break;
}
++x;
}
if((!stop) && (!nsc))
return NON_SXP;
return ((expr[x] == stop) ? x : INVALID_SXP);
}
int
NS_WildCardValid(PRUnichar *expr)
{
int x;
x = _valid_subexp(expr, '\0');
return (x < 0 ? x : VALID_SXP);
}
/* ----------------------------- shexp_match ----------------------------- */
#define MATCH 0
#define NOMATCH 1
#define ABORTED -1
static int _shexp_match(const PRUnichar *str, const PRUnichar *expr,
PRBool case_insensitive);
static int
_handle_union(const PRUnichar *str, const PRUnichar *expr,
PRBool case_insensitive)
{
PRUnichar *e2 = (PRUnichar *) PR_Malloc(sizeof(PRUnichar)*nsCRT::strlen(expr));
register int t,p2,p1 = 1;
int cp;
while(1) {
for(cp=1;expr[cp] != ')';cp++)
if(expr[cp] == '\\')
++cp;
for(p2 = 0;(expr[p1] != '|') && (p1 != cp);p1++,p2++) {
if(expr[p1] == '\\')
e2[p2++] = expr[p1++];
e2[p2] = expr[p1];
}
for (t=cp+1; ((e2[p2] = expr[t]) != 0); ++t,++p2) {}
if(_shexp_match(str,e2, case_insensitive) == MATCH) {
PR_Free(e2);
return MATCH;
}
if(p1 == cp) {
PR_Free(e2);
return NOMATCH;
}
else ++p1;
}
}
static int
_shexp_match(const PRUnichar *str, const PRUnichar *expr,
PRBool case_insensitive)
{
register int x,y;
int ret,neg;
ret = 0;
for(x=0,y=0;expr[y];++y,++x) {
if((!str[x]) && (expr[y] != '(') && (expr[y] != '$') && (expr[y] != '*'))
ret = ABORTED;
else {
switch(expr[y]) {
case '$':
if( (str[x]) )
ret = NOMATCH;
else
--x; /* we don't want loop to increment x */
break;
case '*':
while(expr[++y] == '*'){}
if(!expr[y])
return MATCH;
while(str[x]) {
switch(_shexp_match(&str[x++],&expr[y], case_insensitive)) {
case NOMATCH:
continue;
case ABORTED:
ret = ABORTED;
break;
default:
return MATCH;
}
break;
}
if((expr[y] == '$') && (expr[y+1] == '\0') && (!str[x]))
return MATCH;
else
ret = ABORTED;
break;
case '[':
neg = ((expr[++y] == '^') && (expr[y+1] != ']'));
if (neg)
++y;
if ((isalnum(expr[y])) && (expr[y+1] == '-') &&
(isalnum(expr[y+2])) && (expr[y+3] == ']'))
{
int start = expr[y], end = expr[y+2];
/* Droolproofing for pinheads not included */
if(neg ^ ((str[x] < start) || (str[x] > end))) {
ret = NOMATCH;
break;
}
y+=3;
}
else {
int matched;
for (matched=0;expr[y] != ']';y++)
matched |= (str[x] == expr[y]);
if (neg ^ (!matched))
ret = NOMATCH;
}
break;
case '(':
return _handle_union(&str[x],&expr[y], case_insensitive);
break;
case '?':
break;
case '\\':
++y;
default:
if(case_insensitive)
{
if(toupper(str[x]) != toupper(expr[y]))
ret = NOMATCH;
}
else
{
if(str[x] != expr[y])
ret = NOMATCH;
}
break;
}
}
if(ret)
break;
}
return (ret ? ret : (str[x] ? NOMATCH : MATCH));
}
int
NS_WildCardMatch(const PRUnichar *str, const PRUnichar *xp,
PRBool case_insensitive) {
register int x;
PRUnichar *expr = nsCRT::strdup(xp);
if(!expr)
return 1;
for(x=nsCRT::strlen(expr)-1;x;--x) {
if((expr[x] == '~') && (expr[x-1] != '\\')) {
expr[x] = '\0';
if(_shexp_match(str,&expr[++x], case_insensitive) == MATCH)
goto punt;
break;
}
}
if(_shexp_match(str,expr, PR_FALSE) == MATCH) {
PR_Free(expr);
return 0;
}
punt:
PR_Free(expr);
return 1;
}

Просмотреть файл

@ -0,0 +1,118 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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 ***** */
/*
* shexp.h: Defines and prototypes for shell exp. match routines
*
*
* This routine will match a string with a shell expression. The expressions
* accepted are based loosely on the expressions accepted by zsh.
*
* o * matches anything
* o ? matches one character
* o \ will escape a special character
* o $ matches the end of the string
* o [abc] matches one occurence of a, b, or c. The only character that needs
* to be escaped in this is ], all others are not special.
* o [a-z] matches any character between a and z
* o [^az] matches any character except a or z
* o ~ followed by another shell expression will remove any pattern
* matching the shell expression from the match list
* o (foo|bar) will match either the substring foo, or the substring bar.
* These can be shell expressions as well.
*
* The public interface to these routines is documented below.
*
* Rob McCool
*
*/
#ifndef nsWildCard_h__
#define nsWildCard_h__
#include "prtypes.h"
#include "nscore.h"
#include <ctype.h> /* isalnum */
#include <string.h> /* strlen */
/* --------------------------- Public routines ---------------------------- */
/*
* NS_WildCardValid takes a shell expression exp as input. It returns:
*
* NON_SXP if exp is a standard string
* INVALID_SXP if exp is a shell expression, but invalid
* VALID_SXP if exp is a valid shell expression
*/
#define NON_SXP -1
#define INVALID_SXP -2
#define VALID_SXP 1
extern int NS_WildCardValid(PRUnichar *expr);
/* return values for the search routines */
#define MATCH 0
#define NOMATCH 1
#define ABORTED -1
/*
* NS_WildCardMatch
*
* Takes a prevalidated shell expression exp, and a string str.
*
* Returns 0 on match and 1 on non-match.
*/
extern int NS_WildCardMatch(const PRUnichar *str, const PRUnichar *expr,
PRBool case_insensitive);
/*
* Same as above, but validates the exp first. 0 on match, 1 on non-match,
* -1 on invalid exp.
*/
extern int NS_WildCardSearch(const PRUnichar *str, const PRUnichar *expr);
/*
* Same as above but uses case insensitive search.
*/
extern int NS_WildCardCaseSearch(const PRUnichar *str, const PRUnichar *expr);
#endif /* nsWildCard_h__ */