Compare commits
107 Commits
SUPERWIN
...
CacheInteg
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22c40d96b2 | ||
|
|
06a79b2069 | ||
|
|
ebc4face0d | ||
|
|
150696bb86 | ||
|
|
683045595b | ||
|
|
7f09538b93 | ||
|
|
bb364ef512 | ||
|
|
7c96c92a19 | ||
|
|
a6defdef4c | ||
|
|
76159a2caf | ||
|
|
1988cb05b5 | ||
|
|
dd8c6b3bed | ||
|
|
bc64749366 | ||
|
|
2e9287bd58 | ||
|
|
0f2274a140 | ||
|
|
957fa10cac | ||
|
|
e603146886 | ||
|
|
cb698a0df1 | ||
|
|
1b918d9ef0 | ||
|
|
6407144c9f | ||
|
|
2ed563a178 | ||
|
|
4becc0b508 | ||
|
|
7d5427ea31 | ||
|
|
99904bcc48 | ||
|
|
bcb56c9593 | ||
|
|
f18bc8e6cd | ||
|
|
7d14c5669a | ||
|
|
c0dd3df02e | ||
|
|
e5cc84978f | ||
|
|
5694537330 | ||
|
|
297c5ceba3 | ||
|
|
e0311312f7 | ||
|
|
cf3dc77b02 | ||
|
|
dd2506a737 | ||
|
|
b1bee1f21c | ||
|
|
48ecc5625b | ||
|
|
1b791685e6 | ||
|
|
dc94d1d6e2 | ||
|
|
f5b437ade3 | ||
|
|
8c0b4b3e4a | ||
|
|
fb640ab144 | ||
|
|
106e263b33 | ||
|
|
85045a8552 | ||
|
|
a2279be132 | ||
|
|
0ce702d402 | ||
|
|
f14d03cd67 | ||
|
|
b91343fdf6 | ||
|
|
2c517489b5 | ||
|
|
ae57da58eb | ||
|
|
8d4586dd65 | ||
|
|
9b473ad9be | ||
|
|
2ad227a994 | ||
|
|
94d8da33c1 | ||
|
|
81c05809fd | ||
|
|
e30547b2b2 | ||
|
|
257f9cfaaa | ||
|
|
96e2654e43 | ||
|
|
3b023433be | ||
|
|
1b89716afe | ||
|
|
ad02058877 | ||
|
|
fa8a3196e7 | ||
|
|
5c2c543e58 | ||
|
|
c588721cc0 | ||
|
|
0b049b17ba | ||
|
|
854ef4631d | ||
|
|
051c558653 | ||
|
|
37a04adb09 | ||
|
|
c823c04b45 | ||
|
|
03cbd000eb | ||
|
|
a91e91a1c7 | ||
|
|
be7a5a48b6 | ||
|
|
b2bc7468e8 | ||
|
|
9692dfd994 | ||
|
|
f3edd4cfb5 | ||
|
|
33403345c1 | ||
|
|
20c850de23 | ||
|
|
e8b619cd02 | ||
|
|
eed396bb92 | ||
|
|
41d44c070b | ||
|
|
698ba42268 | ||
|
|
1a0fd23991 | ||
|
|
67dded330b | ||
|
|
936ff4777a | ||
|
|
96c55e42f7 | ||
|
|
82fa0cf06a | ||
|
|
98c8285334 | ||
|
|
bad4b683f4 | ||
|
|
cb5269a28a | ||
|
|
74712f3635 | ||
|
|
9f8ea739db | ||
|
|
97a10dd7c6 | ||
|
|
85a132fac0 | ||
|
|
e594eee877 | ||
|
|
9148eee3d6 | ||
|
|
b5989a8382 | ||
|
|
2b861f60d9 | ||
|
|
87db050b37 | ||
|
|
ffe483cf95 | ||
|
|
52aa17a1c3 | ||
|
|
5fdb3aa69e | ||
|
|
8cae473bc0 | ||
|
|
0719303755 | ||
|
|
90d3e40858 | ||
|
|
c792b2d35c | ||
|
|
7a4377d840 | ||
|
|
a5fa416010 | ||
|
|
49d00db5e2 |
1153
mozilla/netwerk/base/src/nsFileTransport.cpp
Normal file
1153
mozilla/netwerk/base/src/nsFileTransport.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -26,42 +26,13 @@ VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = xpwidgets support
|
||||
|
||||
#
|
||||
# Dont build the DSO under the 'build' directory as windows does.
|
||||
#
|
||||
# The DSOs get built in the toolkit dir itself. Do this so that
|
||||
# multiple implementations of widget can be built on the same
|
||||
# source tree.
|
||||
#
|
||||
ifndef MOZ_MONOLITHIC_TOOLKIT
|
||||
|
||||
ifdef MOZ_ENABLE_GTK
|
||||
DIRS += gtksuperwin
|
||||
DIRS += gtk
|
||||
endif
|
||||
|
||||
ifdef MOZ_ENABLE_MOTIF
|
||||
DIRS += motif
|
||||
endif
|
||||
|
||||
ifdef MOZ_ENABLE_XLIB
|
||||
DIRS += xlib
|
||||
endif
|
||||
|
||||
ifdef MOZ_ENABLE_QT
|
||||
DIRS += qt
|
||||
endif
|
||||
|
||||
else
|
||||
DIRS += $(MOZ_WIDGET_TOOLKIT)
|
||||
endif
|
||||
|
||||
# unix_services are only useful in unix, duh...
|
||||
ifeq (,$(filter beos os2 rhapsody photon,$(MOZ_WIDGET_TOOLKIT)))
|
||||
DIRS += unix_services
|
||||
endif
|
||||
DIRS = \
|
||||
public \
|
||||
memcache \
|
||||
filecache \
|
||||
mgr \
|
||||
build \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
33
mozilla/netwerk/cache/Makefile.win
vendored
Executable file
33
mozilla/netwerk/cache/Makefile.win
vendored
Executable file
@@ -0,0 +1,33 @@
|
||||
#!gmake
|
||||
#
|
||||
# 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=..\..
|
||||
DIRS= \
|
||||
public \
|
||||
mgr \
|
||||
memcache \
|
||||
filecache \
|
||||
build \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
54
mozilla/netwerk/cache/build/Makefile.in
vendored
Normal file
54
mozilla/netwerk/cache/build/Makefile.in
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = nkcacke
|
||||
LIBRARY_NAME = necko_cache
|
||||
IS_COMPONENT = 1
|
||||
|
||||
CPPSRCS = nsNetDataCacheModule.cpp
|
||||
|
||||
SHARED_LIBRARY_LIBS = \
|
||||
$(DIST)/lib/libnkcachemgr_s.a \
|
||||
$(DIST)/lib/libnkfilecache_s.a \
|
||||
$(DIST)/lib/libnkmemcache_s.a \
|
||||
$(DIST)/lib/libmozdbm_s.a \
|
||||
$(DIST)/lib/libxpcomio_s.a \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(DEPTH)/netwerk/cache/memcache \
|
||||
-I$(DEPTH)/netwerk/cache/filecache \
|
||||
-I$(DEPTH)/netwerk/cache/mgr \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DSO_LDOPTS = \
|
||||
$(MKSHLIB_FORCE_ALL) \
|
||||
$(SHARED_LIBRARY_LIBS) \
|
||||
$(MKSHLIB_UNFORCE_ALL) \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
$(LIBRARY) $(SHARED_LIBRARY): $(SHARED_LIBRARY_LIBS) Makefile
|
||||
|
||||
51
mozilla/netwerk/cache/build/makefile.win
vendored
Normal file
51
mozilla/netwerk/cache/build/makefile.win
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
#!gmake
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
DEPTH=..\..\..
|
||||
MODULE=nkcache
|
||||
|
||||
MAKE_OBJ_TYPE=DLL
|
||||
DLLNAME=nkcache
|
||||
DLL=.\$(OBJDIR)\$(DLLNAME).dll
|
||||
|
||||
CPP_OBJS= \
|
||||
.\$(OBJDIR)\nsNetDataCacheModule.obj \
|
||||
$(NULL)
|
||||
|
||||
LLIBS= \
|
||||
$(DIST)\lib\nkcachemgr_s.lib \
|
||||
$(DIST)\lib\nkfilecache_s.lib \
|
||||
$(DIST)\lib\nkmemcache_s.lib \
|
||||
$(DIST)\lib\dbm32.lib \
|
||||
$(DIST)\lib\xpcom.lib \
|
||||
$(LIBNSPR)
|
||||
|
||||
INCS = $(INCS) \
|
||||
-I$(DEPTH)\netwerk\cache\memcache \
|
||||
-I$(DEPTH)\netwerk\cache\filecache \
|
||||
-I$(DEPTH)\netwerk\cache\mgr \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
install:: $(DLL)
|
||||
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin\components
|
||||
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib
|
||||
|
||||
49
mozilla/netwerk/cache/build/nsNetDataCacheModule.cpp
vendored
Normal file
49
mozilla/netwerk/cache/build/nsNetDataCacheModule.cpp
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIModule.h"
|
||||
#include "nscore.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIGenericFactory.h"
|
||||
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsINetDataCacheManager.h"
|
||||
#include "nsMemCacheCID.h"
|
||||
#include "nsMemCache.h"
|
||||
#include "nsNetDiskCache.h"
|
||||
#include "nsNetDiskCacheCID.h"
|
||||
#include "nsCacheManager.h"
|
||||
|
||||
// Factory method to create a new nsMemCache instance. Used
|
||||
// by nsNetDataCacheModule
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMemCache, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNetDiskCache, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsCacheManager, Init)
|
||||
|
||||
static nsModuleComponentInfo components[] = {
|
||||
{ "Memory Cache", NS_MEM_CACHE_FACTORY_CID, NS_NETWORK_MEMORY_CACHE_PROGID, nsMemCacheConstructor },
|
||||
{ "File Cache", NS_NETDISKCACHE_CID, NS_NETWORK_FILE_CACHE_PROGID, nsNetDiskCacheConstructor },
|
||||
{ "Cache Manager",NS_CACHE_MANAGER_CID, NS_NETWORK_CACHE_MANAGER_PROGID,nsCacheManagerConstructor }
|
||||
};
|
||||
|
||||
NS_IMPL_NSGETMODULE("Network Data Cache", components)
|
||||
60
mozilla/netwerk/cache/filecache/Makefile.in
vendored
Normal file
60
mozilla/netwerk/cache/filecache/Makefile.in
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
#
|
||||
# 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 Communicator.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Intel Corp.
|
||||
# Portions created by Intel Corp. are
|
||||
# Copyright (C) 1999, 1999 Intel Corp. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
# Carl Wong <carl.wong@intel.com>
|
||||
#
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
srcdir = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
LIBRARY_NAME = nkfilecache_s
|
||||
|
||||
REQUIRES = nspr dbm
|
||||
|
||||
EXTRA_DSO_LDOPTS += -L$(DIST)/lib -lmozdbm_s
|
||||
|
||||
EXPORTS=nsNetDiskCacheCID.h \
|
||||
nsNetDiskCache.h \
|
||||
nsIDBAccessor.h \
|
||||
nsDBAccessor.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
nsDBAccessor.cpp\
|
||||
nsDBEnumerator.cpp \
|
||||
nsNetDiskCache.cpp \
|
||||
nsDiskCacheRecord.cpp \
|
||||
nsDiskCacheRecordChannel.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_LIBS = $(NSPR_LIBS)
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a
|
||||
# static lib.
|
||||
override NO_SHARED_LIB=1
|
||||
override NO_STATIC_LIB=
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
44
mozilla/netwerk/cache/filecache/makefile.win
vendored
Normal file
44
mozilla/netwerk/cache/filecache/makefile.win
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=..\..\..
|
||||
|
||||
include <$(DEPTH)/config/config.mak>
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
LIBRARY_NAME = nkfilecache_s
|
||||
|
||||
CPP_OBJS= \
|
||||
.\$(OBJDIR)\nsDBAccessor.obj \
|
||||
.\$(OBJDIR)\nsDBEnumerator.obj \
|
||||
.\$(OBJDIR)\nsNetDiskCache.obj \
|
||||
.\$(OBJDIR)\nsDiskCacheRecord.obj \
|
||||
.\$(OBJDIR)\nsDiskCacheRecordChannel.obj \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS=nsNetDiskCacheCID.h
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
install:: $(LIBRARY)
|
||||
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
|
||||
|
||||
clobber::
|
||||
rm -rf $(OBJDIR)
|
||||
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib
|
||||
|
||||
416
mozilla/netwerk/cache/filecache/nsDBAccessor.cpp
vendored
Normal file
416
mozilla/netwerk/cache/filecache/nsDBAccessor.cpp
vendored
Normal file
@@ -0,0 +1,416 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of filecache implementation.
|
||||
*
|
||||
* nsIDBAccessor is a interface that shields all the direct database access
|
||||
* method from nsNetDiskCache.
|
||||
*
|
||||
* nsDBAccessor is a implementation of the nsIDBAccessor interface. It
|
||||
* uses dbm(Berkely) as the database.
|
||||
*
|
||||
* a nsDiskCacheRecord is mapped into two entries in the database,
|
||||
* key->recordID
|
||||
* recordID->metadata
|
||||
*/
|
||||
|
||||
#include "nsDBAccessor.h"
|
||||
#include "nscore.h"
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "plhash.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
nsDBAccessor::nsDBAccessor() :
|
||||
mDB(0) ,
|
||||
mDBFile(0) ,
|
||||
mSessionID(0) ,
|
||||
mSessionCntr(0) ,
|
||||
mDBFilesize(0)
|
||||
{
|
||||
mLastSyncTime = PR_IntervalNow() ;
|
||||
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsDBAccessor::~nsDBAccessor()
|
||||
{
|
||||
Shutdown() ;
|
||||
}
|
||||
|
||||
//
|
||||
// Implement nsISupports methods
|
||||
//
|
||||
NS_IMPL_ISUPPORTS(nsDBAccessor, NS_GET_IID(nsIDBAccessor))
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// nsIDBAccessor methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::Init(nsIFileSpec* dbfile)
|
||||
{
|
||||
char* dbname ;
|
||||
|
||||
// this should cover all platforms.
|
||||
dbfile->GetNativePath(&dbname) ;
|
||||
|
||||
mDBFile = dbfile ;
|
||||
|
||||
// FUR - how is page size chosen ? It's worth putting a comment
|
||||
// in here about the possible usefulness of tuning these parameters
|
||||
HASHINFO hash_info = {
|
||||
16*1024 , /* bucket size */
|
||||
0 , /* fill factor */
|
||||
0 , /* number of elements */
|
||||
0 , /* bytes to cache */
|
||||
0 , /* hash function */
|
||||
0} ; /* byte order */
|
||||
|
||||
mDB = dbopen(dbname,
|
||||
O_RDWR | O_CREAT ,
|
||||
0600 ,
|
||||
DB_HASH ,
|
||||
& hash_info) ;
|
||||
|
||||
nsCRT::free(dbname) ;
|
||||
|
||||
if(!mDB)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
// set mSessionID
|
||||
DBT db_key, db_data ;
|
||||
|
||||
db_key.data = NS_CONST_CAST(char*, SessionKey) ;
|
||||
db_key.size = PL_strlen(SessionKey) ;
|
||||
|
||||
int status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
|
||||
if(status == -1) {
|
||||
NS_ERROR("ERROR: failed get session id in database.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
if(status == 0) {
|
||||
// get the last session id
|
||||
PRInt16 *old_ID = NS_STATIC_CAST(PRInt16*, db_data.data) ;
|
||||
if(*old_ID < ini_sessionID) {
|
||||
NS_ERROR("ERROR: Bad Session ID in database, corrupted db.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
mSessionID = *old_ID + 1 ;
|
||||
}
|
||||
else if(status == 1) {
|
||||
// must be a new db
|
||||
mSessionID = ini_sessionID ;
|
||||
}
|
||||
db_data.data = NS_REINTERPRET_CAST(void*, &mSessionID) ;
|
||||
db_data.size = sizeof(PRInt16) ;
|
||||
|
||||
// store the new session id
|
||||
status = (*mDB->put)(mDB, &db_key, &db_data, 0) ;
|
||||
|
||||
if(status == 0) {
|
||||
(*mDB->sync)(mDB, 0) ;
|
||||
|
||||
// initialize database filesize
|
||||
return mDBFile->GetFileSize(&mDBFilesize) ;
|
||||
}
|
||||
else {
|
||||
NS_ERROR("reset session ID failure.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::Shutdown(void)
|
||||
{
|
||||
if(mDB) {
|
||||
(*mDB->sync)(mDB, 0) ;
|
||||
(*mDB->close)(mDB) ;
|
||||
mDB = nsnull ;
|
||||
}
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::Get(PRInt32 aID, void** anEntry, PRUint32 *aLength)
|
||||
{
|
||||
if(!anEntry)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*anEntry = nsnull ;
|
||||
*aLength = 0 ;
|
||||
|
||||
NS_ASSERTION(mDB, "no database") ;
|
||||
|
||||
DBT db_key, db_data ;
|
||||
|
||||
db_key.data = NS_REINTERPRET_CAST(void*, &aID) ;
|
||||
db_key.size = sizeof(PRInt32) ;
|
||||
|
||||
int status = 0 ;
|
||||
status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
|
||||
|
||||
if(status == 0) {
|
||||
*anEntry = db_data.data ;
|
||||
*aLength = db_data.size ;
|
||||
return NS_OK ;
|
||||
}
|
||||
else if(status == 1)
|
||||
return NS_OK ;
|
||||
else
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::Put(PRInt32 aID, void* anEntry, PRUint32 aLength)
|
||||
{
|
||||
NS_ASSERTION(mDB, "no database") ;
|
||||
|
||||
DBT db_key, db_data ;
|
||||
|
||||
db_key.data = NS_REINTERPRET_CAST(void*, &aID) ;
|
||||
db_key.size = sizeof(PRInt32) ;
|
||||
|
||||
db_data.data = anEntry ;
|
||||
db_data.size = aLength ;
|
||||
|
||||
if(0 == (*mDB->put)(mDB, &db_key, &db_data, 0)) {
|
||||
return Sync() ;
|
||||
}
|
||||
else {
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* It's more important to remove the id->metadata entry first since
|
||||
* key->id mapping is just a reference
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::Del(PRInt32 aID, void* anEntry, PRUint32 aLength)
|
||||
{
|
||||
NS_ASSERTION(mDB, "no database") ;
|
||||
|
||||
DBT db_key ;
|
||||
|
||||
// delete recordID->metadata
|
||||
db_key.data = NS_REINTERPRET_CAST(void*, &aID) ;
|
||||
db_key.size = sizeof(PRInt32) ;
|
||||
|
||||
PRInt32 status = -1 ;
|
||||
status = (*mDB->del)(mDB, &db_key, 0) ;
|
||||
|
||||
if(-1 == status) {
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
// delete key->recordID
|
||||
db_key.data = anEntry ;
|
||||
db_key.size = aLength ;
|
||||
status = (*mDB->del)(mDB, &db_key, 0) ;
|
||||
if(-1 == status) {
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
return Sync() ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::GetID(const char* key, PRUint32 length, PRInt32* aID)
|
||||
{
|
||||
NS_ASSERTION(mDB, "no database") ;
|
||||
|
||||
DBT db_key, db_data ;
|
||||
|
||||
db_key.data = NS_CONST_CAST(char*, key) ;
|
||||
db_key.size = length ;
|
||||
|
||||
int status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
|
||||
if(status == 0) {
|
||||
// found recordID
|
||||
*aID = *(NS_REINTERPRET_CAST(PRInt32*, db_data.data)) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
else if(status == 1) {
|
||||
// create a new one
|
||||
PRInt32 id = 0 ;
|
||||
id = mSessionID << 16 | mSessionCntr++ ;
|
||||
|
||||
// add new id into mDB
|
||||
db_data.data = NS_REINTERPRET_CAST(void*, &id) ;
|
||||
db_data.size = sizeof(PRInt32) ;
|
||||
|
||||
status = (*mDB->put)(mDB, &db_key, &db_data, 0) ;
|
||||
if(status != 0) {
|
||||
NS_ERROR("updating db failure.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
*aID = id ;
|
||||
return Sync() ;
|
||||
}
|
||||
else {
|
||||
NS_ERROR("ERROR: keydb failure.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::EnumEntry(void** anEntry, PRUint32* aLength, PRBool bReset)
|
||||
{
|
||||
if(!anEntry)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*anEntry = nsnull ;
|
||||
*aLength = 0 ;
|
||||
|
||||
NS_ASSERTION(mDB, "no database") ;
|
||||
|
||||
PRUint32 flag ;
|
||||
|
||||
if(bReset)
|
||||
flag = R_FIRST ;
|
||||
else
|
||||
flag = R_NEXT ;
|
||||
|
||||
DBT db_key, db_data ;
|
||||
|
||||
PRUint32 len = PL_strlen(SessionKey) ;
|
||||
|
||||
int status ;
|
||||
|
||||
do {
|
||||
status = (*mDB->seq)(mDB, &db_key, &db_data, flag) ;
|
||||
flag = R_NEXT ;
|
||||
if(status == -1)
|
||||
return NS_ERROR_FAILURE ;
|
||||
// get next if it's a key->recordID
|
||||
if(db_key.size > sizeof(PRInt32) && db_data.size == sizeof(PRInt32))
|
||||
continue ;
|
||||
// get next if it's a sessionID entry
|
||||
if(db_key.size == len && db_data.size == sizeof(PRInt16))
|
||||
continue ;
|
||||
// recordID is always 32 bits long
|
||||
if(db_key.size == sizeof(PRInt32))
|
||||
break ;
|
||||
} while(!status) ;
|
||||
|
||||
if (0 == status) {
|
||||
*anEntry = db_data.data ;
|
||||
*aLength = db_data.size ;
|
||||
}
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the cached database file size.
|
||||
* mDBFilesize will be updated during Sync().
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::GetDBFilesize(PRUint32* aSize)
|
||||
{
|
||||
*aSize = mDBFilesize ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::GetSpecialEntry(void** anEntry, PRUint32* aLength)
|
||||
{
|
||||
if(!anEntry)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*anEntry = nsnull ;
|
||||
*aLength = 0 ;
|
||||
|
||||
DBT db_key, db_data ;
|
||||
|
||||
db_key.data = NS_CONST_CAST(char*, SpecialEntry) ;
|
||||
db_key.size = PL_strlen(SpecialEntry) ;
|
||||
|
||||
int status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
|
||||
|
||||
if(status == -1) {
|
||||
NS_ERROR("ERROR: failed get special entry in database.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
if(status == 0) {
|
||||
*anEntry = db_data.data ;
|
||||
*aLength = db_data.size ;
|
||||
}
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::SetSpecialEntry(void* anEntry, PRUint32 aLength)
|
||||
{
|
||||
DBT db_key, db_data ;
|
||||
|
||||
db_key.data = NS_CONST_CAST(char*, SpecialEntry) ;
|
||||
db_key.size = PL_strlen(SpecialEntry) ;
|
||||
|
||||
db_data.data = anEntry ;
|
||||
db_data.size = aLength ;
|
||||
|
||||
if(0 == (*mDB->put)(mDB, &db_key, &db_data, 0)) {
|
||||
(*mDB->sync)(mDB, 0) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
else {
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sync routine is only called when the SyncInterval is reached. Otherwise
|
||||
* it just returns. If db synced, the filesize will be updated at the
|
||||
* same time.
|
||||
*/
|
||||
nsresult
|
||||
nsDBAccessor::Sync(void)
|
||||
{
|
||||
PRIntervalTime time = PR_IntervalNow() ;
|
||||
PRIntervalTime duration = time - mLastSyncTime ;
|
||||
|
||||
if (PR_IntervalToMilliseconds(duration) > SyncInterval) {
|
||||
int status = (*mDB->sync)(mDB, 0) ;
|
||||
if(status == 0) {
|
||||
// printf("\tsynced\n") ;
|
||||
mLastSyncTime = time ;
|
||||
|
||||
// update db filesize here
|
||||
return mDBFile->GetFileSize(&mDBFilesize) ;
|
||||
|
||||
} else
|
||||
return NS_ERROR_FAILURE ;
|
||||
} else {
|
||||
// printf("\tnot synced\n") ;
|
||||
return NS_OK ;
|
||||
}
|
||||
}
|
||||
93
mozilla/netwerk/cache/filecache/nsDBAccessor.h
vendored
Normal file
93
mozilla/netwerk/cache/filecache/nsDBAccessor.h
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
/*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of filecache implementation.
|
||||
*
|
||||
* nsIDBAccessor is a interface that shields all the direct database access
|
||||
* method from nsNetDiskCache.
|
||||
*
|
||||
* nsDBAccessor is a implementation of the nsIDBAccessor interface. It
|
||||
* uses dbm(Berkely) as the database.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _NSIDBACCESSOR_H_
|
||||
#define _NSIDBACCESSOR_H_
|
||||
|
||||
#include "nsIDBAccessor.h"
|
||||
#include "mcom_db.h"
|
||||
#include "prinrval.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
// bogus string for the key of session id
|
||||
static const char * const SessionKey = "SK" ;
|
||||
|
||||
// bogus string for the size
|
||||
static const char * const SpecialEntry = "SE" ;
|
||||
|
||||
// initial session id number
|
||||
static const PRInt16 ini_sessionID = 0xff ;
|
||||
|
||||
static const PRUint16 SyncInterval = 1000 ;
|
||||
|
||||
class nsDBAccessor : public nsIDBAccessor
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsDBAccessor() ;
|
||||
virtual ~nsDBAccessor() ;
|
||||
|
||||
NS_IMETHOD Init(nsIFileSpec* dbfile) ;
|
||||
NS_IMETHOD Shutdown(void) ;
|
||||
|
||||
NS_IMETHOD Put(PRInt32 aID, void* anEntry, PRUint32 aLength) ;
|
||||
|
||||
NS_IMETHOD Get(PRInt32 aID, void** anEntry, PRUint32 *aLength) ;
|
||||
|
||||
NS_IMETHOD Del(PRInt32 aID, void* anEntry, PRUint32 aLength) ;
|
||||
|
||||
NS_IMETHOD GetID(const char* key, PRUint32 length, PRInt32* aID) ;
|
||||
|
||||
NS_IMETHOD EnumEntry(void* *anEntry, PRUint32* aLength, PRBool bReset) ;
|
||||
|
||||
NS_IMETHOD GetDBFilesize(PRUint32* aSize) ;
|
||||
|
||||
NS_IMETHOD GetSpecialEntry(void** anEntry, PRUint32 *aLength) ;
|
||||
NS_IMETHOD SetSpecialEntry(void* anEntry, PRUint32 aLength) ;
|
||||
|
||||
protected:
|
||||
nsresult Sync(void) ;
|
||||
|
||||
private:
|
||||
DB * mDB ;
|
||||
nsCOMPtr<nsIFileSpec> mDBFile ;
|
||||
PRInt16 mSessionID ;
|
||||
PRInt16 mSessionCntr ;
|
||||
PRIntervalTime mLastSyncTime ;
|
||||
PRUint32 mDBFilesize ; // cached DB filesize,
|
||||
// updated on every sync for now
|
||||
} ;
|
||||
|
||||
#endif // _NSIDBACCESSOR_H_
|
||||
108
mozilla/netwerk/cache/filecache/nsDBEnumerator.cpp
vendored
Normal file
108
mozilla/netwerk/cache/filecache/nsDBEnumerator.cpp
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of filecache implementation.
|
||||
*
|
||||
* It implements a simple iterator for the database, see nsDBAccessor.
|
||||
*/
|
||||
|
||||
#include "nsDBEnumerator.h"
|
||||
#include "nsDiskCacheRecord.h"
|
||||
|
||||
nsDBEnumerator::nsDBEnumerator(nsIDBAccessor* aDB, nsNetDiskCache* aCache) :
|
||||
m_DB(aDB) ,
|
||||
m_DiskCache(aCache) ,
|
||||
m_tempEntry(0) ,
|
||||
m_tempEntry_length(0) ,
|
||||
m_CacheEntry(0) ,
|
||||
m_bReset(PR_TRUE)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
}
|
||||
|
||||
nsDBEnumerator::~nsDBEnumerator()
|
||||
{
|
||||
NS_IF_RELEASE(m_CacheEntry) ;
|
||||
}
|
||||
|
||||
//
|
||||
// Implement nsISupports methods
|
||||
//
|
||||
NS_IMPL_ISUPPORTS(nsDBEnumerator, NS_GET_IID(nsIEnumerator))
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// nsISimpleEnumerator methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBEnumerator::HasMoreElements(PRBool *_retval)
|
||||
{
|
||||
*_retval = PR_FALSE ;
|
||||
|
||||
nsresult rv = m_DB->EnumEntry(&m_tempEntry, &m_tempEntry_length, m_bReset) ;
|
||||
|
||||
if(NS_FAILED(rv)) {
|
||||
// do some error recovery
|
||||
m_DiskCache->DBRecovery() ;
|
||||
return rv ;
|
||||
}
|
||||
|
||||
m_bReset = PR_FALSE ;
|
||||
|
||||
if(m_tempEntry && m_tempEntry_length != 0)
|
||||
*_retval = PR_TRUE ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
// this routine does not create a new item by itself
|
||||
// Rather it reuses the item inside the object. So if you need to use the
|
||||
// item later, you have to
|
||||
// create a new item specifically, using copy constructor or some other dup
|
||||
// function. And don't forget to release it after you're done
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsDBEnumerator::GetNext(nsISupports **_retval)
|
||||
{
|
||||
if(!m_CacheEntry) {
|
||||
m_CacheEntry = new nsDiskCacheRecord(m_DB, m_DiskCache) ;
|
||||
if(m_CacheEntry)
|
||||
NS_ADDREF(m_CacheEntry) ;
|
||||
else
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
}
|
||||
|
||||
if(!_retval)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
*_retval = nsnull ;
|
||||
|
||||
nsresult rv = m_CacheEntry->RetrieveInfo(m_tempEntry, m_tempEntry_length) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
*_retval = NS_STATIC_CAST(nsISupports*, m_CacheEntry) ;
|
||||
NS_ADDREF(*_retval) ; // all good getter addref
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
60
mozilla/netwerk/cache/filecache/nsDBEnumerator.h
vendored
Normal file
60
mozilla/netwerk/cache/filecache/nsDBEnumerator.h
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of filecache implementation.
|
||||
*
|
||||
* It implements a simple iterator for the database, see nsDBAccessor.
|
||||
*/
|
||||
|
||||
#ifndef _NS_DBENUMERATOR_H_
|
||||
#define _NS_DBENUMERATOR_H_
|
||||
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsINetDataCacheRecord.h"
|
||||
#include "nsIDBAccessor.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsNetDiskCache.h"
|
||||
#include "nsDiskCacheRecord.h"
|
||||
|
||||
class nsCachedDiskData ; /* forward decl */
|
||||
|
||||
class nsDBEnumerator : public nsISimpleEnumerator {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
|
||||
nsDBEnumerator(nsIDBAccessor* aDB, nsNetDiskCache* aCache) ;
|
||||
virtual ~nsDBEnumerator() ;
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIDBAccessor> m_DB ;
|
||||
nsCOMPtr<nsNetDiskCache> m_DiskCache ;
|
||||
void * m_tempEntry ;
|
||||
PRUint32 m_tempEntry_length ;
|
||||
nsDiskCacheRecord* m_CacheEntry ;
|
||||
PRBool m_bReset ;
|
||||
};
|
||||
|
||||
#endif // _NS_DBENUMERATOR_H_
|
||||
456
mozilla/netwerk/cache/filecache/nsDiskCacheRecord.cpp
vendored
Normal file
456
mozilla/netwerk/cache/filecache/nsDiskCacheRecord.cpp
vendored
Normal file
@@ -0,0 +1,456 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
#include "nsDiskCacheRecord.h"
|
||||
#include "nsINetDataDiskCache.h"
|
||||
#include "nsNetDiskCacheCID.h"
|
||||
#include "nsDiskCacheRecordChannel.h"
|
||||
#include "nsFileStream.h"
|
||||
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIAllocator.h"
|
||||
|
||||
#include "plstr.h"
|
||||
#include "prprf.h"
|
||||
#include "prmem.h"
|
||||
#include "prlog.h"
|
||||
#include "prtypes.h"
|
||||
#include "netCore.h"
|
||||
|
||||
#include "nsDBAccessor.h"
|
||||
|
||||
#if !defined(IS_LITTLE_ENDIAN) && !defined(IS_BIG_ENDIAN)
|
||||
ERROR! Must have a byte order
|
||||
#endif
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define COPY_INT32(_a,_b) memcpy(_a, _b, sizeof(int32))
|
||||
#else
|
||||
#define COPY_INT32(_a,_b) /* swap */ \
|
||||
do { \
|
||||
((char *)(_a))[0] = ((char *)(_b))[3]; \
|
||||
((char *)(_a))[1] = ((char *)(_b))[2]; \
|
||||
((char *)(_a))[2] = ((char *)(_b))[1]; \
|
||||
((char *)(_a))[3] = ((char *)(_b))[0]; \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
nsDiskCacheRecord::nsDiskCacheRecord(nsIDBAccessor* db, nsNetDiskCache* aCache) :
|
||||
mKey(0) ,
|
||||
mKeyLength(0) ,
|
||||
mRecordID(0) ,
|
||||
mMetaData(0) ,
|
||||
mMetaDataLength(0) ,
|
||||
mDB(db) ,
|
||||
mInfo(0) ,
|
||||
mInfoSize(0) ,
|
||||
mNumChannels(0) ,
|
||||
mDiskCache(aCache)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ASSERTION(mDiskCache, "Must have an nsNetDiskCache");
|
||||
NS_ADDREF(mDiskCache);
|
||||
}
|
||||
|
||||
// mem alloced. so caller should do free() on key.
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::Init(const char* key, PRUint32 length, PRInt32 ID)
|
||||
{
|
||||
NS_NewFileSpec(getter_AddRefs(mFile));
|
||||
if(!mFile)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
// copy key
|
||||
mKeyLength = length ;
|
||||
mKey = NS_STATIC_CAST(char*, nsAllocator::Alloc(mKeyLength*sizeof(char))) ;
|
||||
if(!mKey)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
memcpy(mKey, key, length) ;
|
||||
|
||||
// get RecordID
|
||||
mRecordID = ID ;
|
||||
|
||||
// setup the file name
|
||||
nsCOMPtr<nsIFileSpec> dbFolder ;
|
||||
mDiskCache->GetDiskCacheFolder(getter_AddRefs(dbFolder)) ;
|
||||
|
||||
nsresult rv = mFile->FromFileSpec(dbFolder) ;
|
||||
if(NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
// dir is a hash result of mRecordID%32, hope it's enough
|
||||
char filename[9], dirName[3] ;
|
||||
|
||||
PR_snprintf(dirName, 3, "%02x", (((PRUint32)mRecordID) % 32)) ;
|
||||
mFile->AppendRelativeUnixPath(dirName) ;
|
||||
|
||||
PR_snprintf(filename, 9, "%08x", mRecordID) ;
|
||||
mFile->AppendRelativeUnixPath(filename) ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
nsDiskCacheRecord::~nsDiskCacheRecord()
|
||||
{
|
||||
if(mKey)
|
||||
nsAllocator::Free(mKey) ;
|
||||
if(mMetaData)
|
||||
nsAllocator::Free(mMetaData) ;
|
||||
if(mInfo)
|
||||
nsAllocator::Free(mInfo) ;
|
||||
|
||||
NS_IF_RELEASE(mDiskCache);
|
||||
}
|
||||
|
||||
//
|
||||
// Implement nsISupports methods
|
||||
//
|
||||
NS_IMPL_ISUPPORTS(nsDiskCacheRecord, NS_GET_IID(nsINetDataCacheRecord))
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// nsINetDataCacheRecord methods
|
||||
|
||||
// yes, mem alloced on *_retval.
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::GetKey(PRUint32 *length, char** _retval)
|
||||
{
|
||||
if(!_retval)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*length = mKeyLength ;
|
||||
*_retval = NS_STATIC_CAST(char*, nsAllocator::Alloc(mKeyLength*sizeof(char))) ;
|
||||
if(!*_retval)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
memcpy(*_retval, mKey, mKeyLength) ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::GetRecordID(PRInt32* aRecordID)
|
||||
{
|
||||
*aRecordID = mRecordID ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
// yes, mem alloced on *_retval.
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::GetMetaData(PRUint32 *length, char **_retval)
|
||||
{
|
||||
if(!_retval)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
// always null the return value first.
|
||||
*_retval = nsnull ;
|
||||
|
||||
*length = mMetaDataLength ;
|
||||
|
||||
if(mMetaDataLength) {
|
||||
*_retval = NS_STATIC_CAST(char*, nsAllocator::Alloc(mMetaDataLength*sizeof(char))) ;
|
||||
if(!*_retval)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
memcpy(*_retval, mMetaData, mMetaDataLength) ;
|
||||
}
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::SetMetaData(PRUint32 length, const char* data)
|
||||
{
|
||||
// set the mMetaData
|
||||
mMetaDataLength = length ;
|
||||
if(mMetaData)
|
||||
nsAllocator::Free(mMetaData) ;
|
||||
mMetaData = NS_STATIC_CAST(char*, nsAllocator::Alloc(mMetaDataLength*sizeof(char))) ;
|
||||
if(!mMetaData) {
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
}
|
||||
memcpy(mMetaData, data, length) ;
|
||||
|
||||
// Generate mInfo
|
||||
nsresult rv = GenInfo() ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
// write through into mDB
|
||||
rv = mDB->Put(mRecordID, mInfo, mInfoSize) ;
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::GetStoredContentLength(PRUint32 *aStoredContentLength)
|
||||
{
|
||||
return mFile->GetFileSize(aStoredContentLength) ;
|
||||
}
|
||||
|
||||
// untill nsIFileSpec::Truncate() is in, we have to do all this ugly stuff
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::SetStoredContentLength(PRUint32 aStoredContentLength)
|
||||
{
|
||||
PRUint32 len = 0 ;
|
||||
nsresult rv = mFile->GetFileSize(&len) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
if(len < aStoredContentLength)
|
||||
{
|
||||
NS_ERROR("Error: can not set filesize to something bigger than itself.\n") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
else {
|
||||
rv = mFile->Truncate(aStoredContentLength) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
mDiskCache->m_StorageInUse -= (len - aStoredContentLength) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::Delete(void)
|
||||
{
|
||||
if(mNumChannels)
|
||||
return NS_ERROR_NOT_AVAILABLE ;
|
||||
|
||||
PRUint32 len ;
|
||||
mFile->GetFileSize(&len) ;
|
||||
|
||||
nsFileSpec cache_file ;
|
||||
nsresult rv = mFile->GetFileSpec(&cache_file) ;
|
||||
|
||||
if(NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
cache_file.Delete(PR_TRUE) ;
|
||||
|
||||
// updata the storage size
|
||||
mDiskCache->m_StorageInUse -= len ;
|
||||
|
||||
rv = mDB->Del(mRecordID, mKey, mKeyLength) ;
|
||||
if(NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE ;
|
||||
else
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::GetFilename(nsIFileSpec * *aFilename)
|
||||
{
|
||||
if(!aFilename)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*aFilename = mFile ;
|
||||
NS_ADDREF(*aFilename) ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::NewChannel(nsILoadGroup *loadGroup, nsIChannel **_retval)
|
||||
{
|
||||
nsDiskCacheRecordChannel* channel = new nsDiskCacheRecordChannel(this, loadGroup) ;
|
||||
if(!channel)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
nsresult rv = channel->Init() ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
NS_ADDREF(channel) ;
|
||||
*_retval = NS_STATIC_CAST(nsIChannel*, channel) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// nsDiskCacheRecord methods
|
||||
|
||||
// file name is represented by a url string. I hope this would be more
|
||||
// generic
|
||||
nsresult
|
||||
nsDiskCacheRecord::GenInfo()
|
||||
{
|
||||
if(mInfo)
|
||||
nsAllocator::Free(mInfo) ;
|
||||
|
||||
char* file_url=nsnull ;
|
||||
PRUint32 name_len ;
|
||||
mFile->GetURLString(&file_url) ;
|
||||
name_len = PL_strlen(file_url)+1 ;
|
||||
|
||||
mInfoSize = sizeof(PRUint32) ; // checksum for mInfoSize
|
||||
mInfoSize += sizeof(PRInt32) ; // RecordID
|
||||
mInfoSize += sizeof(PRUint32) ; // key length
|
||||
mInfoSize += mKeyLength ; // key
|
||||
mInfoSize += sizeof(PRUint32) ; // metadata length
|
||||
mInfoSize += mMetaDataLength ; // metadata
|
||||
mInfoSize += sizeof(PRUint32) ; // filename length
|
||||
mInfoSize += name_len ; // filename
|
||||
|
||||
void* newInfo = nsAllocator::Alloc(mInfoSize*sizeof(char)) ;
|
||||
if(!newInfo) {
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
}
|
||||
|
||||
// copy the checksum mInfoSize
|
||||
char* cur_ptr = NS_STATIC_CAST(char*, newInfo) ;
|
||||
COPY_INT32(cur_ptr, &mInfoSize) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// copy RecordID
|
||||
COPY_INT32(cur_ptr, &mRecordID) ;
|
||||
cur_ptr += sizeof(PRInt32) ;
|
||||
|
||||
// copy key length
|
||||
COPY_INT32(cur_ptr, &mKeyLength) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// copy key
|
||||
memcpy(cur_ptr, mKey, mKeyLength) ;
|
||||
cur_ptr += mKeyLength ;
|
||||
|
||||
// copy metadata length
|
||||
COPY_INT32(cur_ptr, &mMetaDataLength) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// copy metadata
|
||||
memcpy(cur_ptr, mMetaData, mMetaDataLength) ;
|
||||
cur_ptr += mMetaDataLength ;
|
||||
|
||||
// copy file name length
|
||||
COPY_INT32(cur_ptr, &name_len) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// copy file name
|
||||
memcpy(cur_ptr, file_url, name_len) ;
|
||||
cur_ptr += name_len ;
|
||||
|
||||
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, newInfo) + mInfoSize);
|
||||
mInfo = newInfo ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
/*
|
||||
* This Method suppose to get all the info from the db record
|
||||
* and set them to accroding members. the original values
|
||||
* will all be overwritten. only minimal error checking is performed.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::RetrieveInfo(void* aInfo, PRUint32 aInfoLength)
|
||||
{
|
||||
// reset everything
|
||||
if(mInfo) {
|
||||
nsAllocator::Free(mInfo) ;
|
||||
mInfo = nsnull ;
|
||||
}
|
||||
|
||||
if(mKey) {
|
||||
nsAllocator::Free(mKey) ;
|
||||
mKey = nsnull ;
|
||||
}
|
||||
if(mMetaData) {
|
||||
nsAllocator::Free(mMetaData) ;
|
||||
mMetaData = nsnull ;
|
||||
}
|
||||
|
||||
char * cur_ptr = NS_STATIC_CAST(char*, aInfo) ;
|
||||
|
||||
char* file_url ;
|
||||
PRUint32 name_len ;
|
||||
|
||||
// set mInfoSize
|
||||
COPY_INT32(&mInfoSize, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// check this at least
|
||||
if(mInfoSize != aInfoLength)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
// set mRecordID
|
||||
COPY_INT32(&mRecordID, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRInt32) ;
|
||||
|
||||
// set mKeyLength
|
||||
COPY_INT32(&mKeyLength, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// set mKey
|
||||
mKey = NS_STATIC_CAST(char*, nsAllocator::Alloc(mKeyLength*sizeof(char))) ;
|
||||
if(!mKey)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
memcpy(mKey, cur_ptr, mKeyLength) ;
|
||||
cur_ptr += mKeyLength ;
|
||||
|
||||
PRInt32 id ;
|
||||
mDB->GetID(mKey, mKeyLength, &id) ;
|
||||
NS_ASSERTION(id==mRecordID, "\t ++++++ bad record, somethings wrong\n") ;
|
||||
|
||||
// set mMetaDataLength
|
||||
COPY_INT32(&mMetaDataLength, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// set mMetaData
|
||||
mMetaData = NS_STATIC_CAST(char*, nsAllocator::Alloc(mMetaDataLength*sizeof(char))) ;
|
||||
if(!mMetaData)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
memcpy(mMetaData, cur_ptr, mMetaDataLength) ;
|
||||
cur_ptr += mMetaDataLength ;
|
||||
|
||||
// get mFile name length
|
||||
COPY_INT32(&name_len, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// get mFile native name
|
||||
file_url = NS_STATIC_CAST(char*, nsAllocator::Alloc(name_len*sizeof(char))) ;
|
||||
if(!file_url)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
memcpy(file_url, cur_ptr, name_len) ;
|
||||
cur_ptr += name_len ;
|
||||
|
||||
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, aInfo) + mInfoSize);
|
||||
|
||||
// create mFile if Init() isn't called
|
||||
if(!mFile) {
|
||||
NS_NewFileSpec(getter_AddRefs(mFile));
|
||||
if(!mFile)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
}
|
||||
|
||||
// setup mFile
|
||||
mFile->SetURLString(file_url) ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
71
mozilla/netwerk/cache/filecache/nsDiskCacheRecord.h
vendored
Normal file
71
mozilla/netwerk/cache/filecache/nsDiskCacheRecord.h
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
#ifndef _NET_CACHEDDISKDATA_H_
|
||||
#define _NET_CACHEDDISKDATA_H_
|
||||
|
||||
#include "nsINetDataCacheRecord.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDBAccessor.h"
|
||||
#include "prtypes.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsIFileChannel.h"
|
||||
#include "nsNetDiskCache.h"
|
||||
|
||||
class nsDiskCacheRecord : public nsINetDataCacheRecord
|
||||
{
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSINETDATACACHERECORD
|
||||
|
||||
protected:
|
||||
|
||||
nsDiskCacheRecord(nsIDBAccessor* db, nsNetDiskCache* aCache) ;
|
||||
virtual ~nsDiskCacheRecord() ;
|
||||
|
||||
NS_IMETHOD RetrieveInfo(void* aInfo, PRUint32 aInfoLength) ;
|
||||
NS_IMETHOD Init(const char* key, PRUint32 length, PRInt32 ID) ;
|
||||
|
||||
nsresult GenInfo(void) ;
|
||||
|
||||
private:
|
||||
|
||||
char* mKey ;
|
||||
PRUint32 mKeyLength ;
|
||||
PRInt32 mRecordID ;
|
||||
char* mMetaData ;
|
||||
PRUint32 mMetaDataLength ;
|
||||
nsCOMPtr<nsIFileSpec> mFile ;
|
||||
nsCOMPtr<nsIDBAccessor> mDB ;
|
||||
void* mInfo ;
|
||||
PRUint32 mInfoSize ;
|
||||
PRUint32 mNumChannels ;
|
||||
nsNetDiskCache* mDiskCache ;
|
||||
|
||||
friend class nsDiskCacheRecordChannel ;
|
||||
friend class nsDBEnumerator ;
|
||||
friend class nsNetDiskCache ;
|
||||
} ;
|
||||
|
||||
#endif // _NET_CACHEDDISKDATA_H_
|
||||
552
mozilla/netwerk/cache/filecache/nsDiskCacheRecordChannel.cpp
vendored
Normal file
552
mozilla/netwerk/cache/filecache/nsDiskCacheRecordChannel.cpp
vendored
Normal file
@@ -0,0 +1,552 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Most of the code are taken from nsFileChannel.
|
||||
*/
|
||||
|
||||
#include "nsDiskCacheRecordChannel.h"
|
||||
#include "nsIFileTransportService.h"
|
||||
//#include "nsIIOService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "netCore.h"
|
||||
#include "nsIMIMEService.h"
|
||||
#include "nsISupportsUtils.h"
|
||||
|
||||
//static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||||
static NS_DEFINE_CID(kFileTransportServiceCID, NS_FILETRANSPORTSERVICE_CID);
|
||||
static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
|
||||
static NS_DEFINE_CID(kMIMEServiceCID, NS_MIMESERVICE_CID);
|
||||
|
||||
// This is copied from nsMemCacheChannel, We should consolidate these two.
|
||||
class WriteStreamWrapper : public nsIOutputStream
|
||||
{
|
||||
public:
|
||||
WriteStreamWrapper(nsDiskCacheRecordChannel* aChannel,
|
||||
nsIOutputStream *aBaseStream) ;
|
||||
|
||||
virtual ~WriteStreamWrapper() ;
|
||||
|
||||
static nsresult
|
||||
Create(nsDiskCacheRecordChannel* aChannel, nsIOutputStream *aBaseStream, nsIOutputStream* *aWrapper) ;
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIBASESTREAM
|
||||
NS_DECL_NSIOUTPUTSTREAM
|
||||
|
||||
private:
|
||||
nsDiskCacheRecordChannel* mChannel;
|
||||
nsCOMPtr<nsIOutputStream> mBaseStream;
|
||||
} ;
|
||||
|
||||
// implement nsISupports
|
||||
NS_IMPL_ISUPPORTS(WriteStreamWrapper, NS_GET_IID(nsIOutputStream))
|
||||
|
||||
WriteStreamWrapper::WriteStreamWrapper(nsDiskCacheRecordChannel* aChannel,
|
||||
nsIOutputStream *aBaseStream)
|
||||
: mChannel(aChannel), mBaseStream(aBaseStream)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF(mChannel);
|
||||
}
|
||||
|
||||
WriteStreamWrapper::~WriteStreamWrapper()
|
||||
{
|
||||
NS_RELEASE(mChannel);
|
||||
}
|
||||
|
||||
nsresult
|
||||
WriteStreamWrapper::Create(nsDiskCacheRecordChannel*aChannel, nsIOutputStream *aBaseStream, nsIOutputStream* * aWrapper)
|
||||
{
|
||||
WriteStreamWrapper *wrapper = new WriteStreamWrapper(aChannel, aBaseStream);
|
||||
if (!wrapper) return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(wrapper);
|
||||
*aWrapper = wrapper;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WriteStreamWrapper::Write(const char *aBuffer, PRUint32 aCount, PRUint32 *aNumWritten)
|
||||
{
|
||||
*aNumWritten = 0;
|
||||
nsresult rv = mBaseStream->Write(aBuffer, aCount, aNumWritten);
|
||||
mChannel->NotifyStorageInUse(*aNumWritten);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WriteStreamWrapper::Flush()
|
||||
{
|
||||
return mBaseStream->Flush();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WriteStreamWrapper::Close()
|
||||
{
|
||||
return mBaseStream->Close();
|
||||
}
|
||||
|
||||
nsDiskCacheRecordChannel::nsDiskCacheRecordChannel(nsDiskCacheRecord *aRecord,
|
||||
nsILoadGroup *aLoadGroup)
|
||||
: mRecord(aRecord) ,
|
||||
mLoadGroup(aLoadGroup)
|
||||
{
|
||||
NS_INIT_REFCNT() ;
|
||||
NS_ADDREF(mRecord);
|
||||
mRecord->mNumChannels++ ;
|
||||
}
|
||||
|
||||
nsDiskCacheRecordChannel::~nsDiskCacheRecordChannel()
|
||||
{
|
||||
mRecord->mNumChannels-- ;
|
||||
NS_RELEASE(mRecord);
|
||||
}
|
||||
|
||||
// I know that I gave conflicting advice on the issue of file
|
||||
// transport versus file protocol handler, but I thought that the
|
||||
// last word was that we would use the raw transport, when I wrote:
|
||||
//
|
||||
// > I just thought of an argument for the other side of the coin, i.e. the
|
||||
// > benefit of *not* reusing the file protocol handler: On the Mac, it's
|
||||
// > expensive to convert from a string URL to an nsFileSpec, because the Mac
|
||||
// > is brain-dead and scans every directory on the path to the file. It's
|
||||
// > cheaper to create a nsFileSpec for a cache file by combining a single,
|
||||
// > static nsFileSpec that corresponds to the cache directory with the
|
||||
// > relative path to the cache file (using nsFileSpec's operator +). This
|
||||
// > operation is optimized on the Mac to avoid the scanning operation.
|
||||
//
|
||||
// The Mac guys will eat us alive if we do path string to nsFileSpec
|
||||
// conversions for every cache file we open.
|
||||
|
||||
nsresult
|
||||
nsDiskCacheRecordChannel::Init(void)
|
||||
{
|
||||
nsresult rv = mRecord->mFile->GetFileSpec(&mSpec) ;
|
||||
|
||||
#ifdef XP_MAC
|
||||
|
||||
// Don't assume we actually created a good file spec
|
||||
FSSpec theSpec = mSpec.GetFSSpec();
|
||||
if (!theSpec.name[0]) {
|
||||
NS_ERROR("failed to create a file spec");
|
||||
|
||||
// Since we didn't actually create the file spec
|
||||
// we return an error
|
||||
return NS_ERROR_MALFORMED_URI;
|
||||
}
|
||||
#endif
|
||||
|
||||
return rv ;
|
||||
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDiskCacheRecordChannel::NotifyStorageInUse(PRInt32 aBytesUsed)
|
||||
{
|
||||
return mRecord->mDiskCache->m_StorageInUse += aBytesUsed ;
|
||||
}
|
||||
|
||||
// implement nsISupports
|
||||
NS_IMPL_ISUPPORTS4(nsDiskCacheRecordChannel,
|
||||
nsIChannel,
|
||||
nsIRequest,
|
||||
nsIStreamListener,
|
||||
nsIStreamObserver)
|
||||
|
||||
// implement nsIRequest
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::IsPending(PRBool *aIsPending)
|
||||
{
|
||||
*aIsPending = PR_FALSE ;
|
||||
if(!mFileTransport)
|
||||
return NS_OK ;
|
||||
|
||||
return mFileTransport->IsPending(aIsPending) ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::Cancel(void)
|
||||
{
|
||||
if(!mFileTransport)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
return mFileTransport->Cancel() ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::Suspend(void)
|
||||
{
|
||||
if(!mFileTransport)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
return mFileTransport->Suspend() ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::Resume(void)
|
||||
{
|
||||
if(!mFileTransport)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
return mFileTransport->Resume() ;
|
||||
}
|
||||
|
||||
// implement nsIChannel
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetOriginalURI(nsIURI* *aURI)
|
||||
{
|
||||
// FUR - might need to implement this - not sure
|
||||
return NS_ERROR_NOT_IMPLEMENTED ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetURI(nsIURI * *aURI)
|
||||
{
|
||||
if(!mFileTransport)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
return mFileTransport->GetURI(aURI) ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::OpenInputStream(PRUint32 aStartPosition,
|
||||
PRInt32 aReadCount,
|
||||
nsIInputStream* *aResult)
|
||||
{
|
||||
nsresult rv ;
|
||||
|
||||
if(mFileTransport)
|
||||
return NS_ERROR_IN_PROGRESS ;
|
||||
|
||||
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv) ;
|
||||
if(NS_FAILED(rv)) return rv ;
|
||||
|
||||
rv = fts->CreateTransport(mSpec, "load", 0, 0, getter_AddRefs(mFileTransport)) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
// we don't need to worry about notification callbacks
|
||||
|
||||
rv = mFileTransport->OpenInputStream(aStartPosition, aReadCount, aResult) ;
|
||||
if(NS_FAILED(rv))
|
||||
mFileTransport = nsnull ;
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::OpenOutputStream(PRUint32 startPosition,
|
||||
nsIOutputStream* *aResult)
|
||||
{
|
||||
nsresult rv ;
|
||||
NS_ENSURE_ARG(aResult) ;
|
||||
|
||||
if(mFileTransport)
|
||||
return NS_ERROR_IN_PROGRESS ;
|
||||
|
||||
nsCOMPtr<nsIOutputStream> outputStream ;
|
||||
|
||||
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv) ;
|
||||
if(NS_FAILED(rv)) return rv ;
|
||||
|
||||
rv = fts->CreateTransport(mSpec, "load", 0, 0, getter_AddRefs(mFileTransport)) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
// we don't need to worry about notification callbacks
|
||||
|
||||
rv = mFileTransport->OpenOutputStream(startPosition, getter_AddRefs(outputStream)) ;
|
||||
if(NS_FAILED(rv)) {
|
||||
mFileTransport = nsnull ;
|
||||
return rv ;
|
||||
}
|
||||
|
||||
return WriteStreamWrapper::Create(this, outputStream, aResult) ;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::AsyncOpen(nsIStreamObserver *observer,
|
||||
nsISupports *ctxt)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::AsyncRead(PRUint32 aStartPosition,
|
||||
PRInt32 aReadCount,
|
||||
nsISupports *aContext,
|
||||
nsIStreamListener *aListener)
|
||||
{
|
||||
nsresult rv ;
|
||||
|
||||
if(mFileTransport)
|
||||
return NS_ERROR_IN_PROGRESS ;
|
||||
|
||||
mRealListener = aListener;
|
||||
nsCOMPtr<nsIStreamListener> tempListener = this;
|
||||
|
||||
if (mLoadGroup) {
|
||||
nsCOMPtr<nsILoadGroupListenerFactory> factory;
|
||||
//
|
||||
// Create a load group "proxy" listener...
|
||||
//
|
||||
rv = mLoadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
|
||||
if (factory) {
|
||||
nsIStreamListener *newListener;
|
||||
rv = factory->CreateLoadGroupListener(mRealListener, &newListener);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mRealListener = newListener;
|
||||
NS_RELEASE(newListener);
|
||||
}
|
||||
}
|
||||
|
||||
rv = mLoadGroup->AddChannel(this, nsnull);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = fts->CreateTransport(mSpec, "load", 0, 0, getter_AddRefs(mFileTransport));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// no callbacks
|
||||
|
||||
rv = mFileTransport->AsyncRead(aStartPosition,
|
||||
aReadCount,
|
||||
aContext,
|
||||
tempListener);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
// release the transport so that we don't think we're in progress
|
||||
mFileTransport = nsnull;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::AsyncWrite(nsIInputStream *fromStream,
|
||||
PRUint32 startPosition,
|
||||
PRInt32 writeCount,
|
||||
nsISupports *ctxt,
|
||||
nsIStreamObserver *observer)
|
||||
|
||||
{
|
||||
/*
|
||||
if(!mFileTransport)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
return mFileTransport->AsyncWrite(fromStream,
|
||||
startPosition,
|
||||
writeCount,
|
||||
ctxt,
|
||||
observer) ;
|
||||
*/
|
||||
|
||||
// I can't do this since the write is not monitored, and I won't be
|
||||
// able to updata the storage.
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#define DUMMY_TYPE "text/html"
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetContentType(char * *aContentType)
|
||||
{
|
||||
nsresult rv ;
|
||||
|
||||
if (mSpec.IsDirectory()) {
|
||||
*aContentType = nsCRT::strdup("application/http-index-format");
|
||||
return *aContentType ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
else {
|
||||
// I wish I can make this simplier
|
||||
|
||||
char* urlStr ;
|
||||
mRecord->mFile->GetURLString(&urlStr) ;
|
||||
|
||||
// file: URLs (currently) have no additional structure beyond that provided by standard
|
||||
// URLs, so there is no "outer" given to CreateInstance
|
||||
|
||||
nsCOMPtr<nsIURI> url;
|
||||
rv = nsComponentManager::CreateInstance(kStandardURLCID, nsnull,
|
||||
NS_GET_IID(nsIURI),
|
||||
//(void**)&url);
|
||||
getter_AddRefs(url)) ;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = url->SetSpec((char*)urlStr);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIMIMEService, MIMEService, kMIMEServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = MIMEService->GetTypeFromURI(url, aContentType);
|
||||
if (NS_SUCCEEDED(rv)) return rv;
|
||||
}
|
||||
|
||||
// if all else fails treat it as text/html?
|
||||
*aContentType = nsCRT::strdup(DUMMY_TYPE);
|
||||
if (!*aContentType) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
} else {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetContentLength(PRInt32 *aContentLength)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 length;
|
||||
|
||||
rv = mRecord->mFile->GetFileSize(&length);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
*aContentLength = (PRInt32)length;
|
||||
} else {
|
||||
*aContentLength = -1;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetOwner(nsISupports* *aOwner)
|
||||
{
|
||||
*aOwner = mOwner.get() ;
|
||||
NS_IF_ADDREF(*aOwner) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::SetOwner(nsISupports* aOwner)
|
||||
{
|
||||
mOwner = aOwner ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIStreamListener methods:
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::OnStartRequest(nsIChannel* transportChannel, nsISupports* context)
|
||||
{
|
||||
NS_ASSERTION(mRealListener, "No listener...");
|
||||
return mRealListener->OnStartRequest(this, context);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::OnStopRequest(nsIChannel* transportChannel, nsISupports* context,
|
||||
nsresult aStatus, const PRUnichar* aMsg)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = mRealListener->OnStopRequest(this, context, aStatus, aMsg);
|
||||
|
||||
if (mLoadGroup) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mLoadGroup->RemoveChannel(this, context, aStatus, aMsg);
|
||||
}
|
||||
}
|
||||
|
||||
// Release the reference to the consumer stream listener...
|
||||
mRealListener = null_nsCOMPtr();
|
||||
mFileTransport = null_nsCOMPtr();
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::OnDataAvailable(nsIChannel* transportChannel, nsISupports* context,
|
||||
nsIInputStream *aIStream, PRUint32 aSourceOffset,
|
||||
PRUint32 aLength)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = mRealListener->OnDataAvailable(this, context, aIStream,
|
||||
aSourceOffset, aLength);
|
||||
|
||||
//
|
||||
// If the connection is being aborted cancel the transport. This will
|
||||
// insure that the transport will go away even if it is blocked waiting
|
||||
// for the consumer to empty the pipe...
|
||||
//
|
||||
if (NS_FAILED(rv)) {
|
||||
mFileTransport->Cancel();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
76
mozilla/netwerk/cache/filecache/nsDiskCacheRecordChannel.h
vendored
Normal file
76
mozilla/netwerk/cache/filecache/nsDiskCacheRecordChannel.h
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
#ifndef _ns_DiskCacheRecordChannel_h_
|
||||
#define _ns_DiskCacheRecordChannel_h_
|
||||
|
||||
#include "nsIChannel.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDiskCacheRecord.h"
|
||||
#include "nsIStreamListener.h"
|
||||
|
||||
/*
|
||||
* This class is plagiarized from nsMemCacheChannel
|
||||
*/
|
||||
|
||||
class nsDiskCacheRecordChannel : public nsIChannel,
|
||||
public nsIStreamListener
|
||||
{
|
||||
public:
|
||||
|
||||
nsDiskCacheRecordChannel(nsDiskCacheRecord *aRecord, nsILoadGroup *aLoadGroup);
|
||||
virtual ~nsDiskCacheRecordChannel() ;
|
||||
|
||||
// Declare nsISupports methods
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// Declare nsIRequest methods
|
||||
NS_DECL_NSIREQUEST
|
||||
|
||||
// Declare nsIChannel methods
|
||||
NS_DECL_NSICHANNEL
|
||||
|
||||
// Declare nsIStreamObserver methods
|
||||
NS_DECL_NSISTREAMOBSERVER
|
||||
|
||||
// Declare nsIStreamListener methods
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
|
||||
nsresult Init(void) ;
|
||||
|
||||
private:
|
||||
|
||||
nsresult NotifyStorageInUse(PRInt32 aBytesUsed) ;
|
||||
|
||||
nsDiskCacheRecord* mRecord ;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup ;
|
||||
nsCOMPtr<nsISupports> mOwner ;
|
||||
nsCOMPtr<nsIChannel> mFileTransport ;
|
||||
nsFileSpec mSpec ;
|
||||
nsCOMPtr<nsIStreamListener> mRealListener;
|
||||
|
||||
friend class WriteStreamWrapper ;
|
||||
} ;
|
||||
|
||||
#endif // _ns_DiskCacheRecordChannel_h_
|
||||
|
||||
66
mozilla/netwerk/cache/filecache/nsIDBAccessor.h
vendored
Normal file
66
mozilla/netwerk/cache/filecache/nsIDBAccessor.h
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
#ifndef _NS_IDBACCESSOR_H_
|
||||
#define _NS_IDBACCESSOR_H_
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIFileSpec.h"
|
||||
|
||||
// nsIDBAccessorIID {6AADD4D0-7785-11d3-87FE-000629D01344}
|
||||
#define NS_IDBACCESSOR_IID \
|
||||
{ 0x6aadd4d0, 0x7785, 0x11d3, \
|
||||
{0x87, 0xfe, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44}}
|
||||
|
||||
// nsDBAccessorCID {6AADD4D1-7785-11d3-87FE-000629D01344}
|
||||
#define NS_DBACCESSOR_CID \
|
||||
{ 0x6aadd4d1, 0x7785, 0x11d3, \
|
||||
{ 0x87, 0xfe, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44 }}
|
||||
|
||||
class nsIDBAccessor : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IDBACCESSOR_IID)
|
||||
|
||||
NS_IMETHOD Init(nsIFileSpec* DBFile) = 0 ;
|
||||
NS_IMETHOD Shutdown(void) = 0 ;
|
||||
|
||||
NS_IMETHOD Put(PRInt32 aID, void* anEntry, PRUint32 aLength) = 0 ;
|
||||
|
||||
NS_IMETHOD Get(PRInt32 aID, void** anEntry, PRUint32 *aLength) = 0 ;
|
||||
|
||||
NS_IMETHOD Del(PRInt32 aID, void* anEntry, PRUint32 aLength) = 0 ;
|
||||
|
||||
NS_IMETHOD GetID(const char* key, PRUint32 length, PRInt32* aID) = 0 ;
|
||||
|
||||
NS_IMETHOD EnumEntry(void* *anEntry, PRUint32* aLength, PRBool bReset) = 0 ;
|
||||
|
||||
NS_IMETHOD GetDBFilesize(PRUint32* aSize) = 0 ;
|
||||
|
||||
NS_IMETHOD GetSpecialEntry(void** anEntry, PRUint32 *aLength) = 0 ;
|
||||
NS_IMETHOD SetSpecialEntry(void* anEntry, PRUint32 aLength) = 0 ;
|
||||
|
||||
} ;
|
||||
|
||||
#endif // _NS_IDBACCESSOR_H_
|
||||
|
||||
704
mozilla/netwerk/cache/filecache/nsNetDiskCache.cpp
vendored
Normal file
704
mozilla/netwerk/cache/filecache/nsNetDiskCache.cpp
vendored
Normal file
@@ -0,0 +1,704 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
#include "nsNetDiskCache.h"
|
||||
#include "nscore.h"
|
||||
|
||||
#include "plstr.h"
|
||||
#include "prprf.h"
|
||||
#include "prtypes.h"
|
||||
#include "prio.h"
|
||||
#include "prsystem.h" // Directory Seperator
|
||||
#include "plhash.h"
|
||||
#include "prclist.h"
|
||||
#include "prmem.h"
|
||||
#include "prlog.h"
|
||||
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
#include "nsIPref.h"
|
||||
#include "mcom_db.h"
|
||||
#include "nsDBEnumerator.h"
|
||||
|
||||
#include "nsDiskCacheRecord.h"
|
||||
#include "netCore.h"
|
||||
|
||||
#if !defined(IS_LITTLE_ENDIAN) && !defined(IS_BIG_ENDIAN)
|
||||
ERROR! Must have a byte order
|
||||
#endif
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define COPY_INT32(_a,_b) memcpy(_a, _b, sizeof(int32))
|
||||
#else
|
||||
#define COPY_INT32(_a,_b) /* swap */ \
|
||||
do { \
|
||||
((char *)(_a))[0] = ((char *)(_b))[3]; \
|
||||
((char *)(_a))[1] = ((char *)(_b))[2]; \
|
||||
((char *)(_a))[2] = ((char *)(_b))[1]; \
|
||||
((char *)(_a))[3] = ((char *)(_b))[0]; \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID) ;
|
||||
static NS_DEFINE_CID(kDBAccessorCID, NS_DBACCESSOR_CID) ;
|
||||
|
||||
static const PRUint32 DISK_CACHE_SIZE_DEFAULT = 5*1024*1024 ; // 5MB
|
||||
static const char * const DISK_CACHE_PREF = "browser.cache.disk_cache_size";
|
||||
static const char * const CACHE_DIR_PREF = "browser.cache.directory";
|
||||
|
||||
class nsDiskCacheRecord ;
|
||||
|
||||
nsNetDiskCache::nsNetDiskCache() :
|
||||
m_Enabled(PR_TRUE) ,
|
||||
m_NumEntries(0) ,
|
||||
m_pNextCache(0) ,
|
||||
m_pDiskCacheFolder(0) ,
|
||||
m_StorageInUse(0) ,
|
||||
m_DB(0) ,
|
||||
m_DBCorrupted(PR_FALSE)
|
||||
{
|
||||
// set it to INF for now
|
||||
m_MaxEntries = (PRUint32)-1 ;
|
||||
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
}
|
||||
|
||||
nsNetDiskCache::~nsNetDiskCache()
|
||||
{
|
||||
SetSpecialEntry() ;
|
||||
|
||||
NS_IF_RELEASE(m_DB) ;
|
||||
|
||||
|
||||
// FUR
|
||||
// I think that, eventually, we also want a distinguished key in the DB which
|
||||
// means "clean cache shutdown". You clear this flag when the db is first
|
||||
// opened and set it just before the db is closed. If the db wasn't shutdown
|
||||
// cleanly in a prior session, i.e. because the app crashed, on startup you
|
||||
// scan all the individual files in directories and look for "orphans",
|
||||
// i.e. cache files which don't have corresponding entries in the db. That's
|
||||
// also when storage-in-use and number of entries would be recomputed.
|
||||
//
|
||||
// We don't necessarily need all this functionality immediately, though.
|
||||
|
||||
|
||||
if(m_DBCorrupted) {
|
||||
|
||||
nsFileSpec cacheFolder ;
|
||||
m_pDiskCacheFolder->GetFileSpec(&cacheFolder) ;
|
||||
|
||||
char nameInt[6] ;
|
||||
|
||||
for(nsDirectoryIterator di(cacheFolder, PR_FALSE); di.Exists(); di++) {
|
||||
char* filename = di.Spec().GetLeafName() ;
|
||||
char* pname = nameInt ;
|
||||
pname = PL_strncpyz(pname, filename, 6) ;
|
||||
|
||||
if(PL_strcmp(pname, "trash") == 0)
|
||||
RemoveFolder(di.Spec()) ;
|
||||
|
||||
nsCRT::free(filename) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::Init(void)
|
||||
{
|
||||
nsresult rv ;
|
||||
|
||||
// don't initialize if no cache folder is set.
|
||||
if(!m_pDiskCacheFolder) return NS_OK ;
|
||||
|
||||
if(!m_DB) {
|
||||
m_DB = new nsDBAccessor() ;
|
||||
if(!m_DB)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
else
|
||||
NS_ADDREF(m_DB) ;
|
||||
}
|
||||
|
||||
// create cache sub directories
|
||||
nsCOMPtr<nsIFileSpec> cacheSubDir;
|
||||
rv = NS_NewFileSpec(getter_AddRefs(cacheSubDir));
|
||||
|
||||
for (int i=0; i < 32; i++) {
|
||||
rv = cacheSubDir->FromFileSpec(m_pDiskCacheFolder) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
char dirName[3];
|
||||
PR_snprintf (dirName, 3, "%0.2x", i);
|
||||
cacheSubDir->AppendRelativeUnixPath (dirName) ;
|
||||
CreateDir(cacheSubDir);
|
||||
}
|
||||
|
||||
return InitDB() ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::InitDB(void)
|
||||
{
|
||||
nsresult rv ;
|
||||
|
||||
if(!m_DBFile) {
|
||||
NS_NewFileSpec(getter_AddRefs(m_DBFile)) ;
|
||||
if(!m_DBFile)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
}
|
||||
|
||||
rv = m_DBFile->FromFileSpec(m_pDiskCacheFolder) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
m_DBFile->AppendRelativeUnixPath("cache.db") ;
|
||||
|
||||
rv = m_DB->Init(m_DBFile) ;
|
||||
|
||||
if(rv == NS_ERROR_FAILURE) {
|
||||
// try recovery if error
|
||||
DBRecovery() ;
|
||||
}
|
||||
|
||||
rv = GetSpecialEntry() ;
|
||||
if(rv == NS_ERROR_FAILURE) {
|
||||
// try recovery if error
|
||||
DBRecovery() ;
|
||||
}
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// nsISupports methods
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsNetDiskCache,
|
||||
nsINetDataDiskCache,
|
||||
nsINetDataCache,
|
||||
nsISupports)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// nsINetDataCache Method
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetDescription(PRUnichar* *aDescription)
|
||||
{
|
||||
nsAutoString description("Disk Cache") ;
|
||||
*aDescription = description.ToNewUnicode() ;
|
||||
if(!*aDescription)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
/* don't alloc mem for nsICachedNetData.
|
||||
* RecordID is generated using the same scheme in nsCacheDiskData,
|
||||
* see GetCachedNetData() for detail.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::Contains(const char* key, PRUint32 length, PRBool *_retval)
|
||||
{
|
||||
*_retval = PR_FALSE ;
|
||||
|
||||
NS_ASSERTION(m_DB, "no db.") ;
|
||||
|
||||
PRInt32 id = 0 ;
|
||||
nsresult rv = m_DB->GetID(key, length, &id) ;
|
||||
|
||||
if(NS_FAILED(rv)) {
|
||||
// try recovery if error
|
||||
DBRecovery() ;
|
||||
return rv ;
|
||||
}
|
||||
|
||||
void* info = 0 ;
|
||||
PRUint32 info_size = 0 ;
|
||||
|
||||
rv = m_DB->Get(id, &info, &info_size) ;
|
||||
if(NS_SUCCEEDED(rv) && info)
|
||||
*_retval = PR_TRUE ;
|
||||
|
||||
if(NS_FAILED(rv)) {
|
||||
// try recovery if error
|
||||
DBRecovery() ;
|
||||
}
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
/* regardless if it's cached or not, a copy of nsNetDiskCache would
|
||||
* always be returned. so release it appropriately.
|
||||
* if mem alloced, updata m_NumEntries also.
|
||||
* for now, the new nsCachedNetData is not written into db yet since
|
||||
* we have nothing to write.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetCachedNetData(const char* key, PRUint32 length, nsINetDataCacheRecord **_retval)
|
||||
{
|
||||
NS_ASSERTION(m_DB, "no db.") ;
|
||||
|
||||
nsresult rv = 0 ;
|
||||
if (!_retval)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*_retval = nsnull ;
|
||||
|
||||
PRInt32 id = 0 ;
|
||||
rv = m_DB->GetID(key, length, &id) ;
|
||||
if(NS_FAILED(rv)) {
|
||||
// try recovery if error
|
||||
DBRecovery() ;
|
||||
return rv ;
|
||||
}
|
||||
|
||||
// construct an empty record
|
||||
nsDiskCacheRecord* newRecord = new nsDiskCacheRecord(m_DB, this) ;
|
||||
if(!newRecord)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
rv = newRecord->Init(key, length, id) ;
|
||||
if(NS_FAILED(rv)) {
|
||||
delete newRecord ;
|
||||
return rv ;
|
||||
}
|
||||
|
||||
NS_ADDREF(newRecord) ; // addref for _retval
|
||||
*_retval = (nsINetDataCacheRecord*) newRecord ;
|
||||
|
||||
void* info = 0 ;
|
||||
PRUint32 info_size = 0 ;
|
||||
|
||||
rv = m_DB->Get(id, &info, &info_size) ;
|
||||
if(NS_SUCCEEDED(rv) && info) {
|
||||
|
||||
// this is a previously cached record
|
||||
nsresult r1 ;
|
||||
r1 = newRecord->RetrieveInfo(info, info_size) ;
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
return NS_OK ;
|
||||
else {
|
||||
// probably a bad one
|
||||
NS_RELEASE(newRecord) ;
|
||||
*_retval = nsnull ;
|
||||
return r1;
|
||||
}
|
||||
|
||||
} else if (NS_SUCCEEDED(rv) && !info) {
|
||||
// this is a new record.
|
||||
m_NumEntries ++ ;
|
||||
return NS_OK ;
|
||||
} else {
|
||||
// database error.
|
||||
DBRecovery() ;
|
||||
return rv ;
|
||||
}
|
||||
}
|
||||
|
||||
/* get an nsICachedNetData, mem needs to be de-alloced if not found. */
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetCachedNetDataByID(PRInt32 RecordID, nsINetDataCacheRecord **_retval)
|
||||
{
|
||||
NS_ASSERTION(m_DB, "no db.") ;
|
||||
|
||||
if (!_retval)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*_retval = nsnull ;
|
||||
|
||||
nsresult rv ;
|
||||
|
||||
void* info = 0 ;
|
||||
PRUint32 info_size = 0 ;
|
||||
|
||||
rv = m_DB->Get(RecordID, &info, &info_size) ;
|
||||
if(NS_SUCCEEDED(rv) && info) {
|
||||
|
||||
// construct an empty record if only found in db
|
||||
nsDiskCacheRecord* newRecord = new nsDiskCacheRecord(m_DB, this) ;
|
||||
if(!newRecord)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
NS_ADDREF(newRecord) ; // addref for _retval
|
||||
rv = newRecord->RetrieveInfo(info, info_size) ;
|
||||
|
||||
if(NS_SUCCEEDED(rv)) {
|
||||
*_retval = (nsINetDataCacheRecord*) newRecord ;
|
||||
return NS_OK ;
|
||||
}
|
||||
else {
|
||||
// bad record, I guess
|
||||
NS_RELEASE(newRecord) ; // release if bad things happen
|
||||
return rv ;
|
||||
}
|
||||
} else {
|
||||
NS_ERROR("Error: RecordID not in DB\n") ;
|
||||
DBRecovery() ;
|
||||
return rv ;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetEnabled(PRBool *aEnabled)
|
||||
{
|
||||
*aEnabled = m_Enabled ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::SetEnabled(PRBool aEnabled)
|
||||
{
|
||||
m_Enabled = aEnabled ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetFlags(PRUint32 *aFlags)
|
||||
{
|
||||
*aFlags = FILE_PER_URL_CACHE;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetNumEntries(PRUint32 *aNumEntries)
|
||||
{
|
||||
*aNumEntries = m_NumEntries ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetMaxEntries(PRUint32 *aMaxEntries)
|
||||
{
|
||||
*aMaxEntries = m_MaxEntries ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::NewCacheEntryIterator(nsISimpleEnumerator **_retval)
|
||||
{
|
||||
NS_ASSERTION(m_DB, "no db.") ;
|
||||
|
||||
if(!_retval)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*_retval = nsnull ;
|
||||
|
||||
nsISimpleEnumerator* enumerator = new nsDBEnumerator(m_DB, this) ;
|
||||
if(enumerator) {
|
||||
NS_ADDREF(enumerator) ;
|
||||
*_retval = enumerator ;
|
||||
return NS_OK ;
|
||||
}
|
||||
else
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetNextCache(nsINetDataCache * *aNextCache)
|
||||
{
|
||||
if(!aNextCache)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*aNextCache = m_pNextCache ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::SetNextCache(nsINetDataCache *aNextCache)
|
||||
{
|
||||
m_pNextCache = aNextCache ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
// db size can always be measured at the last minute. Since it's hard
|
||||
// to know before hand.
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetStorageInUse(PRUint32 *aStorageInUse)
|
||||
{
|
||||
NS_ASSERTION(m_DB, "no db.") ;
|
||||
|
||||
PRUint32 total_size = m_StorageInUse ;
|
||||
|
||||
/*
|
||||
PRUint32 len = 0 ;
|
||||
// add the size of the db.
|
||||
m_DB->GetDBFilesize(&len) ;
|
||||
total_size += len ;
|
||||
*/
|
||||
|
||||
// we need size in kB
|
||||
total_size = total_size >> 10 ;
|
||||
|
||||
*aStorageInUse = total_size ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
/*
|
||||
* The whole cache dirs can be whiped clean since all the cache
|
||||
* files are resides in seperate hashed dirs. It's safe to do so.
|
||||
*/
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::RemoveAll(void)
|
||||
{
|
||||
NS_ASSERTION(m_DB, "no db.") ;
|
||||
NS_ASSERTION(m_pDiskCacheFolder, "no cache folder.") ;
|
||||
|
||||
// remove all the sub folders
|
||||
nsFileSpec cacheSubDir;
|
||||
|
||||
for (int i=0; i < 32; i++) {
|
||||
m_pDiskCacheFolder->GetFileSpec(&cacheSubDir) ;
|
||||
|
||||
char dirName[3];
|
||||
PR_snprintf (dirName, 3, "%0.2x", i);
|
||||
cacheSubDir += dirName ;
|
||||
RemoveFolder(cacheSubDir) ;
|
||||
}
|
||||
|
||||
// don't forget the db file itself
|
||||
m_DB->Shutdown() ;
|
||||
nsFileSpec dbfile ;
|
||||
m_DBFile->GetFileSpec(&dbfile) ;
|
||||
dbfile.Delete(PR_TRUE) ;
|
||||
|
||||
// reinitilize
|
||||
return Init() ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// nsINetDataDiskCache methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetDiskCacheFolder(nsIFileSpec * *aDiskCacheFolder)
|
||||
{
|
||||
*aDiskCacheFolder = nsnull ;
|
||||
NS_ASSERTION(m_pDiskCacheFolder, "no cache folder.") ;
|
||||
|
||||
*aDiskCacheFolder = m_pDiskCacheFolder ;
|
||||
NS_ADDREF(*aDiskCacheFolder) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::SetDiskCacheFolder(nsIFileSpec * aDiskCacheFolder)
|
||||
{
|
||||
if(!m_pDiskCacheFolder) {
|
||||
NS_NewFileSpec(getter_AddRefs(m_pDiskCacheFolder));
|
||||
if(!m_pDiskCacheFolder)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
m_pDiskCacheFolder = aDiskCacheFolder ;
|
||||
return Init() ;
|
||||
}
|
||||
else {
|
||||
char *newfolder, *oldfolder ;
|
||||
m_pDiskCacheFolder->GetNativePath(&oldfolder) ;
|
||||
aDiskCacheFolder->GetNativePath(&newfolder) ;
|
||||
|
||||
if(PL_strcmp(newfolder, oldfolder) != 0) {
|
||||
m_pDiskCacheFolder = aDiskCacheFolder ;
|
||||
|
||||
// do we need to blow away old cache before building a new one?
|
||||
// return RemoveAll() ;
|
||||
|
||||
m_DB->Shutdown() ;
|
||||
return Init() ;
|
||||
|
||||
} else
|
||||
return NS_OK ;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// nsNetDiskCache methods
|
||||
|
||||
// create a directory (recursively)
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::CreateDir(nsIFileSpec* dir_spec)
|
||||
{
|
||||
PRBool does_exist ;
|
||||
nsCOMPtr<nsIFileSpec> p_spec ;
|
||||
|
||||
dir_spec->Exists(&does_exist) ;
|
||||
if(does_exist)
|
||||
return NS_OK ;
|
||||
|
||||
nsresult rv = dir_spec->GetParent(getter_AddRefs(p_spec)) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
p_spec->Exists(&does_exist) ;
|
||||
if(!does_exist) {
|
||||
CreateDir(p_spec) ;
|
||||
rv = dir_spec->CreateDir() ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
}
|
||||
else {
|
||||
rv = dir_spec->CreateDir() ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
}
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
// We can't afford to make a *separate* pass over the whole db on every
|
||||
// startup, just to figure out m_NumEntries and m_StorageInUse. (This is a
|
||||
// several second operation on a large db). We'll likely need to store
|
||||
// distinguished keys in the db that contain these values and update them
|
||||
// incrementally, except when failure to shut down the db cleanly is detected.
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetSpecialEntry(void)
|
||||
{
|
||||
void* pInfo ;
|
||||
PRUint32 InfoSize ;
|
||||
|
||||
nsresult rv = m_DB->GetSpecialEntry(&pInfo, &InfoSize) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
if(!pInfo && InfoSize == 0) {
|
||||
// must be a new DB
|
||||
m_NumEntries = 0 ;
|
||||
m_StorageInUse = 0 ;
|
||||
}
|
||||
else {
|
||||
char * cur_ptr = NS_STATIC_CAST(char*, pInfo) ;
|
||||
|
||||
// get m_NumEntries
|
||||
COPY_INT32(&m_NumEntries, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// get m_StorageInUse
|
||||
COPY_INT32(&m_StorageInUse, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, pInfo) + InfoSize);
|
||||
}
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::SetSpecialEntry(void)
|
||||
{
|
||||
PRUint32 InfoSize ;
|
||||
|
||||
InfoSize = sizeof m_NumEntries ;
|
||||
InfoSize += sizeof m_StorageInUse ;
|
||||
|
||||
void* pInfo = nsAllocator::Alloc(InfoSize*sizeof(char)) ;
|
||||
if(!pInfo)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
char* cur_ptr = NS_STATIC_CAST(char*, pInfo) ;
|
||||
|
||||
COPY_INT32(cur_ptr, &m_NumEntries) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
COPY_INT32(cur_ptr, &m_StorageInUse) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, pInfo) + InfoSize);
|
||||
|
||||
return m_DB->SetSpecialEntry(pInfo, InfoSize) ;
|
||||
}
|
||||
|
||||
// this routine will be called everytime we have a db corruption.
|
||||
// m_DB will be re-initialized, m_StorageInUse and m_NumEntries will
|
||||
// be reset.
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::DBRecovery(void)
|
||||
{
|
||||
// rename all the sub cache dirs and remove them later during dtor.
|
||||
nsresult rv = RenameCacheSubDirs() ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
// remove corrupted db file, don't care if db->shutdown fails or not.
|
||||
m_DB->Shutdown() ;
|
||||
|
||||
nsFileSpec dbfile ;
|
||||
m_DBFile->GetFileSpec(&dbfile) ;
|
||||
dbfile.Delete(PR_TRUE) ;
|
||||
|
||||
// make sure it's not there any more
|
||||
PRBool exists = dbfile.Exists() ;
|
||||
if(exists) {
|
||||
NS_ERROR("can't remove old db.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
// reinitilize DB
|
||||
return InitDB() ;
|
||||
}
|
||||
|
||||
// this routine will add string "trash" to current CacheSubDir names.
|
||||
// e.g. 00->trash00, 1f->trash1f. and update the m_DBCorrupted.
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::RenameCacheSubDirs(void)
|
||||
{
|
||||
nsCOMPtr<nsIFileSpec> cacheSubDir;
|
||||
nsresult rv = NS_NewFileSpec(getter_AddRefs(cacheSubDir)) ;
|
||||
|
||||
for (int i=0; i < 32; i++) {
|
||||
rv = cacheSubDir->FromFileSpec(m_pDiskCacheFolder) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
char oldName[3], newName[8];
|
||||
PR_snprintf(oldName, 3, "%0.2x", i) ;
|
||||
cacheSubDir->AppendRelativeUnixPath(oldName) ;
|
||||
|
||||
// re-name the directory
|
||||
PR_snprintf(newName, 8, "trash%0.2x", i) ;
|
||||
rv = cacheSubDir->Rename(newName) ;
|
||||
if(NS_FAILED(rv))
|
||||
// TODO, error checking
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
// update m_DBCorrupted
|
||||
m_DBCorrupted = PR_TRUE ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
// this routine is used by dtor and RemoveAll() to clean up dirs.
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::RemoveFolder(nsFileSpec aFolder)
|
||||
{
|
||||
for(nsDirectoryIterator di(aFolder, PR_FALSE); di.Exists(); di++) {
|
||||
di.Spec().Delete(PR_TRUE) ;
|
||||
}
|
||||
|
||||
aFolder.Delete(PR_FALSE) ; // recursive delete
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
91
mozilla/netwerk/cache/filecache/nsNetDiskCache.h
vendored
Normal file
91
mozilla/netwerk/cache/filecache/nsNetDiskCache.h
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of filecache implementation.
|
||||
*
|
||||
* nsNetDiskCache is the main disk cache module that will create
|
||||
* the cache database, and then store and retrieve nsDiskCacheRecord
|
||||
* objects from it. It also contains some basic error recovery procedure.
|
||||
*/
|
||||
|
||||
#ifndef __gen_nsNetDiskCache_h__
|
||||
#define __gen_nsNetDiskCache_h__
|
||||
|
||||
#include "nsINetDataDiskCache.h"
|
||||
#include "nsNetDiskCacheCID.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIPref.h"
|
||||
#include "nsDBAccessor.h"
|
||||
|
||||
class nsIURI; /* forward decl */
|
||||
class nsICachedNetData; /* forward decl */
|
||||
class nsISimpleEnumerator; /* forward decl */
|
||||
class nsIFileSpec; /* forward decl */
|
||||
|
||||
/* starting interface: nsNetDiskCache */
|
||||
|
||||
class nsNetDiskCache : public nsINetDataDiskCache {
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSINETDATACACHE
|
||||
NS_DECL_NSINETDATADISKCACHE
|
||||
|
||||
NS_IMETHOD Init(void) ;
|
||||
|
||||
nsNetDiskCache() ;
|
||||
virtual ~nsNetDiskCache() ;
|
||||
|
||||
protected:
|
||||
|
||||
NS_IMETHOD InitDB(void) ;
|
||||
NS_IMETHOD CreateDir(nsIFileSpec* dir_spec) ;
|
||||
NS_IMETHOD GetSpecialEntry(void) ;
|
||||
NS_IMETHOD SetSpecialEntry(void) ;
|
||||
|
||||
NS_IMETHOD RenameCacheSubDirs(void) ;
|
||||
NS_IMETHOD DBRecovery(void) ;
|
||||
NS_IMETHOD RemoveFolder(nsFileSpec aFolder) ;
|
||||
|
||||
private:
|
||||
|
||||
PRBool m_Enabled ;
|
||||
PRUint32 m_NumEntries ;
|
||||
nsCOMPtr<nsINetDataCache> m_pNextCache ;
|
||||
nsCOMPtr<nsIFileSpec> m_pDiskCacheFolder ;
|
||||
nsCOMPtr<nsIFileSpec> m_DBFile ;
|
||||
|
||||
PRUint32 m_MaxEntries ;
|
||||
PRUint32 m_StorageInUse ;
|
||||
nsIDBAccessor* m_DB ;
|
||||
|
||||
// this is used to indicate a db corruption
|
||||
PRBool m_DBCorrupted ;
|
||||
|
||||
friend class nsDiskCacheRecord ;
|
||||
friend class nsDiskCacheRecordChannel ;
|
||||
friend class nsDBEnumerator ;
|
||||
} ;
|
||||
|
||||
#endif /* __gen_nsNetDiskCache_h__ */
|
||||
32
mozilla/netwerk/cache/filecache/nsNetDiskCacheCID.h
vendored
Normal file
32
mozilla/netwerk/cache/filecache/nsNetDiskCacheCID.h
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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 Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
#ifndef _nsNetDiskCacheCID_h_
|
||||
#define _nsNetDiskCacheCID_h_
|
||||
|
||||
#define NS_NETDISKCACHE_CID_STR "ECFEEA00-7201-11d3-87FE-000629D01344"
|
||||
|
||||
#define NS_NETDISKCACHE_CID \
|
||||
{ 0xecfeea00, 0x7201, 0x11d3, \
|
||||
{ 0x87, 0xfe, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44 }}
|
||||
|
||||
#endif /* _nsNetDiskCacheCID_h_ */
|
||||
50
mozilla/netwerk/cache/filecache/test/Makefile.in
vendored
Normal file
50
mozilla/netwerk/cache/filecache/test/Makefile.in
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
REQUIRES = libreg xpcom
|
||||
|
||||
CPPSRCS = \
|
||||
diskcache.cpp \
|
||||
$(NULL)
|
||||
|
||||
SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=)
|
||||
|
||||
ifdef NO_LD_ARCHIVE_FLAGS
|
||||
LOST_SYM_LIBS = -lxpcomds_s -lxptinfo -lmozreg_s
|
||||
endif
|
||||
|
||||
LIBS = \
|
||||
-lmozjs \
|
||||
-lxpcom \
|
||||
-lmozdbm_s \
|
||||
$(MOZ_NECKO_UTIL_LIBS) \
|
||||
$(LOST_SYM_LIBS) \
|
||||
$(NSPR_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
LOCAL_INCLUDES = -I$(srcdir)/..
|
||||
|
||||
DEFINES += -DUSE_NSREG -DCACHE
|
||||
836
mozilla/netwerk/cache/filecache/test/diskcache.cpp
vendored
Normal file
836
mozilla/netwerk/cache/filecache/test/diskcache.cpp
vendored
Normal file
@@ -0,0 +1,836 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIStreamObserver.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIEventQueue.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsINetDataCacheRecord.h"
|
||||
//#include "nsMemCacheCID.h"
|
||||
#include "nsNetDiskCache.h"
|
||||
#include "nsIPref.h"
|
||||
#include "prenv.h"
|
||||
#include "nsIFileStream.h"
|
||||
|
||||
// Number of test entries to be placed in the cache
|
||||
#define NUM_CACHE_ENTRIES 250
|
||||
|
||||
// Cache content stream length will have random length between zero and
|
||||
// MAX_CONTENT_LENGTH bytes
|
||||
#define MAX_CONTENT_LENGTH 20000
|
||||
|
||||
// Length of random-data cache entry key
|
||||
#define CACHE_KEY_LENGTH 15
|
||||
|
||||
// Length of random-data cache entry meta-data
|
||||
#define CACHE_METADATA_LENGTH 100
|
||||
|
||||
//static NS_DEFINE_CID(kMemCacheCID, NS_MEM_CACHE_FACTORY_CID);
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
static NS_DEFINE_CID(kDiskCacheCID, NS_NETDISKCACHE_CID) ;
|
||||
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
|
||||
static NS_DEFINE_IID(kIPrefIID, NS_IPREF_IID);
|
||||
|
||||
// Mapping from test case number to RecordID
|
||||
static PRInt32 recordID[NUM_CACHE_ENTRIES];
|
||||
|
||||
static PRInt32
|
||||
mapRecordIdToTestNum(PRInt32 aRecordID)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NUM_CACHE_ENTRIES; i++) {
|
||||
if (recordID[i] == aRecordID)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// A supply of stream data to either store or compare with
|
||||
class nsITestDataStream {
|
||||
public:
|
||||
virtual ~nsITestDataStream() {};
|
||||
virtual PRUint32 Next() = 0;
|
||||
virtual void Read(char* aBuf, PRUint32 aCount) = 0;
|
||||
|
||||
virtual PRBool Match(char* aBuf, PRUint32 aCount) = 0;
|
||||
virtual void Skip(PRUint32 aCount) = 0;
|
||||
};
|
||||
|
||||
// A reproducible stream of random data.
|
||||
class RandomStream : public nsITestDataStream {
|
||||
public:
|
||||
RandomStream(PRUint32 aSeed) {
|
||||
mStartSeed = mState = aSeed;
|
||||
}
|
||||
|
||||
PRUint32 GetStartSeed() {
|
||||
return mStartSeed;
|
||||
}
|
||||
|
||||
PRUint32 Next() {
|
||||
mState = 1103515245 * mState + 12345;
|
||||
return mState;
|
||||
}
|
||||
|
||||
void Read(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
*aBuf++ = Next();
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
Match(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
if (*aBuf++ != (char)(Next() & 0xff))
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Skip(PRUint32 aCount) {
|
||||
while (aCount--)
|
||||
Next();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mState;
|
||||
PRUint32 mStartSeed;
|
||||
};
|
||||
|
||||
// A stream of data that increments on each byte that is read, modulo 256
|
||||
class CounterStream : public nsITestDataStream {
|
||||
public:
|
||||
CounterStream(PRUint32 aSeed) {
|
||||
mStartSeed = mState = aSeed;
|
||||
}
|
||||
|
||||
PRUint32 GetStartSeed() {
|
||||
return mStartSeed;
|
||||
}
|
||||
|
||||
PRUint32 Next() {
|
||||
mState += 1;
|
||||
mState &= 0xff;
|
||||
return mState;
|
||||
}
|
||||
|
||||
void Read(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
*aBuf++ = Next();
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
Match(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
if (*aBuf++ != (char)Next())
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Skip(PRUint32 aCount) {
|
||||
mState += aCount;
|
||||
mState &= 0xff;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mState;
|
||||
PRUint32 mStartSeed;
|
||||
};
|
||||
|
||||
static int gNumReaders = 0;
|
||||
static PRUint32 gTotalBytesRead = 0;
|
||||
static PRUint32 gTotalDuration = 0;
|
||||
|
||||
class nsReader : public nsIStreamListener {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsReader()
|
||||
: mStartTime(0), mBytesRead(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
gNumReaders++;
|
||||
}
|
||||
|
||||
virtual ~nsReader() {
|
||||
delete mTestDataStream;
|
||||
gNumReaders--;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Init(nsIChannel *aChannel, nsITestDataStream* aRandomStream, PRUint32 aExpectedStreamLength) {
|
||||
mChannel = aChannel;
|
||||
mTestDataStream = aRandomStream;
|
||||
mExpectedStreamLength = aExpectedStreamLength;
|
||||
mRefCnt = 1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStartRequest(nsIChannel* channel,
|
||||
nsISupports* context) {
|
||||
mStartTime = PR_IntervalNow();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnDataAvailable(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsIInputStream *aIStream,
|
||||
PRUint32 aSourceOffset,
|
||||
PRUint32 aLength) {
|
||||
char buf[1025];
|
||||
while (aLength > 0) {
|
||||
PRUint32 amt;
|
||||
PRBool match;
|
||||
aIStream->Read(buf, sizeof buf, &amt);
|
||||
if (amt == 0) break;
|
||||
aLength -= amt;
|
||||
mBytesRead += amt;
|
||||
match = mTestDataStream->Match(buf, amt);
|
||||
NS_ASSERTION(match, "Stored data was corrupted on read");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStopRequest(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsresult aStatus,
|
||||
const PRUnichar* aMsg) {
|
||||
PRIntervalTime endTime;
|
||||
PRIntervalTime duration;
|
||||
|
||||
endTime = PR_IntervalNow();
|
||||
duration = (endTime - mStartTime);
|
||||
|
||||
if (NS_FAILED(aStatus)) printf("channel failed.\n");
|
||||
// printf("read %d bytes\n", mBytesRead);
|
||||
|
||||
NS_ASSERTION(mBytesRead == mExpectedStreamLength,
|
||||
"Stream in cache is wrong length");
|
||||
|
||||
gTotalBytesRead += mBytesRead;
|
||||
gTotalDuration += duration;
|
||||
|
||||
// Release channel
|
||||
mChannel = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
PRIntervalTime mStartTime;
|
||||
PRUint32 mBytesRead;
|
||||
nsITestDataStream* mTestDataStream;
|
||||
PRUint32 mExpectedStreamLength;
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsReader, nsIStreamListener, nsIStreamObserver)
|
||||
|
||||
static nsIEventQueue* eventQueue;
|
||||
|
||||
nsresult
|
||||
InitQueue() {
|
||||
nsresult rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue service");
|
||||
|
||||
rv = eventQService->CreateThreadEventQueue();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create event queue");
|
||||
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQueue);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue for main thread");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Process events until all streams are OnStopRequest'ed
|
||||
nsresult
|
||||
WaitForEvents() {
|
||||
while (gNumReaders) {
|
||||
eventQueue->ProcessPendingEvents();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Read data for a single cache record and compare against testDataStream
|
||||
nsresult
|
||||
TestReadStream(nsINetDataCacheRecord *record, nsITestDataStream *testDataStream,
|
||||
PRUint32 expectedStreamLength)
|
||||
{
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsresult rv;
|
||||
PRUint32 actualContentLength;
|
||||
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = record->GetStoredContentLength(&actualContentLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(actualContentLength == expectedStreamLength,
|
||||
"nsINetDataCacheRecord::GetContentLength() busted ?");
|
||||
|
||||
nsReader *reader = new nsReader;
|
||||
reader->AddRef();
|
||||
rv = reader->Init(channel, testDataStream, expectedStreamLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = channel->AsyncRead(0, -1, 0, reader);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
reader->Release();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check that records can be retrieved using their record-ID, in addition
|
||||
// to using the opaque key.
|
||||
nsresult
|
||||
TestRecordID(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char *metaData;
|
||||
PRUint32 testNum;
|
||||
PRBool match;
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
rv = cache->GetCachedNetDataByID(recordID[testNum], getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't obtain record using record ID");
|
||||
|
||||
// Match against previously stored meta-data
|
||||
rv = record->GetMetaData(&metaDataLength, &metaData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
|
||||
match = randomStream->Match(metaData, metaDataLength);
|
||||
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
|
||||
|
||||
nsAllocator::Free(metaData);
|
||||
delete randomStream;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check that all cache entries in the database are enumerated and that
|
||||
// no duplicates appear.
|
||||
nsresult
|
||||
TestEnumeration(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCOMPtr<nsISupports> tempISupports;
|
||||
nsCOMPtr<nsISimpleEnumerator> iterator;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char *metaData;
|
||||
PRUint32 testNum;
|
||||
PRBool match;
|
||||
PRInt32 recID;
|
||||
|
||||
int numRecords = 0;
|
||||
|
||||
// Iterate over all records in the cache
|
||||
rv = cache->NewCacheEntryIterator(getter_AddRefs(iterator));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create new cache entry iterator");
|
||||
|
||||
PRBool notDone;
|
||||
while (1) {
|
||||
|
||||
// Done iterating ?
|
||||
rv = iterator->HasMoreElements(¬Done);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!notDone)
|
||||
break;
|
||||
|
||||
// Get next record in iteration
|
||||
rv = iterator->GetNext(getter_AddRefs(tempISupports));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "iterator bustage");
|
||||
record = do_QueryInterface(tempISupports);
|
||||
|
||||
numRecords++;
|
||||
|
||||
// Get record ID
|
||||
rv = record->GetRecordID(&recID);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
|
||||
testNum = mapRecordIdToTestNum(recID);
|
||||
NS_ASSERTION(testNum != -1, "Corrupted Record ID ?");
|
||||
|
||||
// Erase mapping from table, so that duplicate enumerations are detected
|
||||
recordID[testNum] = -1;
|
||||
|
||||
// Make sure stream matches test data
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
// Match against previously stored meta-data
|
||||
rv = record->GetMetaData(&metaDataLength, &metaData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
|
||||
match = randomStream->Match(metaData, metaDataLength);
|
||||
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
|
||||
nsAllocator::Free(metaData);
|
||||
|
||||
delete randomStream;
|
||||
}
|
||||
|
||||
NS_ASSERTION(numRecords == NUM_CACHE_ENTRIES, "Iteration bug");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Read the test data that was written in FillCache(), checking for
|
||||
// corruption, truncation.
|
||||
nsresult
|
||||
TestRead(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inCache;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char *metaData, *storedCacheKey;
|
||||
PRUint32 testNum, storedCacheKeyLength;
|
||||
PRBool match;
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
// Ensure that entry is in the cache
|
||||
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
// Match against previously stored meta-data
|
||||
match = record->GetMetaData(&metaDataLength, &metaData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
match = randomStream->Match(metaData, metaDataLength);
|
||||
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
|
||||
nsAllocator::Free(metaData);
|
||||
|
||||
// Test GetKey() method
|
||||
rv = record->GetKey(&storedCacheKeyLength, &storedCacheKey);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) &&
|
||||
(storedCacheKeyLength == sizeof cacheKey) &&
|
||||
!memcmp(storedCacheKey, &cacheKey[0], sizeof cacheKey),
|
||||
"nsINetDataCacheRecord::GetKey failed");
|
||||
nsAllocator::Free(storedCacheKey);
|
||||
|
||||
PRUint32 expectedStreamLength = randomStream->Next() & 0xffff;
|
||||
|
||||
TestReadStream(record, randomStream, expectedStreamLength);
|
||||
}
|
||||
|
||||
WaitForEvents();
|
||||
|
||||
// Compute rate in MB/s
|
||||
double rate = gTotalBytesRead / PR_IntervalToMilliseconds(gTotalDuration);
|
||||
rate *= NUM_CACHE_ENTRIES;
|
||||
rate *= 1000;
|
||||
rate /= (1024 * 1024);
|
||||
printf("Read %d bytes at a rate of %5.1f MB per second \n",
|
||||
gTotalBytesRead, rate);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Repeatedly call SetStoredContentLength() on a cache entry and make
|
||||
// read the stream's data to ensure that it's not corrupted by the effect
|
||||
nsresult
|
||||
TestTruncation(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
RandomStream *randomStream;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
|
||||
randomStream = new RandomStream(0);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
randomStream->Skip(CACHE_METADATA_LENGTH);
|
||||
PRUint32 initialStreamLength = randomStream->Next() & 0xffff;
|
||||
delete randomStream;
|
||||
|
||||
PRUint32 i;
|
||||
PRUint32 delta = initialStreamLength / 64;
|
||||
for (i = initialStreamLength; i >= delta; i -= delta) {
|
||||
PRUint32 expectedStreamLength = i;
|
||||
|
||||
// Do the truncation
|
||||
record->SetStoredContentLength(expectedStreamLength);
|
||||
randomStream = new RandomStream(0);
|
||||
randomStream->Skip(CACHE_KEY_LENGTH + CACHE_METADATA_LENGTH + 1);
|
||||
|
||||
TestReadStream(record, randomStream, expectedStreamLength);
|
||||
WaitForEvents();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Write known data to random offsets in a single cache entry and test
|
||||
// resulting stream for correctness.
|
||||
nsresult
|
||||
TestOffsetWrites(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsIOutputStream> outStream;
|
||||
char buf[512];
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
RandomStream *randomStream;
|
||||
|
||||
randomStream = new RandomStream(0);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
|
||||
|
||||
|
||||
nsCOMPtr<nsIFileSpec> file ;
|
||||
record->GetFilename(getter_AddRefs(file)) ;
|
||||
char* name ;
|
||||
file->GetUnixStyleFilePath(&name) ;
|
||||
printf(" file name is %s \n", name) ;
|
||||
|
||||
// Write buffer-fulls of data at random offsets into the cache entry.
|
||||
// Data written is (offset % 0xff)
|
||||
PRUint32 startingOffset;
|
||||
PRUint32 streamLength = 0;
|
||||
PRUint32 len = 0 ;
|
||||
CounterStream *counterStream;
|
||||
|
||||
int i = 0;
|
||||
for (i = 0; i < 257; i++) {
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
startingOffset = streamLength ? streamLength - (randomStream->Next() % sizeof buf): 0;
|
||||
rv = channel->OpenOutputStream(startingOffset, getter_AddRefs(outStream));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
truncate(name, startingOffset) ;
|
||||
|
||||
counterStream = new CounterStream(startingOffset);
|
||||
counterStream->Read(buf, sizeof buf);
|
||||
|
||||
nsresult status ;
|
||||
nsCOMPtr<nsIRandomAccessStore> ras = do_QueryInterface(outStream, &status);
|
||||
if (NS_FAILED(status)) {
|
||||
// mState = END_WRITE;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
PRIntn offset ;
|
||||
ras->Tell(&offset) ;
|
||||
// printf(" offset is %d \n", offset) ;
|
||||
|
||||
PRUint32 numWritten;
|
||||
rv = outStream->Write(buf, sizeof buf, &numWritten);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(numWritten == sizeof buf, "Write() bug?");
|
||||
streamLength = startingOffset + sizeof buf;
|
||||
|
||||
rv = outStream->Close();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't close channel");
|
||||
delete counterStream;
|
||||
|
||||
record->GetStoredContentLength(&len) ;
|
||||
if(len != streamLength)
|
||||
printf(" offset = %d is wrong, filesize = %d\n", startingOffset, len) ;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
startingOffset = 208;
|
||||
rv = channel->OpenOutputStream(startingOffset, getter_AddRefs(outStream));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
counterStream = new CounterStream(startingOffset);
|
||||
counterStream->Read(buf, sizeof buf);
|
||||
|
||||
nsresult status ;
|
||||
nsCOMPtr<nsIRandomAccessStore> ras = do_QueryInterface(outStream, &status);
|
||||
if (NS_FAILED(status)) {
|
||||
// mState = END_WRITE;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
PRIntn offset = 0 ;
|
||||
ras->Tell(&offset) ;
|
||||
printf(" offset is %d \n", offset) ;
|
||||
|
||||
PRUint32 numWritten;
|
||||
rv = outStream->Write(buf, sizeof buf, &numWritten);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(numWritten == sizeof buf, "Write() bug?");
|
||||
streamLength = startingOffset + sizeof buf;
|
||||
|
||||
rv = outStream->Close();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't close channel");
|
||||
delete counterStream;
|
||||
|
||||
record->GetStoredContentLength(&len) ;
|
||||
if(len != streamLength)
|
||||
printf(" offset = %d is wrong, filesize = %d\n", startingOffset, len) ;
|
||||
*/
|
||||
|
||||
delete randomStream;
|
||||
|
||||
counterStream = new CounterStream(0);
|
||||
TestReadStream(record, counterStream, streamLength);
|
||||
WaitForEvents();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Create entries in the network data cache, using random data for the
|
||||
// key, the meta-data and the stored content data.
|
||||
nsresult
|
||||
FillCache(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inCache;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsIOutputStream> outStream;
|
||||
char buf[1000];
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char metaData[CACHE_METADATA_LENGTH];
|
||||
PRUint32 testNum;
|
||||
char *data;
|
||||
RandomStream *randomStream;
|
||||
|
||||
PRIntervalTime startTime = PR_IntervalNow();
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
// No entry should be in cache until we add it
|
||||
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(!inCache, "nsINetDataCache::Contains error");
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
|
||||
|
||||
// Test nsINetDataCacheRecord::GetRecordID()
|
||||
rv = record->GetRecordID(&recordID[testNum]);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
|
||||
|
||||
// Test nsINetDataCache::GetNumEntries()
|
||||
PRUint32 numEntries = (PRUint32)-1;
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == testNum + 1, "GetNumEntries failure");
|
||||
|
||||
// Record meta-data should be initially empty
|
||||
rv = record->GetMetaData(&metaDataLength, &data);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
if ((metaDataLength != 0) || (data != 0))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Store random data as meta-data
|
||||
randomStream->Read(metaData, sizeof metaData);
|
||||
record->SetMetaData(sizeof metaData, metaData);
|
||||
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = channel->OpenOutputStream(0, getter_AddRefs(outStream));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
PRUint32 beforeOccupancy;
|
||||
rv = cache->GetStorageInUse(&beforeOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
|
||||
int streamLength = randomStream->Next() & 0xffff;
|
||||
int remaining = streamLength;
|
||||
while (remaining) {
|
||||
PRUint32 numWritten;
|
||||
int amount = PR_MIN(sizeof buf, remaining);
|
||||
randomStream->Read(buf, amount);
|
||||
|
||||
rv = outStream->Write(buf, amount, &numWritten);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(numWritten == (PRUint32)amount, "Write() bug?");
|
||||
|
||||
remaining -= amount;
|
||||
}
|
||||
outStream->Close();
|
||||
|
||||
PRUint32 afterOccupancy;
|
||||
rv = cache->GetStorageInUse(&afterOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
PRUint32 streamLengthInKB = streamLength >> 10;
|
||||
NS_ASSERTION((afterOccupancy - beforeOccupancy) >= streamLengthInKB,
|
||||
"nsINetDataCache::GetStorageInUse() is busted");
|
||||
|
||||
|
||||
// *Now* there should be an entry in the cache
|
||||
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
|
||||
|
||||
delete randomStream;
|
||||
}
|
||||
|
||||
PRIntervalTime endTime = PR_IntervalNow();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult NS_AutoregisterComponents()
|
||||
{
|
||||
nsresult rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup,
|
||||
NULL /* default */);
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRBool initPref ()
|
||||
{
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIPref, prefPtr, kPrefCID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
nsCOMPtr<nsIFileSpec> fileSpec;
|
||||
rv = NS_NewFileSpec (getter_AddRefs(fileSpec));
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
nsCString defaultPrefFile = PR_GetEnv ("MOZILLA_FIVE_HOME");
|
||||
if (defaultPrefFile.Length())
|
||||
defaultPrefFile += "/";
|
||||
else
|
||||
defaultPrefFile = "./";
|
||||
defaultPrefFile += "default_prefs.js";
|
||||
|
||||
fileSpec->SetUnixStyleFilePath (defaultPrefFile.GetBuffer());
|
||||
|
||||
PRBool exists = false;
|
||||
fileSpec->Exists(&exists);
|
||||
if (exists)
|
||||
prefPtr->ReadUserPrefsFrom(fileSpec);
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
initPref() ;
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCache> cache;
|
||||
|
||||
rv = NS_AutoregisterComponents();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't register XPCOM components");
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kDiskCacheCID, nsnull,
|
||||
NS_GET_IID(nsINetDataCache),
|
||||
getter_AddRefs(cache));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create memory cache factory");
|
||||
|
||||
InitQueue();
|
||||
|
||||
PRUnichar* description;
|
||||
rv = cache->GetDescription(&description);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache description");
|
||||
nsCAutoString descStr(description);
|
||||
printf("Testing: %s\n", descStr.GetBuffer());
|
||||
|
||||
rv = cache->RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
|
||||
|
||||
PRUint32 startOccupancy;
|
||||
rv = cache->GetStorageInUse(&startOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
|
||||
PRUint32 numEntries = (PRUint32)-1;
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
|
||||
|
||||
rv = FillCache(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't fill cache with random test data");
|
||||
|
||||
rv = TestRead(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't read random test data from cache");
|
||||
|
||||
rv = TestRecordID(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't index records using record ID");
|
||||
|
||||
rv = TestEnumeration(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully enumerate records");
|
||||
|
||||
rv = TestTruncation(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully truncate records");
|
||||
|
||||
rv = TestOffsetWrites(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully write to records using non-zero offsets");
|
||||
|
||||
rv = cache->RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
|
||||
|
||||
PRUint32 endOccupancy;
|
||||
rv = cache->GetStorageInUse(&endOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
|
||||
NS_ASSERTION(startOccupancy == endOccupancy, "Cache occupancy not correctly computed ?");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
48
mozilla/netwerk/cache/memcache/Makefile.in
vendored
Normal file
48
mozilla/netwerk/cache/memcache/Makefile.in
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
# Generated automatically from Makefile.in by configure.
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
srcdir = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
LIBRARY_NAME = nkmemcache_s
|
||||
|
||||
REQUIRES = nspr dbm
|
||||
|
||||
EXPORTS=nsMemCacheCID.h \
|
||||
nsMemCache.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
nsMemCache.cpp \
|
||||
nsMemCacheRecord.cpp \
|
||||
nsMemCacheChannel.cpp \
|
||||
$(NULL)
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a
|
||||
# static lib.
|
||||
override NO_SHARED_LIB=1
|
||||
override NO_STATIC_LIB=
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
42
mozilla/netwerk/cache/memcache/makefile.win
vendored
Normal file
42
mozilla/netwerk/cache/memcache/makefile.win
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
#!nmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=..\..\..
|
||||
|
||||
include <$(DEPTH)/config/config.mak>
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
LIBRARY_NAME = nkmemcache_s
|
||||
|
||||
CPP_OBJS = \
|
||||
.\$(OBJDIR)\nsMemCache.obj \
|
||||
.\$(OBJDIR)\nsMemCacheRecord.obj \
|
||||
.\$(OBJDIR)\nsMemCacheChannel.obj \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS=nsMemCacheCID.h
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
install:: $(LIBRARY)
|
||||
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
|
||||
|
||||
clobber::
|
||||
rm -rf $(OBJDIR)
|
||||
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib
|
||||
|
||||
334
mozilla/netwerk/cache/memcache/nsMemCache.cpp
vendored
Normal file
334
mozilla/netwerk/cache/memcache/nsMemCache.cpp
vendored
Normal file
@@ -0,0 +1,334 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* nsMemCache is the implementation of an in-memory network-data
|
||||
* cache, used to cache the responses to network retrieval commands.
|
||||
* Each cache entry may contain both content, e.g. GIF image data, and
|
||||
* associated metadata, e.g. HTTP headers. Each entry is indexed by
|
||||
* two different keys: a record id number and an opaque key, which is
|
||||
* created by the cache manager by combining the URI with a "secondary
|
||||
* key", e.g. HTTP post data.
|
||||
*/
|
||||
|
||||
#include "nsMemCache.h"
|
||||
#include "nsMemCacheRecord.h"
|
||||
#include "nsIGenericFactory.h"
|
||||
#include "nsString.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsHashtableEnumerator.h"
|
||||
#include "nsEnumeratorUtils.h"
|
||||
|
||||
PRInt32 nsMemCache::gRecordSerialNumber = 0;
|
||||
|
||||
nsMemCache::nsMemCache()
|
||||
: mNumEntries(0), mOccupancy(0), mEnabled(PR_TRUE),
|
||||
mHashTable(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsMemCache::~nsMemCache()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) && (mNumEntries == 0),
|
||||
"Failure to shut down memory cache. "
|
||||
"Somewhere, someone is holding references to at least one cache record");
|
||||
delete mHashTable;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMemCache::Init()
|
||||
{
|
||||
mHashTable = new nsHashtable(256);
|
||||
if (!mHashTable)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMemCache, NS_GET_IID(nsINetDataCache))
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetDescription(PRUnichar * *aDescription)
|
||||
{
|
||||
nsAutoString description("Memory Cache");
|
||||
*aDescription = description.ToNewUnicode();
|
||||
if (!*aDescription)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::Contains(const char *aKey, PRUint32 aKeyLength, PRBool *aFound)
|
||||
{
|
||||
nsOpaqueKey *opaqueKey = new nsOpaqueKey(aKey, aKeyLength);
|
||||
if (!opaqueKey)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
*aFound = mHashTable->Exists(opaqueKey);
|
||||
delete opaqueKey;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetCachedNetData(const char *aKey, PRUint32 aKeyLength,
|
||||
nsINetDataCacheRecord* *aRecord)
|
||||
{
|
||||
nsresult rv;
|
||||
nsMemCacheRecord* record = 0;
|
||||
nsOpaqueKey *opaqueKey2 = 0;
|
||||
nsOpaqueKey *opaqueKey3 = 0;
|
||||
nsOpaqueKey *opaqueKey;
|
||||
|
||||
opaqueKey = new nsOpaqueKey(aKey, aKeyLength);
|
||||
if (!opaqueKey)
|
||||
goto out_of_memory;
|
||||
record = (nsMemCacheRecord*)mHashTable->Get(opaqueKey);
|
||||
delete opaqueKey;
|
||||
|
||||
// No existing cache database entry was found. Create a new one.
|
||||
// This requires two mappings in the hash table:
|
||||
// Record ID ==> record
|
||||
// Opaque key ==> record
|
||||
if (!record) {
|
||||
record = new nsMemCacheRecord;
|
||||
if (!record)
|
||||
goto out_of_memory;
|
||||
rv = record->Init(aKey, aKeyLength, ++gRecordSerialNumber, this);
|
||||
if (NS_FAILED(rv)) goto out_of_memory;
|
||||
|
||||
// Index the record by opaque key
|
||||
opaqueKey2 = new nsOpaqueKey(record->mKey, record->mKeyLength);
|
||||
if (!opaqueKey2) goto out_of_memory;
|
||||
mHashTable->Put(opaqueKey2, record);
|
||||
|
||||
// Index the record by it's record ID
|
||||
char *recordIDbytes = NS_REINTERPRET_CAST(char *, &record->mRecordID);
|
||||
opaqueKey3 = new nsOpaqueKey(recordIDbytes,
|
||||
sizeof record->mRecordID);
|
||||
if (!opaqueKey3) {
|
||||
// Clean up the first record from the hash table
|
||||
mHashTable->Remove(opaqueKey);
|
||||
goto out_of_memory;
|
||||
}
|
||||
mHashTable->Put(opaqueKey3, record);
|
||||
|
||||
// The hash table holds on to the record
|
||||
record->AddRef();
|
||||
|
||||
delete opaqueKey2;
|
||||
delete opaqueKey3;
|
||||
mNumEntries++;
|
||||
}
|
||||
|
||||
record->AddRef();
|
||||
*aRecord = record;
|
||||
return NS_OK;
|
||||
|
||||
out_of_memory:
|
||||
delete opaqueKey2;
|
||||
delete opaqueKey3;
|
||||
delete record;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetCachedNetDataByID(PRInt32 RecordID,
|
||||
nsINetDataCacheRecord* *aRecord)
|
||||
{
|
||||
nsOpaqueKey opaqueKey(NS_REINTERPRET_CAST(const char *, &RecordID),
|
||||
sizeof RecordID);
|
||||
*aRecord = (nsINetDataCacheRecord*)mHashTable->Get(&opaqueKey);
|
||||
if (*aRecord) {
|
||||
NS_ADDREF(*aRecord);
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
nsMemCache::Delete(nsMemCacheRecord* aRecord)
|
||||
{
|
||||
nsMemCacheRecord *removedRecord;
|
||||
|
||||
char *recordIDbytes = NS_REINTERPRET_CAST(char *, &aRecord->mRecordID);
|
||||
nsOpaqueKey opaqueRecordIDKey(recordIDbytes,
|
||||
sizeof aRecord->mRecordID);
|
||||
removedRecord = (nsMemCacheRecord*)mHashTable->Remove(&opaqueRecordIDKey);
|
||||
NS_ASSERTION(removedRecord == aRecord, "memory cache database inconsistent");
|
||||
|
||||
nsOpaqueKey opaqueKey(aRecord->mKey, aRecord->mKeyLength);
|
||||
removedRecord = (nsMemCacheRecord*)mHashTable->Remove(&opaqueKey);
|
||||
NS_ASSERTION(removedRecord == aRecord, "memory cache database inconsistent");
|
||||
|
||||
aRecord->Release();
|
||||
|
||||
mNumEntries--;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetEnabled(PRBool *aEnabled)
|
||||
{
|
||||
NS_ENSURE_ARG(aEnabled);
|
||||
*aEnabled = mEnabled;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::SetEnabled(PRBool aEnabled)
|
||||
{
|
||||
mEnabled = aEnabled;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetFlags(PRUint32 *aFlags)
|
||||
{
|
||||
NS_ENSURE_ARG(aFlags);
|
||||
*aFlags = MEMORY_CACHE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetNumEntries(PRUint32 *aNumEntries)
|
||||
{
|
||||
NS_ENSURE_ARG(aNumEntries);
|
||||
*aNumEntries = mNumEntries;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetMaxEntries(PRUint32 *aMaxEntries)
|
||||
{
|
||||
NS_ENSURE_ARG(aMaxEntries);
|
||||
*aMaxEntries = MEM_CACHE_MAX_ENTRIES;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static NS_METHOD
|
||||
HashEntryConverter(nsHashKey *aKey, void *aValue,
|
||||
void *unused, nsISupports **retval)
|
||||
{
|
||||
nsMemCacheRecord *record;
|
||||
nsOpaqueKey *opaqueKey;
|
||||
|
||||
record = (nsMemCacheRecord*)aValue;
|
||||
opaqueKey = (nsOpaqueKey*)aKey;
|
||||
|
||||
// Hash table keys that index cache entries by their record ID
|
||||
// shouldn't be enumerated.
|
||||
if ((opaqueKey->GetKeyLength() == sizeof(PRInt32))) {
|
||||
|
||||
#ifdef DEBUG
|
||||
PRInt32 recordID;
|
||||
record->GetRecordID(&recordID);
|
||||
NS_ASSERTION(*((PRInt32*)opaqueKey->GetKey()) == recordID,
|
||||
"Key has incorrect key length");
|
||||
#endif
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(record);
|
||||
*retval = NS_STATIC_CAST(nsISupports*, record);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::NewCacheEntryIterator(nsISimpleEnumerator* *aIterator)
|
||||
{
|
||||
nsCOMPtr<nsIEnumerator> iterator;
|
||||
|
||||
NS_ENSURE_ARG(aIterator);
|
||||
NS_NewHashtableEnumerator(mHashTable, HashEntryConverter,
|
||||
mHashTable, getter_AddRefs(iterator));
|
||||
return NS_NewAdapterEnumerator(aIterator, iterator);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetNextCache(nsINetDataCache* *aNextCache)
|
||||
{
|
||||
NS_ENSURE_ARG(aNextCache);
|
||||
*aNextCache = mNextCache;
|
||||
NS_ADDREF(*aNextCache);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::SetNextCache(nsINetDataCache* aNextCache)
|
||||
{
|
||||
mNextCache = aNextCache;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetStorageInUse(PRUint32 *aStorageInUse)
|
||||
{
|
||||
NS_ENSURE_ARG(aStorageInUse);
|
||||
|
||||
// Convert from bytes to KB
|
||||
*aStorageInUse = (mOccupancy >> 10);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::RemoveAll(void)
|
||||
{
|
||||
PRBool failed;
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> iterator;
|
||||
nsCOMPtr<nsISupports> recordSupports;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsresult rv;
|
||||
|
||||
failed = PR_FALSE;
|
||||
rv = NewCacheEntryIterator(getter_AddRefs(iterator));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
PRBool notDone;
|
||||
while (1) {
|
||||
rv = iterator->HasMoreElements(¬Done);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!notDone)
|
||||
break;
|
||||
|
||||
iterator->GetNext(getter_AddRefs(recordSupports));
|
||||
record = do_QueryInterface(recordSupports);
|
||||
recordSupports = 0;
|
||||
|
||||
PRUint32 bytesUsed;
|
||||
record->GetStoredContentLength(&bytesUsed);
|
||||
rv = record->Delete();
|
||||
if (NS_FAILED(rv)) {
|
||||
failed = PR_TRUE;
|
||||
continue;
|
||||
}
|
||||
mOccupancy -= bytesUsed;
|
||||
}
|
||||
|
||||
if (failed)
|
||||
return NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
}
|
||||
83
mozilla/netwerk/cache/memcache/nsMemCache.h
vendored
Normal file
83
mozilla/netwerk/cache/memcache/nsMemCache.h
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* nsMemCache is the implementation of an in-memory network-data
|
||||
* cache, used to cache the responses to network retrieval commands.
|
||||
* Each cache entry may contain both content, e.g. GIF image data, and
|
||||
* associated metadata, e.g. HTTP headers. Each entry is indexed by
|
||||
* two different keys: a record id number and an opaque key, which is
|
||||
* created by the cache manager by combining the URI with a "secondary
|
||||
* key", e.g. HTTP post data.
|
||||
*/
|
||||
|
||||
#ifndef _nsMemCache_h_
|
||||
#define _nsMemCache_h_
|
||||
|
||||
#include "nsINetDataCache.h"
|
||||
|
||||
// Maximum number of URIs that may be resident in the cache
|
||||
#define MEM_CACHE_MAX_ENTRIES 1000
|
||||
|
||||
#define MEM_CACHE_SEGMENT_SIZE (1 << 12)
|
||||
#define MEM_CACHE_MAX_ENTRY_SIZE (1 << 20)
|
||||
|
||||
class nsHashtable;
|
||||
class nsMemCacheRecord;
|
||||
|
||||
class nsMemCache : public nsINetDataCache
|
||||
{
|
||||
public:
|
||||
nsMemCache();
|
||||
virtual ~nsMemCache();
|
||||
nsresult Init();
|
||||
|
||||
// nsISupports methods
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsINetDataCache methods
|
||||
NS_DECL_NSINETDATACACHE
|
||||
|
||||
// Factory
|
||||
static NS_METHOD nsMemCacheConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||
void **aResult);
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mNumEntries;
|
||||
PRUint32 mOccupancy; // Memory used, in bytes
|
||||
PRBool mEnabled; // If false, bypass mem cache
|
||||
|
||||
nsINetDataCache* mNextCache;
|
||||
|
||||
// Mapping from either opaque key or record ID to nsMemCacheRecord
|
||||
nsHashtable* mHashTable;
|
||||
|
||||
// Used to assign record ID's
|
||||
static PRInt32 gRecordSerialNumber;
|
||||
|
||||
NS_METHOD Delete(nsMemCacheRecord* aRecord);
|
||||
|
||||
friend class nsMemCacheRecord;
|
||||
friend class nsMemCacheChannel;
|
||||
};
|
||||
|
||||
#endif // _nsMemCache_h_
|
||||
36
mozilla/netwerk/cache/memcache/nsMemCacheCID.h
vendored
Normal file
36
mozilla/netwerk/cache/memcache/nsMemCacheCID.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
// XPCOM Class ID for the network data in-memory cache
|
||||
|
||||
#ifndef nsMEMCACHECID_h__
|
||||
#define nsMEMCACHECID_h__
|
||||
|
||||
// {e4710560-7de2-11d3-90cb-0040056a906e}
|
||||
#define NS_MEM_CACHE_FACTORY_CID \
|
||||
{ \
|
||||
0xe4710560, \
|
||||
0x7de2, \
|
||||
0x11d3, \
|
||||
{0x90, 0xcb, 0x00, 0x40, 0x05, 0x6a, 0x90, 0x6e} \
|
||||
}
|
||||
|
||||
#endif // nsMEMCACHECID_h__
|
||||
462
mozilla/netwerk/cache/memcache/nsMemCacheChannel.cpp
vendored
Normal file
462
mozilla/netwerk/cache/memcache/nsMemCacheChannel.cpp
vendored
Normal file
@@ -0,0 +1,462 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nsMemCache.h"
|
||||
#include "nsMemCacheChannel.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIStorageStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsILoadGroup.h"
|
||||
|
||||
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||||
static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID);
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMemCacheChannel, NS_GET_IID(nsIChannel))
|
||||
|
||||
void
|
||||
nsMemCacheChannel::NotifyStorageInUse(PRInt32 aBytesUsed)
|
||||
{
|
||||
mRecord->mCache->mOccupancy += aBytesUsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class acts as an adaptor around a synchronous input stream to add async
|
||||
* read capabilities. It adds methods for initiating, suspending, resuming and
|
||||
* cancelling async reads.
|
||||
*/
|
||||
class AsyncReadStreamAdaptor : public nsIInputStream {
|
||||
public:
|
||||
AsyncReadStreamAdaptor(nsMemCacheChannel* aChannel, nsIInputStream *aSyncStream):
|
||||
mSyncStream(aSyncStream), mDataAvailCursor(0),
|
||||
mRemaining(0), mAvailable(0), mChannel(aChannel), mAborted(PR_FALSE), mSuspended(PR_FALSE)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF(mChannel);
|
||||
}
|
||||
|
||||
virtual ~AsyncReadStreamAdaptor() {
|
||||
mChannel->mAsyncReadStream = 0;
|
||||
NS_RELEASE(mChannel);
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsresult
|
||||
IsPending(PRBool* aIsPending) {
|
||||
*aIsPending = (mRemaining != 0) && !mAborted;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Cancel(void) {
|
||||
mAborted = PR_TRUE;
|
||||
return mStreamListener->OnStopRequest(mChannel, mContext, NS_BINDING_ABORTED, nsnull);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Suspend(void) { mSuspended = PR_TRUE; return NS_OK; }
|
||||
|
||||
nsresult
|
||||
Resume(void) {
|
||||
if (!mSuspended)
|
||||
return NS_ERROR_FAILURE;
|
||||
mSuspended = PR_FALSE;
|
||||
return NextListenerEvent();
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Available(PRUint32 *aNumBytes) { return mAvailable; }
|
||||
|
||||
NS_IMETHOD
|
||||
Read(char* aBuf, PRUint32 aCount, PRUint32 *aBytesRead) {
|
||||
if (mAborted)
|
||||
return NS_ERROR_ABORT;
|
||||
|
||||
*aBytesRead = 0;
|
||||
aCount = PR_MIN(aCount, mAvailable);
|
||||
nsresult rv = mSyncStream->Read(aBuf, aCount, aBytesRead);
|
||||
mAvailable -= *aBytesRead;
|
||||
|
||||
if (NS_FAILED(rv) && (rv != NS_BASE_STREAM_WOULD_BLOCK)) {
|
||||
Fail();
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!mSuspended && !mAvailable) {
|
||||
rv = NextListenerEvent();
|
||||
if (NS_FAILED(rv)) {
|
||||
Fail();
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Close() {
|
||||
nsresult rv = mSyncStream->Close();
|
||||
mSyncStream = 0;
|
||||
mContext = 0;
|
||||
mStreamListener = 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsISupports* aContext, nsIStreamListener* aListener) {
|
||||
|
||||
nsresult rv;
|
||||
nsIEventQueue *eventQ;
|
||||
|
||||
mContext = aContext;
|
||||
mStreamListener = aListener;
|
||||
mRemaining = aReadCount;
|
||||
|
||||
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueService, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQ);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = NS_NewAsyncStreamListener(aListener, eventQ,
|
||||
getter_AddRefs(mStreamListener));
|
||||
NS_RELEASE(eventQ);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mStreamListener->OnStartRequest(mChannel, aContext);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NextListenerEvent();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
nsresult
|
||||
Fail(void) {
|
||||
mAborted = PR_TRUE;
|
||||
return mStreamListener->OnStopRequest(mChannel, mContext, NS_BINDING_FAILED, nsnull);
|
||||
}
|
||||
|
||||
nsresult
|
||||
NextListenerEvent() {
|
||||
PRUint32 available;
|
||||
nsresult rv = mSyncStream->Available(&available);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
available -= mAvailable;
|
||||
available = PR_MIN(available, mRemaining);
|
||||
|
||||
if (available) {
|
||||
PRUint32 size = PR_MIN(available, MEM_CACHE_SEGMENT_SIZE);
|
||||
rv = mStreamListener->OnDataAvailable(mChannel, mContext, this,
|
||||
mDataAvailCursor, size);
|
||||
mDataAvailCursor += size;
|
||||
mRemaining -= size;
|
||||
mAvailable += size;
|
||||
return rv;
|
||||
} else {
|
||||
rv = mStreamListener->OnStopRequest(mChannel, mContext, NS_OK, nsnull);
|
||||
AsyncReadStreamAdaptor* thisAlias = this;
|
||||
NS_RELEASE(thisAlias);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsISupports> mContext; // Opaque context passed to AsyncRead()
|
||||
nsCOMPtr<nsIStreamListener> mStreamListener; // Stream listener that has been proxied
|
||||
nsCOMPtr<nsIInputStream> mSyncStream; // Underlying synchronous stream that is
|
||||
// being converted to an async stream
|
||||
PRUint32 mDataAvailCursor;
|
||||
PRUint32 mRemaining; // Size of AsyncRead request less bytes for
|
||||
// consumer OnDataAvailable's that were fired
|
||||
PRUint32 mAvailable; // Number of bytes for which OnDataAvailable fired
|
||||
nsMemCacheChannel* mChannel; // Associated memory cache channel, strong link
|
||||
// but can not use nsCOMPtr
|
||||
PRBool mAborted; // Abort() has been called
|
||||
PRBool mSuspended; // Suspend() has been called
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(AsyncReadStreamAdaptor, NS_GET_IID(nsIInputStream))
|
||||
|
||||
// The only purpose of this output stream wrapper is to adjust the cache's
|
||||
// overall occupancy as new data flows into the cache entry.
|
||||
class MemCacheWriteStreamWrapper : public nsIOutputStream {
|
||||
public:
|
||||
MemCacheWriteStreamWrapper(nsMemCacheChannel* aChannel, nsIOutputStream *aBaseStream):
|
||||
mBaseStream(aBaseStream), mChannel(aChannel)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF(mChannel);
|
||||
}
|
||||
|
||||
virtual ~MemCacheWriteStreamWrapper() { NS_RELEASE(mChannel); };
|
||||
|
||||
static nsresult
|
||||
Create(nsMemCacheChannel* aChannel, nsIOutputStream *aBaseStream, nsIOutputStream* *aWrapper) {
|
||||
MemCacheWriteStreamWrapper *wrapper =
|
||||
new MemCacheWriteStreamWrapper(aChannel, aBaseStream);
|
||||
if (!wrapper) return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(wrapper);
|
||||
*aWrapper = wrapper;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD
|
||||
Write(const char *aBuffer, PRUint32 aCount, PRUint32 *aNumWritten) {
|
||||
*aNumWritten = 0;
|
||||
nsresult rv = mBaseStream->Write(aBuffer, aCount, aNumWritten);
|
||||
mChannel->NotifyStorageInUse(*aNumWritten);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Flush() { return mBaseStream->Flush(); }
|
||||
|
||||
NS_IMETHOD
|
||||
Close() { return mBaseStream->Close(); }
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIOutputStream> mBaseStream;
|
||||
nsMemCacheChannel* mChannel;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(MemCacheWriteStreamWrapper, NS_GET_IID(nsIOutputStream))
|
||||
|
||||
nsMemCacheChannel::nsMemCacheChannel(nsMemCacheRecord *aRecord, nsILoadGroup *aLoadGroup)
|
||||
: mRecord(aRecord)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mRecord->mNumChannels++;
|
||||
}
|
||||
|
||||
nsMemCacheChannel::~nsMemCacheChannel()
|
||||
{
|
||||
mRecord->mNumChannels--;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::IsPending(PRBool* aIsPending)
|
||||
{
|
||||
*aIsPending = PR_FALSE;
|
||||
if (!mAsyncReadStream)
|
||||
return NS_OK;
|
||||
return mAsyncReadStream->IsPending(aIsPending);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::Cancel(void)
|
||||
{
|
||||
if (!mAsyncReadStream)
|
||||
return NS_ERROR_FAILURE;
|
||||
return mAsyncReadStream->Cancel();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::Suspend(void)
|
||||
{
|
||||
if (!mAsyncReadStream)
|
||||
return NS_ERROR_FAILURE;
|
||||
return mAsyncReadStream->Suspend();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::Resume(void)
|
||||
{
|
||||
if (!mAsyncReadStream)
|
||||
return NS_ERROR_FAILURE;
|
||||
return mAsyncReadStream->Resume();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetOriginalURI(nsIURI * *aURI)
|
||||
{
|
||||
// Not required
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetURI(nsIURI * *aURI)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::OpenInputStream(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsIInputStream* *aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_ENSURE_ARG(aResult);
|
||||
if (mInputStream)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
rv = mRecord->mStorageStream->NewInputStream(aStartPosition, getter_AddRefs(mInputStream));
|
||||
*aResult = mInputStream;
|
||||
NS_ADDREF(*aResult);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::OpenOutputStream(PRUint32 startPosition, nsIOutputStream* *aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_ENSURE_ARG(aResult);
|
||||
|
||||
nsCOMPtr<nsIOutputStream> outputStream;
|
||||
|
||||
PRUint32 oldLength;
|
||||
mRecord->mStorageStream->GetLength(&oldLength);
|
||||
rv = mRecord->mStorageStream->GetOutputStream(startPosition, getter_AddRefs(outputStream));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (startPosition < oldLength)
|
||||
NotifyStorageInUse(startPosition - oldLength);
|
||||
|
||||
return MemCacheWriteStreamWrapper::Create(this, outputStream, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::AsyncOpen(nsIStreamObserver *observer, nsISupports *ctxt)
|
||||
{
|
||||
// Not required
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsISupports *aContext, nsIStreamListener *aListener)
|
||||
{
|
||||
nsCOMPtr<nsIInputStream> inputStream;
|
||||
nsresult rv = OpenInputStream(aStartPosition, aReadCount, getter_AddRefs(inputStream));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
AsyncReadStreamAdaptor *asyncReadStreamAdaptor;
|
||||
asyncReadStreamAdaptor = new AsyncReadStreamAdaptor(this, inputStream);
|
||||
if (!asyncReadStreamAdaptor)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(asyncReadStreamAdaptor);
|
||||
mAsyncReadStream = asyncReadStreamAdaptor;
|
||||
|
||||
rv = asyncReadStreamAdaptor->AsyncRead(aStartPosition, aReadCount, aContext, aListener);
|
||||
if (NS_FAILED(rv))
|
||||
delete asyncReadStreamAdaptor;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::AsyncWrite(nsIInputStream *fromStream, PRUint32 startPosition,
|
||||
PRInt32 writeCount, nsISupports *ctxt,
|
||||
nsIStreamObserver *observer)
|
||||
{
|
||||
// Not required to be implemented
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetContentType(char* *aContentType)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetContentLength(PRInt32 *aContentLength)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetOwner(nsISupports* *aOwner)
|
||||
{
|
||||
*aOwner = mOwner.get();
|
||||
NS_IF_ADDREF(*aOwner);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::SetOwner(nsISupports* aOwner)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
mOwner = aOwner;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
61
mozilla/netwerk/cache/memcache/nsMemCacheChannel.h
vendored
Normal file
61
mozilla/netwerk/cache/memcache/nsMemCacheChannel.h
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _nsMemCacheChannel_h_
|
||||
#define _nsMemCacheChannel_h_
|
||||
|
||||
#include "nsMemCacheRecord.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
|
||||
class AsyncReadStreamAdaptor;
|
||||
|
||||
class nsMemCacheChannel : public nsIChannel
|
||||
{
|
||||
public:
|
||||
// Constructors and Destructor
|
||||
nsMemCacheChannel(nsMemCacheRecord *aRecord, nsILoadGroup *aLoadGroup);
|
||||
virtual ~nsMemCacheChannel();
|
||||
|
||||
// Declare nsISupports methods
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// Declare nsIRequest methods
|
||||
NS_DECL_NSIREQUEST
|
||||
|
||||
// Declare nsIChannel methods
|
||||
NS_DECL_NSICHANNEL
|
||||
|
||||
protected:
|
||||
void NotifyStorageInUse(PRInt32 aBytesUsed);
|
||||
|
||||
nsCOMPtr<nsMemCacheRecord> mRecord;
|
||||
nsCOMPtr<nsIInputStream> mInputStream;
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
AsyncReadStreamAdaptor* mAsyncReadStream; // non-owning pointer
|
||||
|
||||
friend class MemCacheWriteStreamWrapper;
|
||||
friend class AsyncReadStreamAdaptor;
|
||||
};
|
||||
|
||||
#endif // _nsMemCacheChannel_h_
|
||||
164
mozilla/netwerk/cache/memcache/nsMemCacheRecord.cpp
vendored
Normal file
164
mozilla/netwerk/cache/memcache/nsMemCacheRecord.cpp
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nsMemCache.h"
|
||||
#include "nsMemCacheRecord.h"
|
||||
#include "nsMemCacheChannel.h"
|
||||
#include "nsIAllocator.h"
|
||||
#include "nsStorageStream.h"
|
||||
|
||||
static NS_DEFINE_IID(kINetDataCacheRecord, NS_INETDATACACHERECORD_IID);
|
||||
|
||||
nsMemCacheRecord::nsMemCacheRecord()
|
||||
: mKey(0), mKeyLength(0), mMetaData(0), mMetaDataLength(0), mNumChannels(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsMemCacheRecord::~nsMemCacheRecord()
|
||||
{
|
||||
if (mMetaData)
|
||||
delete[] mMetaData;
|
||||
if (mKey)
|
||||
delete[] mKey;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMemCacheRecord, NS_GET_IID(nsINetDataCacheRecord))
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::GetKey(PRUint32 *aLength, char **aResult)
|
||||
{
|
||||
NS_ENSURE_ARG(aResult);
|
||||
*aResult = (char *)nsAllocator::Alloc(mKeyLength);
|
||||
if (!*aResult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
memcpy(*aResult, mKey, mKeyLength);
|
||||
*aLength = mKeyLength;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMemCacheRecord::Init(const char *aKey, PRUint32 aKeyLength,
|
||||
PRUint32 aRecordID, nsMemCache *aCache)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
NS_ASSERTION(!mKey, "Memory cache record key set multiple times");
|
||||
|
||||
rv = NS_NewStorageStream(MEM_CACHE_SEGMENT_SIZE, MEM_CACHE_MAX_ENTRY_SIZE,
|
||||
getter_AddRefs(mStorageStream));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mKey = new char[aKeyLength];
|
||||
if (!mKey)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
memcpy(mKey, aKey, aKeyLength);
|
||||
mKeyLength = aKeyLength;
|
||||
mRecordID = aRecordID;
|
||||
mCache = aCache;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::GetRecordID(PRInt32 *aRecordID)
|
||||
{
|
||||
NS_ENSURE_ARG(aRecordID);
|
||||
*aRecordID = mRecordID;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::GetMetaData(PRUint32 *aLength, char **aResult)
|
||||
{
|
||||
NS_ENSURE_ARG(aResult);
|
||||
|
||||
*aResult = 0;
|
||||
if (mMetaDataLength) {
|
||||
*aResult = (char*)nsAllocator::Alloc(mMetaDataLength);
|
||||
if (!*aResult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
memcpy(*aResult, mMetaData, mMetaDataLength);
|
||||
}
|
||||
*aLength = mMetaDataLength;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::SetMetaData(PRUint32 aLength, const char *aData)
|
||||
{
|
||||
if (mMetaData)
|
||||
delete[] mMetaData;
|
||||
mMetaData = new char[aLength];
|
||||
if (!mMetaData)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
memcpy(mMetaData, aData, aLength);
|
||||
mMetaDataLength = aLength;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::GetStoredContentLength(PRUint32 *aStoredContentLength)
|
||||
{
|
||||
NS_ENSURE_ARG(aStoredContentLength);
|
||||
return mStorageStream->GetLength(aStoredContentLength);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::SetStoredContentLength(PRUint32 aStoredContentLength)
|
||||
{
|
||||
PRUint32 before, after;
|
||||
mStorageStream->GetLength(&before);
|
||||
nsresult rv = mStorageStream->SetLength(aStoredContentLength);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
mStorageStream->GetLength(&after);
|
||||
mCache->mOccupancy -= (before - after);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::Delete(void)
|
||||
{
|
||||
if (mNumChannels)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
return mCache->Delete(this);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::GetFilename(nsIFileSpec* *aFilename)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::NewChannel(nsILoadGroup *aLoadGroup, nsIChannel* *aResult)
|
||||
{
|
||||
NS_ENSURE_ARG(aResult);
|
||||
|
||||
nsMemCacheChannel* channel = new nsMemCacheChannel(this, aLoadGroup);
|
||||
if (!channel)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(channel);
|
||||
*aResult = NS_STATIC_CAST(nsIChannel*, channel);
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
65
mozilla/netwerk/cache/memcache/nsMemCacheRecord.h
vendored
Normal file
65
mozilla/netwerk/cache/memcache/nsMemCacheRecord.h
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _nsMemCacheRecord_h_
|
||||
#define _nsMemCacheRecord_h_
|
||||
|
||||
#include "nsINetDataCacheRecord.h"
|
||||
#include "nsIStorageStream.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsMemCache;
|
||||
|
||||
class nsMemCacheRecord : public nsINetDataCacheRecord
|
||||
{
|
||||
|
||||
public:
|
||||
// Declare interface methods
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSINETDATACACHERECORD
|
||||
|
||||
protected:
|
||||
// Constructors and Destructor
|
||||
nsMemCacheRecord();
|
||||
virtual ~nsMemCacheRecord();
|
||||
|
||||
nsresult Init(const char *aKey, PRUint32 aKeyLength,
|
||||
PRUint32 aRecordID, nsMemCache *aCache);
|
||||
|
||||
char* mKey; // opaque database key for this record
|
||||
PRUint32 mKeyLength; // length, in bytes, of mKey
|
||||
|
||||
PRInt32 mRecordID; // An alternate key for this record
|
||||
|
||||
char* mMetaData; // opaque URI metadata
|
||||
PRUint32 mMetaDataLength; // length, in bytes, of mMetaData
|
||||
|
||||
nsMemCache* mCache; // weak pointer to the cache database
|
||||
// that this record inhabits
|
||||
|
||||
nsCOMPtr<nsIStorageStream> mStorageStream;
|
||||
PRUint32 mNumChannels; // Count un-Release'ed nsIChannels
|
||||
|
||||
friend class nsMemCache;
|
||||
friend class nsMemCacheChannel;
|
||||
};
|
||||
|
||||
#endif // _nsMemCacheRecord_h_
|
||||
55
mozilla/netwerk/cache/mgr/Makefile.in
vendored
Normal file
55
mozilla/netwerk/cache/mgr/Makefile.in
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
#
|
||||
# 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 = nkcache
|
||||
LIBRARY_NAME = nkcachemgr_s
|
||||
|
||||
REQUIRES = nspr
|
||||
|
||||
EXPORTS = \
|
||||
nsCacheManager.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
nsCacheManager.cpp \
|
||||
nsCachedNetData.cpp \
|
||||
nsReplacementPolicy.cpp \
|
||||
nsCacheEntryChannel.cpp \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = -I$(srcdir)/../public -I$(srcdir)/../include
|
||||
|
||||
EXTRA_LIBS = $(NSPR_LIBS)
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a
|
||||
# static lib.
|
||||
override NO_SHARED_LIB=1
|
||||
override NO_STATIC_LIB=
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
45
mozilla/netwerk/cache/mgr/Makefile.win
vendored
Executable file
45
mozilla/netwerk/cache/mgr/Makefile.win
vendored
Executable file
@@ -0,0 +1,45 @@
|
||||
#!gmake
|
||||
#
|
||||
# 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=..\..\..
|
||||
|
||||
include <$(DEPTH)/config/config.mak>
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
LIBRARY_NAME = nkcachemgr_s
|
||||
|
||||
CPP_OBJS = \
|
||||
.\$(OBJDIR)\nsCacheManager.obj \
|
||||
.\$(OBJDIR)\nsCachedNetData.obj \
|
||||
.\$(OBJDIR)\nsReplacementPolicy.obj \
|
||||
.\$(OBJDIR)\nsCacheEntryChannel.obj \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
install:: $(LIBRARY)
|
||||
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
|
||||
|
||||
clobber::
|
||||
rm -rf $(OBJDIR)
|
||||
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib
|
||||
|
||||
261
mozilla/netwerk/cache/mgr/nsCacheEntryChannel.cpp
vendored
Normal file
261
mozilla/netwerk/cache/mgr/nsCacheEntryChannel.cpp
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
#include "nsCacheManager.h"
|
||||
#include "nsCacheEntryChannel.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIStreamListener.h"
|
||||
|
||||
nsCacheEntryChannel::nsCacheEntryChannel(nsCachedNetData* aCacheEntry, nsIChannel* aChannel,
|
||||
nsILoadGroup* aLoadGroup):
|
||||
nsChannelProxy(aChannel), mCacheEntry(aCacheEntry), mLoadGroup(aLoadGroup), mLoadAttributes(0)
|
||||
{
|
||||
NS_ASSERTION(aCacheEntry->mChannelCount < 0xFF, "Overflowed channel counter");
|
||||
mCacheEntry->mChannelCount++;
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsCacheEntryChannel::~nsCacheEntryChannel()
|
||||
{
|
||||
mCacheEntry->mChannelCount--;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsCacheEntryChannel, nsISupports, nsIChannel, nsIRequest)
|
||||
|
||||
// A proxy for nsIOutputStream
|
||||
class CacheOutputStream : public nsIOutputStream {
|
||||
|
||||
public:
|
||||
CacheOutputStream(nsIOutputStream *aOutputStream, nsCachedNetData *aCacheEntry):
|
||||
mOutputStream(aOutputStream), mCacheEntry(aCacheEntry), mStartTime(PR_Now())
|
||||
{ NS_INIT_REFCNT(); }
|
||||
|
||||
virtual ~CacheOutputStream() {
|
||||
mCacheEntry->NoteDownloadTime(mStartTime, PR_Now());
|
||||
mCacheEntry->ClearFlag(nsCachedNetData::UPDATE_IN_PROGRESS);
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD Close() {
|
||||
return mOutputStream->Close();
|
||||
}
|
||||
|
||||
NS_IMETHOD Flush() { return mOutputStream->Flush(); }
|
||||
|
||||
NS_IMETHOD
|
||||
Write(const char *aBuf, PRUint32 aCount, PRUint32 *aActualBytes) {
|
||||
nsresult rv;
|
||||
|
||||
*aActualBytes = 0;
|
||||
rv = mOutputStream->Write(aBuf, aCount, aActualBytes);
|
||||
mCacheEntry->mLogicalLength += *aActualBytes;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsCacheManager::LimitCacheSize();
|
||||
return rv;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIOutputStream> mOutputStream;
|
||||
nsCOMPtr<nsCachedNetData> mCacheEntry;
|
||||
|
||||
// Time at which stream was opened
|
||||
PRTime mStartTime;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(CacheOutputStream, NS_GET_IID(nsIOutputStream))
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::OpenOutputStream(PRUint32 aStartPosition, nsIOutputStream* *aOutputStream)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIOutputStream> baseOutputStream;
|
||||
|
||||
rv = mChannel->OpenOutputStream(aStartPosition, getter_AddRefs(baseOutputStream));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mCacheEntry->NoteUpdate();
|
||||
mCacheEntry->NoteAccess();
|
||||
mCacheEntry->mLogicalLength = aStartPosition;
|
||||
|
||||
*aOutputStream = new CacheOutputStream(baseOutputStream, mCacheEntry);
|
||||
if (!*aOutputStream)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(*aOutputStream);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::OpenInputStream(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsIInputStream* *aInputStream)
|
||||
{
|
||||
mCacheEntry->NoteAccess();
|
||||
return mChannel->OpenInputStream(aStartPosition, aReadCount, aInputStream);
|
||||
}
|
||||
|
||||
class CacheManagerStreamListener: public nsIStreamListener {
|
||||
|
||||
public:
|
||||
|
||||
CacheManagerStreamListener(nsIStreamListener *aListener,
|
||||
nsILoadGroup *aLoadGroup, nsIChannel *aChannel):
|
||||
mListener(aListener), mLoadGroup(aLoadGroup), mChannel(aChannel)
|
||||
{ NS_INIT_REFCNT(); }
|
||||
|
||||
virtual ~CacheManagerStreamListener() {}
|
||||
|
||||
private:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD
|
||||
OnDataAvailable(nsIChannel *channel, nsISupports *aContext,
|
||||
nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count) {
|
||||
return mListener->OnDataAvailable(mChannel, aContext, inStr, sourceOffset, count);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnStartRequest(nsIChannel *channel, nsISupports *aContext) {
|
||||
if (mLoadGroup)
|
||||
mLoadGroup->AddChannel(mChannel, aContext);
|
||||
return mListener->OnStartRequest(mChannel, aContext);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnStopRequest(nsIChannel *channel, nsISupports *aContext,
|
||||
nsresult status, const PRUnichar *errorMsg) {
|
||||
nsresult rv;
|
||||
rv = mListener->OnStopRequest(mChannel, aContext, status, errorMsg);
|
||||
if (mLoadGroup)
|
||||
mLoadGroup->RemoveChannel(mChannel, aContext, status, errorMsg);
|
||||
return rv;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
nsCOMPtr<nsIStreamListener> mListener;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS2(CacheManagerStreamListener, nsIStreamListener, nsIStreamObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsISupports *aContext, nsIStreamListener *aListener)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
mCacheEntry->NoteAccess();
|
||||
|
||||
nsCOMPtr<nsIStreamListener> headListener;
|
||||
if (mLoadGroup) {
|
||||
mLoadGroup->GetDefaultLoadAttributes(&mLoadAttributes);
|
||||
|
||||
// Create a load group "proxy" listener...
|
||||
nsCOMPtr<nsILoadGroupListenerFactory> factory;
|
||||
rv = mLoadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
|
||||
if (NS_SUCCEEDED(rv) && factory) {
|
||||
rv = factory->CreateLoadGroupListener(aListener,
|
||||
getter_AddRefs(headListener));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
} else {
|
||||
headListener = aListener;
|
||||
}
|
||||
|
||||
CacheManagerStreamListener* cacheManagerStreamListener;
|
||||
nsIChannel *channelForListener;
|
||||
|
||||
channelForListener = mProxyChannel ? mProxyChannel.get() : NS_STATIC_CAST(nsIChannel*, this);
|
||||
cacheManagerStreamListener =
|
||||
new CacheManagerStreamListener(headListener, mLoadGroup, channelForListener);
|
||||
if (!cacheManagerStreamListener) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(cacheManagerStreamListener);
|
||||
rv = mChannel->AsyncRead(aStartPosition, aReadCount, aContext,
|
||||
cacheManagerStreamListener);
|
||||
NS_RELEASE(cacheManagerStreamListener);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// No async writes allowed to the cache yet
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::AsyncWrite(nsIInputStream *aFromStream, PRUint32 aStartPosition,
|
||||
PRInt32 aWriteCount, nsISupports *aContext,
|
||||
nsIStreamObserver *aObserver)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
|
||||
{
|
||||
*aLoadGroup = mLoadGroup;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
|
||||
{
|
||||
*aLoadAttributes = mLoadAttributes;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
|
||||
{
|
||||
mLoadAttributes = aLoadAttributes;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::GetURI(nsIURI * *aURI)
|
||||
{
|
||||
char* spec;
|
||||
nsresult rv;
|
||||
|
||||
rv = mCacheEntry->GetUriSpec(&spec);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = serv->NewURI(spec, 0, aURI);
|
||||
nsAllocator::Free(spec);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::GetOriginalURI(nsIURI * *aURI)
|
||||
{
|
||||
// FIXME - should return original URI passed into NewChannel() ?
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
82
mozilla/netwerk/cache/mgr/nsCacheEntryChannel.h
vendored
Normal file
82
mozilla/netwerk/cache/mgr/nsCacheEntryChannel.h
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
#ifndef _nsCacheEntryChannel_h_
|
||||
#define _nsCacheEntryChannel_h_
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsCachedNetData.h"
|
||||
#include "nsILoadGroup.h"
|
||||
|
||||
class nsIStreamListener;
|
||||
|
||||
// A proxy for an nsIChannel, useful when only a few nsIChannel
|
||||
// methods must be overridden
|
||||
class nsChannelProxy : public nsIChannel {
|
||||
|
||||
public:
|
||||
NS_FORWARD_NSICHANNEL(mChannel->)
|
||||
NS_FORWARD_NSIREQUEST(mChannel->)
|
||||
|
||||
protected:
|
||||
nsChannelProxy(nsIChannel* aChannel):mChannel(aChannel) {};
|
||||
virtual ~nsChannelProxy() {};
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
};
|
||||
|
||||
// Override several nsIChannel methods so that they interact with the cache manager
|
||||
class nsCacheEntryChannel : public nsChannelProxy {
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD OpenOutputStream(PRUint32 aStartPosition, nsIOutputStream* *aOutputStream);
|
||||
NS_IMETHOD OpenInputStream(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsIInputStream* *aInputStream);
|
||||
NS_IMETHOD AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsISupports *aContext, nsIStreamListener *aListener);
|
||||
NS_IMETHOD AsyncWrite(nsIInputStream *aFromStream, PRUint32 aStartPosition,
|
||||
PRInt32 aWriteCount, nsISupports *aContext,
|
||||
nsIStreamObserver *aObserver);
|
||||
NS_IMETHOD GetLoadAttributes(nsLoadFlags *aLoadAttributes);
|
||||
NS_IMETHOD SetLoadAttributes(nsLoadFlags aLoadAttributes);
|
||||
NS_IMETHOD GetLoadGroup(nsILoadGroup* *aLoadGroup);
|
||||
NS_IMETHOD GetURI(nsIURI * *aURI);
|
||||
NS_IMETHOD GetOriginalURI(nsIURI * *aURI);
|
||||
|
||||
protected:
|
||||
nsCacheEntryChannel(nsCachedNetData* aCacheEntry, nsIChannel* aChannel, nsILoadGroup* aLoadGroup);
|
||||
virtual ~nsCacheEntryChannel();
|
||||
|
||||
friend class nsCachedNetData;
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsCachedNetData> mCacheEntry;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
nsCOMPtr<nsIChannel> mProxyChannel;
|
||||
nsLoadFlags mLoadAttributes;
|
||||
};
|
||||
|
||||
#endif // _nsCacheEntryChannel_h_
|
||||
497
mozilla/netwerk/cache/mgr/nsCacheManager.cpp
vendored
Normal file
497
mozilla/netwerk/cache/mgr/nsCacheManager.cpp
vendored
Normal file
@@ -0,0 +1,497 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsCacheManager.h"
|
||||
#include "nsCachedNetData.h"
|
||||
#include "nsReplacementPolicy.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsINetDataDiskCache.h"
|
||||
|
||||
// Limit the number of entries in the cache to conserve memory space
|
||||
// in the nsReplacementPolicy code
|
||||
#define MAX_MEM_CACHE_ENTRIES 800
|
||||
#define MAX_DISK_CACHE_ENTRIES 3200
|
||||
|
||||
// Cache capacities in MB, overridable via APIs
|
||||
#define DEFAULT_MEMORY_CACHE_CAPACITY 1024
|
||||
#define DEFAULT_DISK_CACHE_CAPACITY 10000
|
||||
|
||||
#define CACHE_HIGH_WATER_MARK(capacity) ((PRUint32)(0.98 * (capacity)))
|
||||
#define CACHE_LOW_WATER_MARK(capacity) ((PRUint32)(0.97 * (capacity)))
|
||||
|
||||
nsCacheManager* gCacheManager = 0;
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsCacheManager, NS_GET_IID(nsINetDataCacheManager))
|
||||
|
||||
nsCacheManager::nsCacheManager()
|
||||
: mActiveCacheRecords(0),
|
||||
mDiskCacheCapacity(DEFAULT_DISK_CACHE_CAPACITY),
|
||||
mMemCacheCapacity(DEFAULT_MEMORY_CACHE_CAPACITY)
|
||||
{
|
||||
NS_ASSERTION(!gCacheManager, "Multiple cache managers created");
|
||||
gCacheManager = this;
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsCacheManager::~nsCacheManager()
|
||||
{
|
||||
gCacheManager = 0;
|
||||
delete mActiveCacheRecords;
|
||||
delete mMemSpaceManager;
|
||||
delete mDiskSpaceManager;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCacheManager::Init()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
mActiveCacheRecords = new nsHashtable(64);
|
||||
if (!mActiveCacheRecords)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// Instantiate the memory cache component
|
||||
rv = nsComponentManager::CreateInstance(NS_NETWORK_MEMORY_CACHE_PROGID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsINetDataCache),
|
||||
getter_AddRefs(mMemCache));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = nsComponentManager::CreateInstance(NS_NETWORK_FLAT_CACHE_PROGID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsINetDataCache),
|
||||
|
||||
getter_AddRefs(mFlatCache));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
// For now, we don't require a flat cache module to be present
|
||||
if (rv != NS_ERROR_FACTORY_NOT_REGISTERED)
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef FILE_CACHE_IS_READY
|
||||
// Instantiate the file cache component
|
||||
rv = nsComponentManager::CreateInstance(NS_NETWORK_FILE_CACHE_PROGID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsINetDataCache),
|
||||
getter_AddRefs(mFileCache));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("No disk cache present");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set up linked list of caches in search order
|
||||
mCacheSearchChain = mMemCache;
|
||||
if (mFlatCache) {
|
||||
mMemCache->SetNextCache(mFlatCache);
|
||||
mFlatCache->SetNextCache(mFileCache);
|
||||
} else {
|
||||
mMemCache->SetNextCache(mFileCache);
|
||||
}
|
||||
|
||||
// TODO - Load any extension caches here
|
||||
|
||||
// Initialize replacement policy for memory cache module
|
||||
mMemSpaceManager = new nsReplacementPolicy;
|
||||
if (!mMemSpaceManager)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
rv = mMemSpaceManager->Init(MAX_MEM_CACHE_ENTRIES);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = mMemSpaceManager->AddCache(mMemCache);
|
||||
|
||||
// Initialize replacement policy for disk cache modules (file
|
||||
// cache and flat cache)
|
||||
mDiskSpaceManager = new nsReplacementPolicy;
|
||||
if (!mDiskSpaceManager)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
rv = mDiskSpaceManager->Init(MAX_DISK_CACHE_ENTRIES);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (mFileCache) {
|
||||
rv = mDiskSpaceManager->AddCache(mFileCache);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
if (mFlatCache) {
|
||||
rv = mDiskSpaceManager->AddCache(mFlatCache);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::GetCachedNetData(const char *aUriSpec, const char *aSecondaryKey,
|
||||
PRUint32 aSecondaryKeyLength,
|
||||
PRUint32 aFlags, nsICachedNetData* *aResult)
|
||||
{
|
||||
nsCachedNetData *cachedData;
|
||||
nsresult rv;
|
||||
nsINetDataCache *cache;
|
||||
nsReplacementPolicy *spaceManager;
|
||||
|
||||
if (aFlags & CACHE_AS_FILE) {
|
||||
cache = mFileCache;
|
||||
spaceManager = mDiskSpaceManager;
|
||||
|
||||
// Ensure that cache is initialized
|
||||
if (mDiskCacheCapacity == (PRUint32)-1)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
} else if ((aFlags & BYPASS_PERSISTENT_CACHE) ||
|
||||
(!mFileCache && !mFlatCache) || !mDiskCacheCapacity) {
|
||||
cache = mMemCache;
|
||||
spaceManager = mMemSpaceManager;
|
||||
} else {
|
||||
cache = mFlatCache ? mFlatCache : mFileCache;
|
||||
spaceManager = mDiskSpaceManager;
|
||||
}
|
||||
|
||||
// Construct the cache key by appending the secondary key to the URI spec
|
||||
nsCAutoString cacheKey(aUriSpec);
|
||||
|
||||
// Insert NUL at end of URI spec
|
||||
cacheKey += '\0';
|
||||
if (aSecondaryKey)
|
||||
cacheKey.Append(aSecondaryKey, aSecondaryKeyLength);
|
||||
|
||||
nsStringKey key(cacheKey);
|
||||
cachedData = (nsCachedNetData*)mActiveCacheRecords->Get(&key);
|
||||
|
||||
// There is no existing instance of nsCachedNetData for this URL.
|
||||
// Make one from the corresponding record in the cache module.
|
||||
if (cachedData) {
|
||||
NS_ASSERTION(cache == cachedData->mCache,
|
||||
"Cannot yet handle simultaneously active requests for the "
|
||||
"same URL using different caches");
|
||||
NS_ADDREF(cachedData);
|
||||
} else {
|
||||
rv = spaceManager->GetCachedNetData(cacheKey.GetBuffer(), cacheKey.Length(),
|
||||
cache, &cachedData);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mActiveCacheRecords->Put(&key, cachedData);
|
||||
}
|
||||
|
||||
*aResult = cachedData;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Remove this cache entry from the list of active ones
|
||||
nsresult
|
||||
nsCacheManager::NoteDormant(nsCachedNetData* aEntry)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 keyLength;
|
||||
char* key;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCachedNetData* deletedEntry;
|
||||
|
||||
rv = aEntry->GetRecord(getter_AddRefs(record));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = record->GetKey(&keyLength, &key);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsStringKey hashTableKey(nsCString(key, keyLength));
|
||||
deletedEntry = (nsCachedNetData*)gCacheManager->mActiveCacheRecords->Remove(&hashTableKey);
|
||||
// NS_ASSERTION(deletedEntry == aEntry, "Hash table inconsistency");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::Contains(const char *aUriSpec, const char *aSecondaryKey,
|
||||
PRUint32 aSecondaryKeyLength,
|
||||
PRUint32 aFlags, PRBool *aResult)
|
||||
{
|
||||
nsINetDataCache *cache;
|
||||
nsReplacementPolicy *spaceManager;
|
||||
nsCachedNetData *cachedData;
|
||||
|
||||
if (aFlags & CACHE_AS_FILE) {
|
||||
cache = mFileCache;
|
||||
spaceManager = mDiskSpaceManager;
|
||||
} else if ((aFlags & BYPASS_PERSISTENT_CACHE) ||
|
||||
(!mFileCache && !mFlatCache) || !mDiskCacheCapacity) {
|
||||
cache = mMemCache;
|
||||
spaceManager = mMemSpaceManager;
|
||||
} else {
|
||||
cache = mFlatCache ? mFlatCache : mFileCache;
|
||||
spaceManager = mDiskSpaceManager;
|
||||
}
|
||||
|
||||
// Construct the cache key by appending the secondary key to the URI spec
|
||||
nsCAutoString cacheKey(aUriSpec);
|
||||
|
||||
// Insert NUL between URI spec and secondary key
|
||||
cacheKey += '\0';
|
||||
cacheKey.Append(aSecondaryKey, aSecondaryKeyLength);
|
||||
|
||||
// Locate the record using (URI + secondary key)
|
||||
nsStringKey key(cacheKey);
|
||||
cachedData = (nsCachedNetData*)mActiveCacheRecords->Get(&key);
|
||||
|
||||
if (cachedData && (cache == cachedData->mCache)) {
|
||||
*aResult = PR_TRUE;
|
||||
return NS_OK;
|
||||
} else {
|
||||
// No active cache entry, see if there is a dormant one
|
||||
return cache->Contains(cacheKey.GetBuffer(), cacheKey.Length(), aResult);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::GetNumEntries(PRUint32 *aNumEntries)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISimpleEnumerator> iterator;
|
||||
nsCOMPtr<nsISupports> cacheSupports;
|
||||
nsCOMPtr<nsINetDataCache> cache;
|
||||
|
||||
PRUint32 totalEntries = 0;
|
||||
|
||||
rv = NewCacheModuleIterator(getter_AddRefs(iterator));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
while (1) {
|
||||
PRBool notDone;
|
||||
rv = iterator->HasMoreElements(¬Done);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!notDone)
|
||||
break;
|
||||
|
||||
iterator->GetNext(getter_AddRefs(cacheSupports));
|
||||
cache = do_QueryInterface(cacheSupports);
|
||||
|
||||
PRUint32 numEntries;
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
totalEntries += numEntries;
|
||||
}
|
||||
|
||||
*aNumEntries = totalEntries;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::NewCacheEntryIterator(nsISimpleEnumerator* *aResult)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
class CacheEnumerator : public nsISimpleEnumerator
|
||||
{
|
||||
public:
|
||||
CacheEnumerator(nsINetDataCache* aFirstCache):mCache(aFirstCache)
|
||||
{ NS_INIT_REFCNT(); }
|
||||
|
||||
virtual ~CacheEnumerator() {};
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHODIMP
|
||||
HasMoreElements(PRBool* aMoreElements) {
|
||||
*aMoreElements = (mCache != 0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GetNext(nsISupports* *aSupports) {
|
||||
*aSupports = mCache;
|
||||
if (!mCache)
|
||||
return NS_ERROR_FAILURE;
|
||||
NS_ADDREF(*aSupports);
|
||||
|
||||
nsCOMPtr<nsINetDataCache> nextCache;
|
||||
nsresult rv = mCache->GetNextCache(getter_AddRefs(nextCache));
|
||||
mCache = nextCache;
|
||||
return rv;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsINetDataCache> mCache;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(CacheEnumerator, NS_GET_IID(nsISimpleEnumerator))
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::NewCacheModuleIterator(nsISimpleEnumerator* *aResult)
|
||||
{
|
||||
*aResult = new CacheEnumerator(mCacheSearchChain);
|
||||
if (!*aResult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::RemoveAll(void)
|
||||
{
|
||||
nsresult rv, result;
|
||||
nsCOMPtr<nsISimpleEnumerator> iterator;
|
||||
nsCOMPtr<nsINetDataCache> cache;
|
||||
nsCOMPtr<nsISupports> iSupports;
|
||||
|
||||
result = NS_OK;
|
||||
rv = NewCacheModuleIterator(getter_AddRefs(iterator));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
while (1) {
|
||||
PRBool notDone;
|
||||
rv = iterator->HasMoreElements(¬Done);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!notDone)
|
||||
break;
|
||||
|
||||
iterator->GetNext(getter_AddRefs(iSupports));
|
||||
cache = do_QueryInterface(iSupports);
|
||||
|
||||
PRUint32 cacheFlags;
|
||||
rv = cache->GetFlags(&cacheFlags);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((cacheFlags & nsINetDataCache::READ_ONLY) == 0) {
|
||||
rv = cache->RemoveAll();
|
||||
if (NS_FAILED(rv))
|
||||
result = rv;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCacheManager::LimitMemCacheSize()
|
||||
{
|
||||
nsresult rv;
|
||||
nsReplacementPolicy* spaceManager;
|
||||
|
||||
NS_ASSERTION(gCacheManager, "No cache manager");
|
||||
|
||||
spaceManager = gCacheManager->mMemSpaceManager;
|
||||
|
||||
PRUint32 occupancy;
|
||||
rv = spaceManager->GetStorageInUse(&occupancy);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRUint32 memCacheCapacity = gCacheManager->mMemCacheCapacity;
|
||||
if (occupancy > CACHE_HIGH_WATER_MARK(memCacheCapacity))
|
||||
return spaceManager->Evict(CACHE_LOW_WATER_MARK(memCacheCapacity));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCacheManager::LimitDiskCacheSize()
|
||||
{
|
||||
nsresult rv;
|
||||
nsReplacementPolicy* spaceManager;
|
||||
|
||||
NS_ASSERTION(gCacheManager, "No cache manager");
|
||||
|
||||
spaceManager = gCacheManager->mDiskSpaceManager;
|
||||
|
||||
PRUint32 occupancy;
|
||||
rv = spaceManager->GetStorageInUse(&occupancy);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRUint32 diskCacheCapacity = gCacheManager->mDiskCacheCapacity;
|
||||
if (occupancy > CACHE_HIGH_WATER_MARK(diskCacheCapacity))
|
||||
return spaceManager->Evict(CACHE_LOW_WATER_MARK(diskCacheCapacity));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCacheManager::LimitCacheSize()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = LimitDiskCacheSize();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = LimitMemCacheSize();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::SetMemCacheCapacity(PRUint32 aCapacity)
|
||||
{
|
||||
mMemCacheCapacity = aCapacity;
|
||||
LimitCacheSize();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::GetMemCacheCapacity(PRUint32* aCapacity)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCapacity);
|
||||
*aCapacity = mMemCacheCapacity;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::SetDiskCacheCapacity(PRUint32 aCapacity)
|
||||
{
|
||||
mDiskCacheCapacity = aCapacity;
|
||||
LimitCacheSize();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::GetDiskCacheCapacity(PRUint32* aCapacity)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCapacity);
|
||||
*aCapacity = mDiskCacheCapacity;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::SetDiskCacheFolder(nsIFileSpec* aFolder)
|
||||
{
|
||||
NS_ENSURE_ARG(aFolder);
|
||||
|
||||
if (!mFileCache)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
nsCOMPtr<nsINetDataDiskCache> fileCache;
|
||||
fileCache = do_QueryInterface(mFileCache);
|
||||
return fileCache->SetDiskCacheFolder(aFolder);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::GetDiskCacheFolder(nsIFileSpec* *aFolder)
|
||||
{
|
||||
NS_ENSURE_ARG(aFolder);
|
||||
|
||||
if (!mFileCache)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
nsCOMPtr<nsINetDataDiskCache> fileCache;
|
||||
fileCache = do_QueryInterface(mFileCache);
|
||||
return fileCache->GetDiskCacheFolder(aFolder);
|
||||
}
|
||||
100
mozilla/netwerk/cache/mgr/nsCacheManager.h
vendored
Normal file
100
mozilla/netwerk/cache/mgr/nsCacheManager.h
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
#ifndef _nsCacheManager_h_
|
||||
#define _nsCacheManager_h_
|
||||
|
||||
// 2030f0b0-9567-11d3-90d3-0040056a906e
|
||||
#define NS_CACHE_MANAGER_CID \
|
||||
{ \
|
||||
0x2030f0b0, \
|
||||
0x9567, \
|
||||
0x11d3, \
|
||||
{0x90, 0xd3, 0x00, 0x40, 0x05, 0x6a, 0x90, 0x6e} \
|
||||
}
|
||||
|
||||
#include "nsINetDataCacheManager.h"
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsHashtable;
|
||||
class nsReplacementPolicy;
|
||||
class nsCachedNetData;
|
||||
|
||||
class nsCacheManager : public nsINetDataCacheManager {
|
||||
|
||||
public:
|
||||
nsCacheManager();
|
||||
virtual ~nsCacheManager();
|
||||
|
||||
NS_METHOD Init();
|
||||
|
||||
// nsISupports methods
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsINetDataCacheManager methods
|
||||
NS_DECL_NSINETDATACACHEMANAGER
|
||||
|
||||
private:
|
||||
|
||||
// Mapping from cache key to nsCachedNetData, but only for those cache
|
||||
// entries with external references, i.e. those referred to outside the
|
||||
// cache manager
|
||||
nsHashtable* mActiveCacheRecords;
|
||||
|
||||
// Memory cache
|
||||
nsCOMPtr<nsINetDataCache> mMemCache;
|
||||
|
||||
// Flat-file database cache; All content aggregated into single disk file
|
||||
nsCOMPtr<nsINetDataCache> mFlatCache;
|
||||
|
||||
// stream-as-file cache
|
||||
nsCOMPtr<nsINetDataCache> mFileCache;
|
||||
|
||||
// Unified replacement policy for flat-cache and file-cache
|
||||
nsReplacementPolicy* mDiskSpaceManager;
|
||||
|
||||
// Replacement policy for memory cache
|
||||
nsReplacementPolicy* mMemSpaceManager;
|
||||
|
||||
// List of caches in search order
|
||||
nsINetDataCache* mCacheSearchChain;
|
||||
|
||||
// Combined file/flat cache capacity, in KB
|
||||
PRUint32 mDiskCacheCapacity;
|
||||
|
||||
// Memory cache capacity, in KB
|
||||
PRUint32 mMemCacheCapacity;
|
||||
|
||||
protected:
|
||||
static nsresult NoteDormant(nsCachedNetData* aEntry);
|
||||
static nsresult LimitCacheSize();
|
||||
static nsresult LimitMemCacheSize();
|
||||
static nsresult LimitDiskCacheSize();
|
||||
|
||||
friend class nsCachedNetData;
|
||||
friend class CacheOutputStream;
|
||||
};
|
||||
|
||||
#endif // _nsCacheManager_h_
|
||||
1155
mozilla/netwerk/cache/mgr/nsCachedNetData.cpp
vendored
Normal file
1155
mozilla/netwerk/cache/mgr/nsCachedNetData.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
242
mozilla/netwerk/cache/mgr/nsCachedNetData.h
vendored
Normal file
242
mozilla/netwerk/cache/mgr/nsCachedNetData.h
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
#ifndef _nsCachedNetData_h_
|
||||
#define _nsCachedNetData_h_
|
||||
|
||||
#include "nsICachedNetData.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsINetDataCacheRecord.h"
|
||||
|
||||
class nsINetDataCache;
|
||||
class nsIStreamAsFileObserver;
|
||||
class nsIStreamAsFile;
|
||||
class nsIArena;
|
||||
class StreamAsFileObserverClosure;
|
||||
class CacheMetaData;
|
||||
|
||||
// Number of recent access times recorded
|
||||
#define MAX_K 3
|
||||
|
||||
/**
|
||||
* FIXME - add comment. There are a lot of these data structures resident in
|
||||
* memory, so be careful about adding members unnecessarily.
|
||||
*/
|
||||
class nsCachedNetData : public nsICachedNetData {
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsICachedNetData methods
|
||||
NS_DECL_NSICACHEDNETDATA
|
||||
|
||||
NS_METHOD Init(nsINetDataCacheRecord *aRecord, nsINetDataCache *aCache);
|
||||
|
||||
protected:
|
||||
|
||||
// Bits for mFlags, below
|
||||
typedef enum {
|
||||
DIRTY = 1 << 0, // Cache entry data needs to be flushed to database
|
||||
|
||||
// ==== Flags that can be set by the protocol handler ====
|
||||
ALLOW_PARTIAL = 1 << 1, // Protocol handler supports partial fetching
|
||||
UPDATE_IN_PROGRESS = 1 << 2, // Protocol handler now modifying cache data
|
||||
|
||||
// ==== Cache-entry state flags. At most one of these flags can be set ====
|
||||
TRUNCATED_CONTENT = 1 << 4, // Entry contains valid content, but it has
|
||||
// been truncated by cache manager
|
||||
|
||||
// A previously-used cache entry, which has been purged of all cached
|
||||
// content and protocol-private data. This cache entry can be refilled
|
||||
// with new content or it may be retained in this vestigial state
|
||||
// because the usage statistics it contains will be used by the
|
||||
// replacement policy if the same URI is ever cached again.
|
||||
VESTIGIAL = 1 << 5,
|
||||
|
||||
// ==== Memory usage status bits. At most one of these flags can be set ====
|
||||
RECYCLED = 1 << 8, // Previously associated database record has
|
||||
// been deleted; This cache entry is available
|
||||
// for recycling.
|
||||
|
||||
DORMANT = 1 << 9, // No references to this cache entry, except by
|
||||
// the cache manager itself
|
||||
|
||||
// ==== Setter bits ====
|
||||
LAST_MODIFIED_KNOWN = 1 <<12, // Protocol handler called SetLastModifiedTime()
|
||||
EXPIRATION_KNOWN = 1 <<13, // Protocol handler called SetExpirationTime()
|
||||
STALE_TIME_KNOWN = 1 <<14, // Protocol handler called SetStaleTime()
|
||||
|
||||
// ==== Useful flag combinations ====
|
||||
// Cache entry not eligible for eviction
|
||||
UNEVICTABLE = VESTIGIAL | RECYCLED | UPDATE_IN_PROGRESS,
|
||||
|
||||
// State flags that are in-memory only, i.e. not persistent
|
||||
TRANSIENT_FLAGS = DIRTY | RECYCLED | DORMANT
|
||||
} Flag;
|
||||
|
||||
PRBool GetFlag(Flag aFlag) { return (mFlags & aFlag) != 0; }
|
||||
nsresult GetFlag(PRBool *aResult, Flag aFlag) { *aResult = GetFlag(aFlag); return NS_OK; }
|
||||
|
||||
// Set a boolean flag for the cache entry
|
||||
nsresult SetFlag(PRBool aValue, Flag aFlag);
|
||||
nsresult SetFlag(Flag aFlag) { return SetFlag(PR_TRUE, aFlag); }
|
||||
nsresult ClearFlag(Flag aFlag) { return SetFlag(PR_FALSE, aFlag); }
|
||||
|
||||
void ComputeProfit(PRUint32 aCurrentTime);
|
||||
static int Compare(const void *a, const void *b, void *unused);
|
||||
|
||||
void NoteAccess();
|
||||
void NoteUpdate();
|
||||
|
||||
// Get underlying raw cache database record.
|
||||
nsresult GetRecord(nsINetDataCacheRecord* *aRecord);
|
||||
|
||||
nsresult GetRecordID(PRInt32 *aRecordID);
|
||||
|
||||
nsresult Evict(PRUint32 aTruncatedContentLength);
|
||||
|
||||
nsresult GetFileSpec(nsIFileSpec* *aFileSpec);
|
||||
|
||||
void NoteDownloadTime(PRTime start, PRTime end);
|
||||
|
||||
// placement new for arena-allocation
|
||||
void *operator new (size_t aSize, nsIArena *aArena);
|
||||
|
||||
friend class nsReplacementPolicy;
|
||||
friend class nsCacheManager;
|
||||
friend class StreamAsFile;
|
||||
friend class nsCacheEntryChannel;
|
||||
friend class CacheOutputStream;
|
||||
friend class InterceptStreamListener;
|
||||
|
||||
private:
|
||||
|
||||
nsCachedNetData() {};
|
||||
virtual ~nsCachedNetData() {};
|
||||
|
||||
// Initialize internal fields of this nsCachedNetData instance from the
|
||||
// underlying raw cache database record.
|
||||
nsresult Deserialize(PRBool aDeserializeFlags);
|
||||
|
||||
// Notify stream-as-file observers about change in cache entry status
|
||||
nsresult Notify(PRUint32 aMessage, nsresult aError);
|
||||
|
||||
// Add/Remove stream-as-file observers
|
||||
nsresult AddObserver(nsIStreamAsFile *aStreamAsFile, nsIStreamAsFileObserver* aObserver);
|
||||
nsresult RemoveObserver(nsIStreamAsFileObserver* aObserver);
|
||||
|
||||
// Mark cache entry to indicate a write out to the cache database is required
|
||||
void SetDirty() { mFlags |= DIRTY; }
|
||||
|
||||
nsresult Resurrect(nsINetDataCacheRecord *aRecord);
|
||||
|
||||
nsresult CommitFlags();
|
||||
|
||||
CacheMetaData* FindTaggedMetaData(const char* aTag, PRBool aCreate);
|
||||
|
||||
private:
|
||||
|
||||
// List of nsIStreamAsFileObserver's that will receive notification events
|
||||
// when the cache manager or a client desires to delete/truncate a cache
|
||||
// entry file.
|
||||
StreamAsFileObserverClosure* mObservers;
|
||||
|
||||
// Protocol-specific meta-data, opaque to the cache manager
|
||||
CacheMetaData *mMetaData;
|
||||
|
||||
// Next in chain for a single bucket in the replacement policy hash table
|
||||
// that maps from record ID to nsCachedNetData
|
||||
nsCachedNetData* mNext;
|
||||
|
||||
// See flag bits, above
|
||||
// NOTE: 16 bit member is combined with members below for
|
||||
// struct packing efficiency. Do not change order of members!
|
||||
PRUint16 mFlags;
|
||||
|
||||
protected:
|
||||
|
||||
// Number of nsCacheEntryChannels referring to this record
|
||||
PRUint8 mChannelCount;
|
||||
|
||||
// Below members are statistics kept per cache-entry, used to decide how
|
||||
// profitable it will be to evict a record from the cache relative to other
|
||||
// existing records. Note: times are measured in *seconds* since the
|
||||
// 1/1/70 epoch, same as a unix time_t.
|
||||
|
||||
// Number of accesses for this cache record
|
||||
// NOTE: 8 bit member is combined with members above for
|
||||
// struct packing efficiency. Do not change order of members!
|
||||
PRUint8 mNumAccesses;
|
||||
|
||||
// A reference to the underlying, raw cache database record, either as a
|
||||
// pointer to an in-memory object or as a database record identifier
|
||||
union {
|
||||
nsINetDataCacheRecord* mRecord;
|
||||
|
||||
// Database record ID of associated cache record. See
|
||||
// nsINetDataCache::GetRecordByID().
|
||||
PRInt32 mRecordID;
|
||||
};
|
||||
|
||||
// Weak link to parent cache
|
||||
nsINetDataCache* mCache;
|
||||
|
||||
// Length of stored content, which may be less than storage consumed if
|
||||
// compression is used
|
||||
PRUint32 mLogicalLength;
|
||||
|
||||
// Most recent cache entry access times, used to compute access frequency
|
||||
PRUint32 mAccessTime[MAX_K];
|
||||
|
||||
// We use modification time of the original document for replacement policy
|
||||
// computations, i.e. to compute a document's age, but if we don't know it,
|
||||
// we use the time that the document was last written to the cache.
|
||||
union {
|
||||
// Document modification time, if known.
|
||||
PRUint32 mLastModifiedTime;
|
||||
|
||||
// Time of last cache update for this doc
|
||||
PRUint32 mLastUpdateTime;
|
||||
};
|
||||
|
||||
union {
|
||||
// Time until which document is fresh, i.e. does not have to be validated
|
||||
// with server and, therefore, data in cache is guaranteed usable
|
||||
PRUint32 mExpirationTime;
|
||||
|
||||
// Heuristic time at which cached document is likely to be out-of-date
|
||||
// with respect to canonical copy on server. Used for cache replacement
|
||||
// policy, not for validation.
|
||||
PRUint32 mStaleTime;
|
||||
};
|
||||
|
||||
// Download time per byte, measure roughly in units of KB/s
|
||||
float mDownloadRate;
|
||||
|
||||
// Heuristic estimate of cache entry future benefits, based on above values
|
||||
float mProfit;
|
||||
};
|
||||
|
||||
#endif // _nsCachedNetData_h_
|
||||
|
||||
666
mozilla/netwerk/cache/mgr/nsReplacementPolicy.cpp
vendored
Normal file
666
mozilla/netwerk/cache/mgr/nsReplacementPolicy.cpp
vendored
Normal file
@@ -0,0 +1,666 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
#include "nsReplacementPolicy.h"
|
||||
#include "nsCachedNetData.h"
|
||||
|
||||
#include "nsQuickSort.h"
|
||||
#include "nsIAllocator.h"
|
||||
#include "nsIEnumerator.h"
|
||||
#include "prtime.h"
|
||||
#include "prbit.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include <math.h>
|
||||
|
||||
// Constant used to estimate frequency of access to a document based on size
|
||||
#define CACHE_CONST_B 1.35
|
||||
|
||||
// A cache whose space is managed by this replacement policy
|
||||
class nsReplacementPolicy::CacheInfo {
|
||||
public:
|
||||
CacheInfo(nsINetDataCache* aCache):mCache(aCache),mNext(0) {}
|
||||
|
||||
nsINetDataCache* mCache;
|
||||
CacheInfo* mNext;
|
||||
};
|
||||
|
||||
nsReplacementPolicy::nsReplacementPolicy()
|
||||
: mRankedEntries(0), mCaches(0), mRecordsRemovedSinceLastRanking(0),
|
||||
mNumEntries(0), mCapacityRankedEntriesArray(0), mLastRankTime(0) {}
|
||||
|
||||
nsReplacementPolicy::~nsReplacementPolicy()
|
||||
{
|
||||
if (mRankedEntries)
|
||||
nsAllocator::Free(mRankedEntries);
|
||||
if (mMapRecordIdToEntry)
|
||||
nsAllocator::Free(mMapRecordIdToEntry);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsReplacementPolicy::Init(PRUint32 aMaxCacheEntries)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = NS_NewHeapArena(getter_AddRefs(mArena), sizeof(nsCachedNetData) * 32);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mMaxEntries = aMaxCacheEntries;
|
||||
|
||||
mHashArrayLength = PR_CeilingLog2(aMaxCacheEntries) >> 3;
|
||||
size_t numBytes = mHashArrayLength * sizeof(*mMapRecordIdToEntry);
|
||||
mMapRecordIdToEntry = (nsCachedNetData**)nsAllocator::Alloc(numBytes);
|
||||
if (!mMapRecordIdToEntry)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsCRT::zero(mMapRecordIdToEntry, numBytes);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsReplacementPolicy::AddCache(nsINetDataCache *aCache)
|
||||
{
|
||||
CacheInfo *cacheInfo = new CacheInfo(aCache);
|
||||
if (!cacheInfo)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
cacheInfo->mNext = mCaches;
|
||||
mCaches = cacheInfo;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsReplacementPolicy::HashRecordID(PRInt32 aRecordID)
|
||||
{
|
||||
return ((aRecordID >> 16) ^ aRecordID) & (mHashArrayLength - 1);
|
||||
}
|
||||
|
||||
nsCachedNetData*
|
||||
nsReplacementPolicy::FindCacheEntryByRecordID(PRInt32 aRecordID, nsINetDataCache *aCache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCachedNetData* cacheEntry;
|
||||
PRUint32 bucket = HashRecordID(aRecordID);
|
||||
|
||||
cacheEntry = mMapRecordIdToEntry[bucket];
|
||||
for (;cacheEntry; cacheEntry = cacheEntry->mNext) {
|
||||
|
||||
PRInt32 recordID;
|
||||
rv = cacheEntry->GetRecordID(&recordID);
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
if ((recordID == aRecordID) && (cacheEntry->mCache == aCache))
|
||||
return cacheEntry;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Add a cache entry to the hash table that maps record ID to entries
|
||||
void
|
||||
nsReplacementPolicy::AddCacheEntry(nsCachedNetData* aCacheEntry, PRInt32 aRecordID)
|
||||
{
|
||||
nsCachedNetData** cacheEntryp;
|
||||
PRUint32 bucket = HashRecordID(aRecordID);
|
||||
|
||||
cacheEntryp = &mMapRecordIdToEntry[bucket];
|
||||
while (*cacheEntryp)
|
||||
cacheEntryp = &(*cacheEntryp)->mNext;
|
||||
*cacheEntryp = aCacheEntry;
|
||||
aCacheEntry->mNext = 0;
|
||||
}
|
||||
|
||||
// Delete a cache entry from the hash table that maps record ID to entries
|
||||
nsresult
|
||||
nsReplacementPolicy::DeleteCacheEntry(nsCachedNetData* aCacheEntry)
|
||||
{
|
||||
nsresult rv;
|
||||
PRInt32 recordID;
|
||||
rv = aCacheEntry->GetRecordID(&recordID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRUint32 bucket = HashRecordID(recordID);
|
||||
|
||||
nsCachedNetData** cacheEntryp;
|
||||
cacheEntryp = &mMapRecordIdToEntry[bucket];
|
||||
while (*cacheEntryp) {
|
||||
if (*cacheEntryp == aCacheEntry) {
|
||||
*cacheEntryp = aCacheEntry->mNext;
|
||||
return NS_OK;
|
||||
}
|
||||
cacheEntryp = &(*cacheEntryp)->mNext;
|
||||
}
|
||||
|
||||
NS_ASSERTION(0, "hash table inconsistency");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsReplacementPolicy::AddAllRecordsInCache(nsINetDataCache *aCache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISimpleEnumerator> iterator;
|
||||
nsCOMPtr<nsISupports> iSupports;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
rv = aCache->NewCacheEntryIterator(getter_AddRefs(iterator));
|
||||
if (!NS_SUCCEEDED(rv)) return rv;
|
||||
|
||||
while (1) {
|
||||
PRBool notDone;
|
||||
|
||||
rv = iterator->HasMoreElements(¬Done);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!notDone)
|
||||
break;
|
||||
|
||||
rv = iterator->GetNext(getter_AddRefs(iSupports));
|
||||
if (!NS_SUCCEEDED(rv)) return rv;
|
||||
record = do_QueryInterface(iSupports);
|
||||
|
||||
rv = AssociateCacheEntryWithRecord(record, aCache, 0);
|
||||
if (!NS_SUCCEEDED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Get current time and convert to seconds since the epoch
|
||||
static PRUint32
|
||||
now32()
|
||||
{
|
||||
double nowFP;
|
||||
PRInt64 now64 = PR_Now();
|
||||
LL_L2D(nowFP, now64);
|
||||
PRUint32 now = (PRUint32)(nowFP * 1e-6);
|
||||
return now;
|
||||
}
|
||||
|
||||
void
|
||||
nsCachedNetData::NoteDownloadTime(PRTime start, PRTime end)
|
||||
{
|
||||
double startFP, endFP, rate, duration;
|
||||
|
||||
LL_L2D(startFP, start);
|
||||
LL_L2D(endFP, end);
|
||||
|
||||
duration = endFP - startFP;
|
||||
|
||||
// If the data arrives so fast that it can not be timed due to the clock
|
||||
// granularity, assume a data arrival duration of 10 ms
|
||||
if (!duration)
|
||||
duration = 10000;
|
||||
|
||||
// Compute download rate in kB/s
|
||||
rate = mLogicalLength / (duration * (1e-6 * 1024.0));
|
||||
|
||||
if (mDownloadRate) {
|
||||
// Exponentially smooth download rate
|
||||
const double alpha = 0.5;
|
||||
mDownloadRate = (float)(mDownloadRate * alpha + rate * (1.0 - alpha));
|
||||
} else {
|
||||
mDownloadRate = (float)rate;
|
||||
}
|
||||
}
|
||||
|
||||
// 1 hour
|
||||
#define MIN_HALFLIFE (60 * 60)
|
||||
|
||||
// 1 week
|
||||
#define TYPICAL_HALFLIFE (7 * 24 * 60 * 60)
|
||||
|
||||
/**
|
||||
* Estimate the profit that would be lost if the given cache entry was evicted
|
||||
* from the cache. Profit is defined as the future expected download delay per
|
||||
* byte of cached content. The profit computation is made based on projected
|
||||
* frequency of access, prior download performance and a heuristic staleness
|
||||
* criteria. The technique used is a variation of that described in the
|
||||
* following paper:
|
||||
*
|
||||
* "A Case for Delay-Conscious Caching of Web Documents"
|
||||
* http://www.bell-labs.com/user/rvingral/www97.html
|
||||
*
|
||||
* Briefly, expected profit is:
|
||||
*
|
||||
* (projected frequency of access) * (download time per byte) * (probability freshness)
|
||||
*/
|
||||
void
|
||||
nsCachedNetData::ComputeProfit(PRUint32 aNow)
|
||||
{
|
||||
PRUint32 K, now;
|
||||
|
||||
if (aNow)
|
||||
now = aNow;
|
||||
else
|
||||
now = now32();
|
||||
|
||||
K = PR_MIN(MAX_K, mNumAccesses);
|
||||
if (!K) {
|
||||
mProfit = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute time, in seconds, since k'th most recent access
|
||||
double timeSinceKthAccess = now - mAccessTime[K - 1];
|
||||
if (timeSinceKthAccess <= 0.0) // Sanity check
|
||||
timeSinceKthAccess = 1.0;
|
||||
|
||||
// Estimate frequency of future document access based on past
|
||||
// access frequency
|
||||
double frequencyAccess = K / timeSinceKthAccess;
|
||||
|
||||
// If we don't have much historical data on access frequency
|
||||
// use a heuristic based on document size as an estimate
|
||||
if (mLogicalLength) {
|
||||
if (K == 1) {
|
||||
frequencyAccess /= pow(mLogicalLength, CACHE_CONST_B);
|
||||
} else if (K == 2) {
|
||||
frequencyAccess /= pow(mLogicalLength, CACHE_CONST_B / 2);
|
||||
}
|
||||
}
|
||||
|
||||
// Estimate likelihood that data in cache is fresh, i.e.
|
||||
// that it corresponds to the document on the server
|
||||
double probabilityFreshness;
|
||||
PRInt32 halfLife, age, docTime;
|
||||
PRBool potentiallyStale;
|
||||
|
||||
docTime = GetFlag(LAST_MODIFIED_KNOWN) ? mLastModifiedTime : mLastUpdateTime;
|
||||
age = now - docTime;
|
||||
|
||||
probabilityFreshness = 1.0; // Optimistic
|
||||
|
||||
if (GetFlag(EXPIRATION_KNOWN)) {
|
||||
potentiallyStale = now > mExpirationTime;
|
||||
halfLife = mExpirationTime - mLastModifiedTime;
|
||||
} else if (GetFlag(STALE_TIME_KNOWN)) {
|
||||
potentiallyStale = PR_TRUE;
|
||||
halfLife = mStaleTime - docTime;
|
||||
} else {
|
||||
potentiallyStale = PR_TRUE;
|
||||
halfLife = TYPICAL_HALFLIFE;
|
||||
}
|
||||
|
||||
if (potentiallyStale) {
|
||||
if (halfLife < MIN_HALFLIFE)
|
||||
halfLife = MIN_HALFLIFE;
|
||||
|
||||
probabilityFreshness = pow(0.5, (double)age / (double)halfLife);
|
||||
}
|
||||
|
||||
mProfit = (float)(frequencyAccess * probabilityFreshness);
|
||||
if (mDownloadRate)
|
||||
mProfit /= mDownloadRate;
|
||||
}
|
||||
|
||||
// Number of entries to grow mRankedEntries array when it's full
|
||||
#define STATS_GROWTH_INCREMENT 256
|
||||
|
||||
|
||||
// Sorting predicate for NS_Quicksort
|
||||
int
|
||||
nsCachedNetData::Compare(const void *a, const void *b, void *unused)
|
||||
{
|
||||
nsCachedNetData* entryA = *(nsCachedNetData**)a;
|
||||
nsCachedNetData* entryB = *(nsCachedNetData**)b;
|
||||
|
||||
// Percolate deleted or empty entries to the end of the mRankedEntries
|
||||
// array, so that they can be recycled.
|
||||
if (!entryA || entryA->GetFlag(RECYCLED)) {
|
||||
if (!entryB || entryB->GetFlag(RECYCLED))
|
||||
return 0;
|
||||
else
|
||||
return +1;
|
||||
}
|
||||
if (!entryB || entryB->GetFlag(RECYCLED))
|
||||
return -1;
|
||||
|
||||
// Evicted entries (those with no content data) and active entries (those
|
||||
// currently being updated) are collected towards the end of the sorted
|
||||
// array just prior to the deleted cache entries, since evicted entries
|
||||
// can't be re-evicted.
|
||||
if (entryA->GetFlag(UPDATE_IN_PROGRESS)) {
|
||||
if (entryB->GetFlag(UPDATE_IN_PROGRESS))
|
||||
return 0;
|
||||
else
|
||||
return +1;
|
||||
}
|
||||
if (entryB->GetFlag(UPDATE_IN_PROGRESS))
|
||||
return -1;
|
||||
|
||||
PRUint16 Ka = PR_MIN(MAX_K, entryA->mNumAccesses);
|
||||
PRUint16 Kb = PR_MIN(MAX_K, entryB->mNumAccesses);
|
||||
|
||||
// Order cache entries by the number of times they've been accessed
|
||||
if (Ka < Kb)
|
||||
return -1;
|
||||
if (Ka > Kb)
|
||||
return +1;
|
||||
|
||||
/*
|
||||
* Among records that have been accessed an equal number of times, order
|
||||
* them by profit.
|
||||
*/
|
||||
if (entryA->mProfit > entryB->mProfit)
|
||||
return +1;
|
||||
if (entryA->mProfit < entryB->mProfit)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rank cache entries in terms of their elegibility for eviction.
|
||||
*/
|
||||
nsresult
|
||||
nsReplacementPolicy::RankRecords()
|
||||
{
|
||||
PRUint32 i, now;
|
||||
|
||||
// Add all cache records if this is the first ranking
|
||||
if (!mLastRankTime) {
|
||||
nsresult rv;
|
||||
CacheInfo *cacheInfo;
|
||||
|
||||
cacheInfo = mCaches;
|
||||
while (cacheInfo) {
|
||||
rv = AddAllRecordsInCache(cacheInfo->mCache);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
cacheInfo = cacheInfo->mNext;
|
||||
}
|
||||
}
|
||||
|
||||
// Get current time and convert to seconds since the epoch
|
||||
now = now32();
|
||||
|
||||
// Recompute profit for every known cache record, except deleted ones
|
||||
for (i = 0; i < mNumEntries; i++) {
|
||||
nsCachedNetData* entry = mRankedEntries[i];
|
||||
if (entry && !entry->GetFlag(nsCachedNetData::RECYCLED))
|
||||
entry->ComputeProfit(now);
|
||||
}
|
||||
NS_QuickSort(mRankedEntries, mNumEntries, sizeof *mRankedEntries,
|
||||
nsCachedNetData::Compare, 0);
|
||||
|
||||
mNumEntries -= mRecordsRemovedSinceLastRanking;
|
||||
mRecordsRemovedSinceLastRanking = 0;
|
||||
mLastRankTime = now;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// A heuristic policy to avoid the cost of re-ranking cache records by
|
||||
// profitability every single time space must be made available in the cache.
|
||||
void
|
||||
nsReplacementPolicy::MaybeRerankRecords()
|
||||
{
|
||||
// Rank at most once per minute
|
||||
PRUint32 now = now32();
|
||||
if ((now - mLastRankTime) >= 60)
|
||||
RankRecords();
|
||||
}
|
||||
|
||||
void
|
||||
nsReplacementPolicy::CompactRankedEntriesArray()
|
||||
{
|
||||
if (mRecordsRemovedSinceLastRanking || !mLastRankTime)
|
||||
RankRecords();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsReplacementPolicy::CheckForTooManyCacheEntries()
|
||||
{
|
||||
if (mCapacityRankedEntriesArray == mMaxEntries) {
|
||||
return DeleteOneEntry(0);
|
||||
} else {
|
||||
nsresult rv;
|
||||
CacheInfo *cacheInfo;
|
||||
|
||||
cacheInfo = mCaches;
|
||||
while (cacheInfo) {
|
||||
PRUint32 numEntries, maxEntries;
|
||||
|
||||
rv = cacheInfo->mCache->GetNumEntries(&numEntries);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = cacheInfo->mCache->GetMaxEntries(&maxEntries);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (numEntries == maxEntries)
|
||||
return DeleteOneEntry(cacheInfo->mCache);
|
||||
|
||||
cacheInfo = cacheInfo->mNext;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new association between a low-level cache database record and a
|
||||
* cache entry. Add the entry to the set of entries eligible for eviction from
|
||||
* the cache. This would typically be done when the cache entry is created.
|
||||
*/
|
||||
nsresult
|
||||
nsReplacementPolicy::AssociateCacheEntryWithRecord(nsINetDataCacheRecord *aRecord,
|
||||
nsINetDataCache* aCache,
|
||||
nsCachedNetData** aResult)
|
||||
{
|
||||
nsCachedNetData* cacheEntry;
|
||||
nsresult rv;
|
||||
|
||||
// First, see if the record is already known to the replacement policy
|
||||
PRInt32 recordID;
|
||||
rv = aRecord->GetRecordID(&recordID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
cacheEntry = FindCacheEntryByRecordID(recordID, aCache);
|
||||
if (cacheEntry) {
|
||||
if (aResult) {
|
||||
if (cacheEntry->GetFlag(nsCachedNetData::DORMANT))
|
||||
cacheEntry->Resurrect(aRecord);
|
||||
NS_ADDREF(cacheEntry);
|
||||
*aResult = cacheEntry;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Compact the array of cache entry statistics, so that free entries appear
|
||||
// at the end, for possible reuse.
|
||||
if (mNumEntries && (mNumEntries == mCapacityRankedEntriesArray))
|
||||
CompactRankedEntriesArray();
|
||||
|
||||
// If compaction doesn't yield available entries in the
|
||||
// mRankedEntries array, then extend the array.
|
||||
if (mNumEntries == mCapacityRankedEntriesArray) {
|
||||
PRUint32 newCapacity;
|
||||
|
||||
rv = CheckForTooManyCacheEntries();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
newCapacity = mCapacityRankedEntriesArray + STATS_GROWTH_INCREMENT;
|
||||
if (newCapacity > mMaxEntries)
|
||||
newCapacity = mMaxEntries;
|
||||
|
||||
nsCachedNetData** newRankedEntriesArray;
|
||||
PRUint32 numBytes = sizeof(nsCachedNetData*) * newCapacity;
|
||||
newRankedEntriesArray =
|
||||
(nsCachedNetData**)nsAllocator::Realloc(mRankedEntries, numBytes);
|
||||
if (!newRankedEntriesArray)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mRankedEntries = newRankedEntriesArray;
|
||||
mCapacityRankedEntriesArray = newCapacity;
|
||||
|
||||
PRUint32 i;
|
||||
for (i = mNumEntries; i < newCapacity; i++)
|
||||
mRankedEntries[i] = 0;
|
||||
}
|
||||
|
||||
// Recycle the record after the last in-use record in the array
|
||||
nsCachedNetData *entry = mRankedEntries[mNumEntries];
|
||||
NS_ASSERTION(!entry || !entry->GetFlag(nsCachedNetData::RECYCLED),
|
||||
"Only deleted cache entries should appear at end of array");
|
||||
|
||||
if (!entry) {
|
||||
entry = new(mArena) nsCachedNetData;
|
||||
if (!entry)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
mRankedEntries[mNumEntries] = entry;
|
||||
} else {
|
||||
// Clear out recycled data structure
|
||||
nsCRT::zero(entry, sizeof(*entry));
|
||||
}
|
||||
|
||||
entry->Init(aRecord, aCache);
|
||||
AddCacheEntry(entry, recordID);
|
||||
|
||||
// Add one reference to the cache entry from the cache manager
|
||||
NS_ADDREF(entry);
|
||||
|
||||
if (aResult) {
|
||||
// And one reference from our caller
|
||||
NS_ADDREF(entry);
|
||||
*aResult = entry;
|
||||
}
|
||||
|
||||
mNumEntries++;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsReplacementPolicy::GetCachedNetData(const char* cacheKey, PRUint32 cacheKeyLength,
|
||||
nsINetDataCache* aCache,
|
||||
nsCachedNetData** aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
|
||||
rv = aCache->GetCachedNetData(cacheKey, cacheKeyLength,
|
||||
getter_AddRefs(record));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
return AssociateCacheEntryWithRecord(record, aCache, aResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the least desirable record from the cache database. This is used
|
||||
* when the addition of another record would exceed either the cache manager or
|
||||
* the cache's maximum permitted number of records.
|
||||
*/
|
||||
nsresult
|
||||
nsReplacementPolicy::DeleteOneEntry(nsINetDataCache *aCache)
|
||||
{
|
||||
PRUint32 i;
|
||||
nsresult rv;
|
||||
nsCachedNetData *entry;
|
||||
|
||||
i = 0;
|
||||
while (1) {
|
||||
MaybeRerankRecords();
|
||||
for (; i < mNumEntries; i++) {
|
||||
entry = mRankedEntries[i];
|
||||
if (!entry || entry->GetFlag(nsCachedNetData::RECYCLED))
|
||||
continue;
|
||||
if (!aCache || (entry->mCache == aCache))
|
||||
break;
|
||||
}
|
||||
|
||||
// Report error if no record found to delete
|
||||
if (i == mNumEntries)
|
||||
return NS_ERROR_FAILURE;
|
||||
rv = entry->Delete();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = DeleteCacheEntry(entry);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsReplacementPolicy::GetStorageInUse(PRUint32* aStorageInUse)
|
||||
{
|
||||
nsresult rv;
|
||||
CacheInfo *cacheInfo;
|
||||
|
||||
*aStorageInUse = 0;
|
||||
cacheInfo = mCaches;
|
||||
while (cacheInfo) {
|
||||
PRUint32 cacheStorage;
|
||||
rv = cacheInfo->mCache->GetStorageInUse(&cacheStorage);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*aStorageInUse += cacheStorage;
|
||||
cacheInfo = cacheInfo->mNext;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the least desirable records from the cache until the occupancy of the
|
||||
* cache has been reduced by the given number of KB. This is used when the
|
||||
* addition of more cache data would exceed the cache's capacity.
|
||||
*/
|
||||
nsresult
|
||||
nsReplacementPolicy::Evict(PRUint32 aTargetOccupancy)
|
||||
{
|
||||
PRUint32 i;
|
||||
nsCachedNetData *entry;
|
||||
nsresult rv;
|
||||
PRUint32 occupancy;
|
||||
PRInt32 truncatedLength;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
|
||||
MaybeRerankRecords();
|
||||
for (i = 0; i < mNumEntries; i++) {
|
||||
rv = GetStorageInUse(&occupancy);
|
||||
if (!NS_SUCCEEDED(rv)) return rv;
|
||||
|
||||
if (occupancy <= aTargetOccupancy)
|
||||
return NS_OK;
|
||||
|
||||
entry = mRankedEntries[i];
|
||||
|
||||
// Skip deleted/empty cache entries and ones that have already been evicted
|
||||
if (!entry || entry->GetFlag(nsCachedNetData::UNEVICTABLE))
|
||||
continue;
|
||||
|
||||
if (entry->GetFlag(nsCachedNetData::ALLOW_PARTIAL)) {
|
||||
rv = entry->GetRecord(getter_AddRefs(record));
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
PRUint32 contentLength;
|
||||
rv = record->GetStoredContentLength(&contentLength);
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
// Additional cache storage required, in KB
|
||||
PRUint32 storageToReclaim = (occupancy - aTargetOccupancy) << 10;
|
||||
|
||||
truncatedLength = (PRInt32)(contentLength - storageToReclaim);
|
||||
if (truncatedLength < 0)
|
||||
truncatedLength = 0;
|
||||
} else {
|
||||
truncatedLength = 0;
|
||||
}
|
||||
rv = entry->Evict(truncatedLength);
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
136
mozilla/netwerk/cache/mgr/nsReplacementPolicy.h
vendored
Normal file
136
mozilla/netwerk/cache/mgr/nsReplacementPolicy.h
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class manages one or more caches that share a storage resource, e.g. a
|
||||
* file cache and a flat-database cache might each occupy space on the disk and
|
||||
* they would share a single instance of nsReplacementPolicy. The replacement
|
||||
* policy heuristically chooses which cache entries to evict when storage is
|
||||
* required to accommodate incoming cache data.
|
||||
*/
|
||||
|
||||
#ifndef _nsReplacementPolicy_h_
|
||||
#define _nsReplacementPolicy_h_
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsISupportsUtils.h"
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsICachedNetData.h"
|
||||
#include "nsIArena.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsHashtable.h"
|
||||
|
||||
class nsCachedNetData;
|
||||
struct PL_HashTable;
|
||||
|
||||
/**
|
||||
* This private class is responsible for implementing the network data cache's
|
||||
* replacement policy, i.e. it decides which cache data should be evicted to
|
||||
* make room for new incoming data.
|
||||
*/
|
||||
class nsReplacementPolicy {
|
||||
|
||||
public:
|
||||
|
||||
nsReplacementPolicy();
|
||||
~nsReplacementPolicy();
|
||||
|
||||
protected:
|
||||
|
||||
nsresult Init(PRUint32 aMaxCacheEntries);
|
||||
nsresult AddCache(nsINetDataCache *aCache);
|
||||
nsresult GetCachedNetData(const char* cacheKey, PRUint32 cacheKeyLength,
|
||||
nsINetDataCache* aCache,
|
||||
nsCachedNetData** aResult);
|
||||
nsresult GetStorageInUse(PRUint32* aNumKBytes);
|
||||
|
||||
friend class nsCacheManager;
|
||||
|
||||
private:
|
||||
nsresult RankRecords();
|
||||
void MaybeRerankRecords();
|
||||
void CompactRankedEntriesArray();
|
||||
nsresult DeleteOneEntry(nsINetDataCache* aCache);
|
||||
nsresult Evict(PRUint32 aTargetOccupancy);
|
||||
|
||||
nsCachedNetData* FindCacheEntryByRecordID(PRInt32 aRecordID, nsINetDataCache *aCache);
|
||||
void AddCacheEntry(nsCachedNetData* aCacheEntry, PRInt32 aRecordID);
|
||||
nsresult DeleteCacheEntry(nsCachedNetData* aCacheEntry);
|
||||
PRUint32 HashRecordID(PRInt32 aRecordID);
|
||||
nsresult AssociateCacheEntryWithRecord(nsINetDataCacheRecord *aRecord,
|
||||
nsINetDataCache* aCache,
|
||||
nsCachedNetData** aResult);
|
||||
|
||||
nsresult AddAllRecordsInCache(nsINetDataCache *aCache);
|
||||
nsresult CheckForTooManyCacheEntries();
|
||||
|
||||
class CacheInfo;
|
||||
|
||||
private:
|
||||
|
||||
// Growable array of pointers to individual cache entries; It is sorted by
|
||||
// profitability, such that low-numbered array indices refer to cache
|
||||
// entries that are the least profitable to retain. New cache entries are
|
||||
// added to the end of the array. Deleted cache entries are specially
|
||||
// marked and percolate to the end of the array for recycling whenever
|
||||
// mRankedEntries is sorted. Evicted cache entries (those with no
|
||||
// associated content data) are retained for the purpose of improving the
|
||||
// replacement policy efficacy, and are percolated towards the end of the
|
||||
// array, just prior to the deleted cache entries.
|
||||
//
|
||||
// The array is not in sorted order 100% of the time; For efficiency
|
||||
// reasons, sorting is only done when heuristically deemed necessary.
|
||||
nsCachedNetData** mRankedEntries;
|
||||
|
||||
// Hash table buckets to map Record ID to cache entry. We use this instead
|
||||
// of a PL_HashTable to reduce storage requirements
|
||||
nsCachedNetData** mMapRecordIdToEntry;
|
||||
|
||||
// Length of mMapRecordIdToEntry array
|
||||
PRUint32 mHashArrayLength;
|
||||
|
||||
// Linked list of caches that share this replacement policy
|
||||
CacheInfo* mCaches;
|
||||
|
||||
// Allocation area for cache entry (nsCachedNetData) instances
|
||||
nsCOMPtr<nsIArena> mArena;
|
||||
|
||||
// Bookkeeping
|
||||
PRUint32 mRecordsRemovedSinceLastRanking;
|
||||
|
||||
// Maximum permitted length of mRankedEntries array
|
||||
PRUint32 mMaxEntries;
|
||||
|
||||
// Number of occupied slots in mRankedEntries array
|
||||
PRUint32 mNumEntries;
|
||||
|
||||
// Capacity of mRankedEntries array
|
||||
PRUint32 mCapacityRankedEntriesArray;
|
||||
|
||||
// Time at which cache entries were last ranked by profitability
|
||||
PRUint32 mLastRankTime;
|
||||
};
|
||||
|
||||
|
||||
#endif // _nsReplacementPolicy_h_
|
||||
43
mozilla/netwerk/cache/public/Makefile.in
vendored
Normal file
43
mozilla/netwerk/cache/public/Makefile.in
vendored
Normal file
@@ -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 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@
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsICachedNetData.idl \
|
||||
nsINetDataCacheManager.idl \
|
||||
nsINetDataCache.idl \
|
||||
nsINetDataCacheRecord.idl \
|
||||
nsINetDataDiskCache.idl \
|
||||
nsIStreamAsFile.idl \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
41
mozilla/netwerk/cache/public/Makefile.win
vendored
Executable file
41
mozilla/netwerk/cache/public/Makefile.win
vendored
Executable file
@@ -0,0 +1,41 @@
|
||||
#!gmake
|
||||
#
|
||||
# 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):
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
DEPTH = ..\..\..
|
||||
include <$(DEPTH)/config/config.mak>
|
||||
|
||||
|
||||
EXPORTS = \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
.\nsICachedNetData.idl \
|
||||
.\nsINetDataCacheManager.idl \
|
||||
.\nsINetDataCache.idl \
|
||||
.\nsINetDataCacheRecord.idl \
|
||||
.\nsINetDataDiskCache.idl \
|
||||
.\nsIStreamAsFile.idl \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)/config/rules.mak>
|
||||
|
||||
229
mozilla/netwerk/cache/public/nsICachedNetData.idl
vendored
Normal file
229
mozilla/netwerk/cache/public/nsICachedNetData.idl
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include "nsrootidl.idl"
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIFileSpec;
|
||||
interface nsIURI;
|
||||
interface nsIObserver;
|
||||
interface nsIChannel;
|
||||
interface nsINetDataCache;
|
||||
interface nsINetDataCacheRecord;
|
||||
interface nsILoadGroup;
|
||||
interface nsIStreamListener;
|
||||
|
||||
/**
|
||||
* The nsICachedNetData interface represents a single entry in a database that
|
||||
* caches data retrieved from the network. This interface is implemented by the
|
||||
* cache manager on top of the low-level nsINetDataCacheRecord and
|
||||
* nsINetDataCache interfaces that are implemented by the database.
|
||||
*
|
||||
* Each cache record may contain both content and metadata. The content may
|
||||
* be, for example, GIF image data or HTML, and it is accessed through
|
||||
* nsIChannel's streaming API. The opaque metadata, which may contain HTTP
|
||||
* headers among other things, is stored as a byte array. Each entry in the
|
||||
* cache is indexed by two different keys: a record id number and a key created
|
||||
* by combining the URI with a "secondary key", e.g. HTTP post data.
|
||||
*
|
||||
* @See nsINetDataCacheRecord
|
||||
* @See nsINetDataCache
|
||||
* @See nsINetDataDiskCache
|
||||
* @See nsINetDataCacheManager
|
||||
*/
|
||||
[scriptable, uuid(6aeb2a40-6d43-11d3-90c8-000064657374)]
|
||||
interface nsICachedNetData : nsISupports
|
||||
{
|
||||
/**
|
||||
* String form of the URI provided as an argument to the call to
|
||||
* nsINetDataCacheManager::GetCachedNetData() that created this record.
|
||||
*/
|
||||
readonly attribute string uriSpec;
|
||||
|
||||
/**
|
||||
* Getter for the opaque secondary database key provided as an argument to
|
||||
* the call to nsINetDataCacheManager::GetCachedNetData() that created this
|
||||
* record.
|
||||
*/
|
||||
void getSecondaryKey(out unsigned long length,
|
||||
[retval, size_is(length)] out string secondaryKey);
|
||||
|
||||
/**
|
||||
* This flag may be set by a protocol handler to indicate that it supports
|
||||
* partial fetching of data. In that case, the cache manager is permitted
|
||||
* to truncate the entry's content to accommodate incoming data for other
|
||||
* cache entries rather than deleting it wholesale.
|
||||
*/
|
||||
attribute boolean allowPartial;
|
||||
|
||||
/**
|
||||
* This flag indicates that the write stream supplying content data for the
|
||||
* cache did not complete normally and, therefore, the content may be
|
||||
* truncated.
|
||||
*/
|
||||
readonly attribute boolean partialFlag;
|
||||
|
||||
/**
|
||||
* This flag can be set and cleared by a protocol handler as a form of
|
||||
* self-notification, so as to avoid race conditions in which a protocol
|
||||
* handler issues two identical network requests to fill the same cache
|
||||
* entry. The cache manager itself largely ignores this flag.
|
||||
*/
|
||||
attribute boolean updateInProgress;
|
||||
|
||||
/**
|
||||
* inUse is set if any existing channels are associated with this cache
|
||||
* entry or if the updateInProgess flag is set. This can be used to
|
||||
* prevent writing to a cache entry by a protocol handler if it's being
|
||||
* read or written elsewhere.
|
||||
*/
|
||||
readonly attribute boolean inUse;
|
||||
|
||||
/**
|
||||
* Date/time that the document was last stored on the origin server, as
|
||||
* supplied by the protocol handler. This value is used as input to the
|
||||
* cache replacement policy, i.e. it is not used for validation. If the
|
||||
* protocol can't supply a last-modified time, this attribute should remain
|
||||
* unset. When unset, the value of this attribute is zero.
|
||||
*
|
||||
* FIXME: Should use nsIDateTime interface, once it's created
|
||||
* instead of PRTime, for improved scriptability ?
|
||||
*/
|
||||
attribute PRTime lastModifiedTime;
|
||||
|
||||
/**
|
||||
* Supplied by the protocol handler, the expirationTime attribute specifies
|
||||
* the time until which the document is guaranteed fresh, i.e. the document
|
||||
* does not have to be validated with the server and, therefore, any data
|
||||
* in cache is definitely usable. The value of this attribute serves as a
|
||||
* hint to the cache replacement policy. Only one of either staleTime or
|
||||
* expirationTime may be set for a single cache record. When unset, the
|
||||
* value of this attribute is zero.
|
||||
*/
|
||||
attribute PRTime expirationTime;
|
||||
|
||||
/**
|
||||
* Date/time supplied by the protocol handler, at which point the content
|
||||
* is *likely* to be stale, i.e. the data in the cache may be out-of-date
|
||||
* with respect to the data on the server. This heuristic date does not
|
||||
* necessarily correspond to the HTTP Expires header, as it does not
|
||||
* determine when cached network data must be validated with the origin
|
||||
* server, but only serves as a hint to the cache replacement policy. Only
|
||||
* one of either staleTime or expirationTime may be set for a single cache
|
||||
* record. When unset, the value of this attribute is zero.
|
||||
*/
|
||||
attribute PRTime staleTime;
|
||||
|
||||
/**
|
||||
* Date/time of last access of the data in this cache record, as determined
|
||||
* by the cache manager.
|
||||
*/
|
||||
readonly attribute PRTime lastAccessTime;
|
||||
|
||||
/**
|
||||
* Number of times this record has been accessed since it was first stored.
|
||||
*/
|
||||
readonly attribute PRUint16 numberAccesses;
|
||||
|
||||
/**
|
||||
* Accessor methods for opaque meta-data which can be read and updated
|
||||
* independently of the content data.
|
||||
*
|
||||
* The aTag argument can be used to accommodate multiple clients of the
|
||||
* cache API, each of which wants to store its own private meta-data into
|
||||
* the cache. For example, there could be a "headers" tag that the HTTP
|
||||
* protocol handler uses to store http response headers and a "image size"
|
||||
* tag used to store the image dimensions of a GIF file. The aData
|
||||
* argument refers to an opaque blob of arbitrary bytes.
|
||||
*
|
||||
* IMPORTANT: If aData does not contain byte-oriented data, i.e. it's not a
|
||||
* string, the contents of aData must be byte-swapped by the,
|
||||
* caller, so as to make the cache files endian-independent.
|
||||
*/
|
||||
void getAnnotation(in string aTag,
|
||||
out PRUint32 aLength, [size_is(aLength), retval] out string aData);
|
||||
void setAnnotation(in string aTag,
|
||||
in PRUint32 aLength, [size_is(aLength)] in string aData);
|
||||
|
||||
/**
|
||||
* As a getter, return the number of content bytes stored in the cache,
|
||||
* i.e. via the nsIChannel streaming APIs. This may be less than the
|
||||
* complete content length if a partial cache fill occurred. The cached
|
||||
* content can be truncated by setting the value of this attribute. The
|
||||
* value of the attribute represents a logical, not a physical, length. If
|
||||
* compression has been used, the content may consume less storage than
|
||||
* indicated by this attribute.
|
||||
*
|
||||
* When this attribute is set to zero the associated cache disk file, if
|
||||
* any, should be deleted.
|
||||
*/
|
||||
attribute PRUint32 storedContentLength;
|
||||
|
||||
/**
|
||||
* Notify any observers associated with this cache entry of the deletion
|
||||
* request. If all observers drop their reference to the cache entry,
|
||||
* proceed to delete the underlying cache database record and associated
|
||||
* content storage.
|
||||
*/
|
||||
void delete();
|
||||
|
||||
/**
|
||||
* Flush any changes in this entry's data to the cache database. This
|
||||
* method will automatically be called when the last reference to the cache
|
||||
* is dropped, but it can also be called explicitly for a synchronous
|
||||
* effect.
|
||||
*/
|
||||
void commit();
|
||||
|
||||
/**
|
||||
* Parent container cache for this entry.
|
||||
*/
|
||||
readonly attribute nsINetDataCache cache;
|
||||
|
||||
/**
|
||||
* Create a channel for reading or writing a stream of content into the
|
||||
* entry. It is expected that many of the nsIChannel methods return
|
||||
* NS_NOT_IMPLEMENTED, including:
|
||||
*
|
||||
* + GetURI()
|
||||
* + GetContentType()
|
||||
* + GetContentLength()
|
||||
*
|
||||
* Though nsIChannel provides for both async and synchronous I/O APIs, both
|
||||
* may not be implemented. Only AsyncRead() and OpenOutputStream() is
|
||||
* required. The aProxyChannel argument allows another channel to be
|
||||
* specified as the proffered argument to nsIStreamListener methods rather
|
||||
* than the cache's own channel.
|
||||
*/
|
||||
nsIChannel newChannel(in nsILoadGroup aLoadGroup,
|
||||
in nsIChannel aProxyChannel);
|
||||
|
||||
/**
|
||||
* This method can be used by a caching protocol handler to store data in
|
||||
* the cache by forking an asynchronous read stream so that it is
|
||||
* simultaneously sent to a requester and written into the cache. This
|
||||
* method implicitly sets the updateInProgress flag, if it has not already
|
||||
* been set.
|
||||
*/
|
||||
nsIStreamListener interceptAsyncRead(in nsIStreamListener aOriginalListener,
|
||||
in PRUint32 aStartOffset);
|
||||
};
|
||||
143
mozilla/netwerk/cache/public/nsINetDataCache.idl
vendored
Normal file
143
mozilla/netwerk/cache/public/nsINetDataCache.idl
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIURI;
|
||||
interface nsINetDataCacheRecord;
|
||||
interface nsISimpleEnumerator;
|
||||
interface nsIFileSpec;
|
||||
|
||||
/**
|
||||
* The nsINetDataCache defines the low-level API for a network-data
|
||||
* cache, used to cache the responses to network retrieval commands.
|
||||
* This interface, along with nsINetDataCacheRecord, is implemented by
|
||||
* the memory cache, the file cache and, optionally, by some extension
|
||||
* caches. This interface is essentially a pseudo-private API for the
|
||||
* cache manager. Other clients should never use this interface.
|
||||
*
|
||||
* Each cache entry may contain both content, e.g. GIF image data, and
|
||||
* associated metadata, e.g. HTTP headers. Each entry is indexed by two
|
||||
* different keys: a record id number and a key created by combining the URI
|
||||
* with a "secondary key", e.g. HTTP post data.
|
||||
*
|
||||
* The nsINetDataCache interface is agnostic as to where the data is
|
||||
* stored and whether the storage is volatile or persistent. The
|
||||
* memory cache, any disk caches and any extension caches must all
|
||||
* implement this interface.
|
||||
*
|
||||
*/
|
||||
[scriptable, uuid(ccfc58c0-6dde-11d3-90c8-000064657374)]
|
||||
interface nsINetDataCache : nsISupports
|
||||
{
|
||||
/**
|
||||
* Human-readable description of the cache module, e.g. "Disk Cache"
|
||||
*/
|
||||
readonly attribute wstring description;
|
||||
|
||||
/**
|
||||
* Returns true if cached data is available for the given opaque key,
|
||||
* even if only partial data is stored.
|
||||
*/
|
||||
boolean contains([size_is(length)] in string key, in PRUint32 length);
|
||||
|
||||
/**
|
||||
* Fetch the cache entry record for the given opaque key. If one does not
|
||||
* exist, create a new, empty record.
|
||||
*/
|
||||
nsINetDataCacheRecord getCachedNetData([size_is(length)] in string key,
|
||||
in PRUint32 length);
|
||||
|
||||
/**
|
||||
* Fetch the cache entry record for the given URI using the record ID as a key.
|
||||
*/
|
||||
nsINetDataCacheRecord getCachedNetDataByID(in PRInt32 RecordID);
|
||||
|
||||
/**
|
||||
* False indicates that this cache is entirely bypassed.
|
||||
*/
|
||||
attribute boolean enabled;
|
||||
|
||||
/**
|
||||
* Constants for flags attribute, below
|
||||
*/
|
||||
|
||||
// Used for extension caches, e.g. a CD-ROM cache
|
||||
const long READ_ONLY = 1 << 0;
|
||||
|
||||
// One of these bits must be set
|
||||
const long MEMORY_CACHE = 1 << 1;
|
||||
const long FLAT_FILE_CACHE = 1 << 2;
|
||||
const long FILE_PER_URL_CACHE = 1 << 3;
|
||||
|
||||
/**
|
||||
* See constants defined above.
|
||||
*/
|
||||
readonly attribute PRUint32 flags;
|
||||
|
||||
/**
|
||||
* Total number of URI entries stored in the cache.
|
||||
*/
|
||||
readonly attribute PRUint32 numEntries;
|
||||
|
||||
/**
|
||||
* Maximum number of URI entries that may be stored in the cache.
|
||||
*/
|
||||
readonly attribute PRUint32 maxEntries;
|
||||
|
||||
/**
|
||||
* Enumerate the URI entries stored in the cache.
|
||||
*/
|
||||
nsISimpleEnumerator newCacheEntryIterator();
|
||||
|
||||
/**
|
||||
* Contains a reference to the next cache in search order. For the memory
|
||||
* cache, this attribute always references the disk cache. For the disk
|
||||
* cache, it contains a reference to the first extension cache.
|
||||
*/
|
||||
attribute nsINetDataCache nextCache;
|
||||
|
||||
/**
|
||||
* An estimate of the amount of storage occupied by the cache, in kB.
|
||||
* Actual use may be slightly higher than reported due to cache overhead
|
||||
* and heap fragmentation (in the memory cache) or block quantization (in
|
||||
* the disk cache).
|
||||
*/
|
||||
readonly attribute PRUint32 storageInUse;
|
||||
|
||||
/**
|
||||
* Remove all entries from a writable cache. This could be used, for
|
||||
* example, after a guest ends a browser session. This is equivalent to
|
||||
* setting the cache's Capacity to zero, except that all cache entries,
|
||||
* even those in active use, will be deleted. Also, any global cache
|
||||
* database files will be deleted.
|
||||
*/
|
||||
void removeAll();
|
||||
};
|
||||
|
||||
%{ C++
|
||||
// ProgID prefix for Components that implement this interface
|
||||
#define NS_NETWORK_CACHE_PROGID "component://netscape/network/cache"
|
||||
#define NS_NETWORK_MEMORY_CACHE_PROGID NS_NETWORK_CACHE_PROGID "?name=memory-cache"
|
||||
#define NS_NETWORK_FLAT_CACHE_PROGID NS_NETWORK_CACHE_PROGID "?name=flat-cache"
|
||||
#define NS_NETWORK_FILE_CACHE_PROGID NS_NETWORK_CACHE_PROGID "?name=file-cache"
|
||||
%}
|
||||
163
mozilla/netwerk/cache/public/nsINetDataCacheManager.idl
vendored
Normal file
163
mozilla/netwerk/cache/public/nsINetDataCacheManager.idl
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsISimpleEnumerator;
|
||||
interface nsICachedNetData;
|
||||
interface nsINetDataCache;
|
||||
interface nsINetDataDiskCache;
|
||||
interface nsIURI;
|
||||
interface nsIFileSpec;
|
||||
|
||||
/**
|
||||
* The network-response cache manager is partly responsible for the caching of
|
||||
* content and associated metadata that has been retrieved via the network.
|
||||
* (The remaining responsibility for caching lies with individual network
|
||||
* protocol handlers.)
|
||||
*
|
||||
* The cache manager supervises the actions of individual cache components,
|
||||
* such as the memory cache, the disk cache and any extension caches, e.g. a
|
||||
* read-only CD-ROM cache.
|
||||
*
|
||||
* @See nsINetDataCache
|
||||
* @See nsICachedNetData
|
||||
*/
|
||||
[scriptable, uuid(71c8ab00-6d5c-11d3-90c8-000064657374)]
|
||||
interface nsINetDataCacheManager : nsISupports
|
||||
{
|
||||
/**
|
||||
* Flag for the GetCachedNetData() method: If set, the memory cache is
|
||||
* neither searched nor will any data be stored into it. This might be
|
||||
* appropriate, for example, with images, because they have their own
|
||||
* cache for storing *decoded* images.
|
||||
*/
|
||||
const unsigned long BYPASS_MEMORY_CACHE = 1 << 0;
|
||||
|
||||
/**
|
||||
* Flag for the GetCachedNetData() method: If set, the disk cache
|
||||
* is neither searched nor will any be data stored into it.
|
||||
* However, read-only extension caches may be searched. This
|
||||
* might be used to avoid leaving persistent records of secure
|
||||
* data.
|
||||
*/
|
||||
const unsigned long BYPASS_PERSISTENT_CACHE = 1 << 1;
|
||||
|
||||
/**
|
||||
* Flag for the GetCachedNetData() method: If set, any stream
|
||||
* content is stored in the cache as a single disk file. Content
|
||||
* will not be cached in the memory cache nor is it cached in a
|
||||
* flat-file cache database. This is used to implement the jar
|
||||
* protocol handler and to provide the stream-as-file semantics
|
||||
* required by the classic bowser plugin API.
|
||||
*/
|
||||
const unsigned long CACHE_AS_FILE = 1 << 2;
|
||||
|
||||
/**
|
||||
* Fetch the cache entry record for the given URI. If one does not exist,
|
||||
* create a new, empty record. The normal search order for caches is:
|
||||
* + Memory cache
|
||||
* + Disk cache
|
||||
* + File cache (stream-as-file cache)
|
||||
* + All extension caches
|
||||
*
|
||||
* When writing, data is typically stored in both the memory cache and the
|
||||
* disk cache. Both the search order and this write policy can be modified by
|
||||
* setting one or more of the flag argument bits, as defined above.
|
||||
*
|
||||
* The optionally-NULL secondaryKey argument can be used, e.g. for form
|
||||
* post data or for HTTP headers in the case of HTTP.
|
||||
*/
|
||||
nsICachedNetData getCachedNetData(in string uri,
|
||||
[size_is(secondaryKeyLength)] in string secondaryKey,
|
||||
in PRUint32 secondaryKeyLength,
|
||||
in PRUint32 flags);
|
||||
|
||||
/**
|
||||
* Returns true if cached content is available for the given URI, even if
|
||||
* only partial data is stored. The flags argument behaves the same as for
|
||||
* the GetCachedNetData() method, above.
|
||||
*/
|
||||
boolean contains(in string uri,
|
||||
[size_is(secondaryKeyLength)] in string secondaryKey,
|
||||
in PRUint32 secondaryKeyLength,
|
||||
in PRUint32 flags);
|
||||
|
||||
/**
|
||||
* Total number of unexpired URI entries stored in all caches. This number
|
||||
* does not take into account duplicate URIs, e.g. because the memory cache
|
||||
* and the disk cache might each contain an entry for the same URI.
|
||||
*/
|
||||
readonly attribute PRUint32 numEntries;
|
||||
|
||||
/**
|
||||
* Enumerate the unexpired URI entries stored in all caches. Some URIs may
|
||||
* be enumerated more than once, e.g. because the the memory cache and the
|
||||
* disk cache might each contain an entry for the same URI.
|
||||
*/
|
||||
nsISimpleEnumerator newCacheEntryIterator();
|
||||
|
||||
/*
|
||||
* Enumerate all the loaded nsINetDataCache-implementing cache modules.
|
||||
* The first module enumerated will be the memory cache, the second will be
|
||||
* the disk cache, then the file cache, followed by all the extension
|
||||
* caches, in search order.
|
||||
*/
|
||||
nsISimpleEnumerator newCacheModuleIterator();
|
||||
|
||||
/**
|
||||
* Remove all entries from all writable caches. This could be used, for
|
||||
* example, after a guest ends a browser session. This is equivalent to
|
||||
* setting the DiskCacheCapacity to zero, except that all cache entries,
|
||||
* even those in active use, will be deleted. Also, any global cache
|
||||
* database files will be deleted.
|
||||
*/
|
||||
void RemoveAll();
|
||||
|
||||
/**
|
||||
* The disk cache is made up of the file cache (for stream-as-file
|
||||
* requests) and a (possibly independent) persistent cache that handles all
|
||||
* other cache requests. This attribute sets/gets the combined capacity of
|
||||
* these caches, measured in KBytes. Setting the capacity lower than the
|
||||
* current amount of space currently in use may cause cache entries to be
|
||||
* evicted from the cache to accomodate the requested capacity.
|
||||
*/
|
||||
attribute PRUint32 diskCacheCapacity;
|
||||
|
||||
/**
|
||||
* This attribute sets/gets the capacity of the memory cache, measured in
|
||||
* KBytes. Setting the capacity lower than the current amount of space
|
||||
* currently in use may cause cache entries to be evicted from the cache to
|
||||
* accomodate the requested capacity.
|
||||
*/
|
||||
attribute PRUint32 memCacheCapacity;
|
||||
|
||||
/**
|
||||
* This attribute must be set before attempting to store into the disk cache.
|
||||
*/
|
||||
attribute nsIFileSpec diskCacheFolder;
|
||||
};
|
||||
|
||||
%{ C++
|
||||
// ProgID prefix for Components that implement this interface
|
||||
#define NS_NETWORK_CACHE_MANAGER_PROGID NS_NETWORK_CACHE_PROGID "?name=manager"
|
||||
%}
|
||||
125
mozilla/netwerk/cache/public/nsINetDataCacheRecord.idl
vendored
Normal file
125
mozilla/netwerk/cache/public/nsINetDataCacheRecord.idl
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsrootidl.idl"
|
||||
|
||||
interface nsIFileSpec;
|
||||
interface nsIChannel;
|
||||
interface nsINetDataCache;
|
||||
|
||||
/**
|
||||
* The nsINetDataCacheRecord represents a single entry in a database that
|
||||
* caches data retrieved from the network. On top of this low-level interface
|
||||
* to the raw record data, the cache manager implements a higher-level record
|
||||
* interface, nsICachedNetData. Each instance of nsINetDataCacheRecord is
|
||||
* (internally) associated with a parent database, an instance of the
|
||||
* nsINetDataCache interface. This interface is essentially a pseudo-private
|
||||
* API for the cache manager. Other clients should never use this interface.
|
||||
*
|
||||
* Each cache record may contain both content and metadata. The content may
|
||||
* be, for example, GIF image data or HTML, and it is accessed through
|
||||
* nsIChannel's streaming API. The opaque metadata, which may contain HTTP
|
||||
* headers among other things, is accessed as a contiguous byte array. Each
|
||||
* entry in the cache is indexed by two different keys: a unique record id
|
||||
* number, generated by the cache, and an opaque string. The latter contains
|
||||
* the URI and other secondary key information, e.g. HTTP form post key/value
|
||||
* pairs.
|
||||
*
|
||||
* The nsINetDataCacheRecord interface is agnostic as to where the data is
|
||||
* stored and whether the storage is volatile or persistent. The memory cache,
|
||||
* the disk cache, a flat-file cache and any read-only extension caches must
|
||||
* all implement this interface.
|
||||
*
|
||||
* @See nsICachedNetData
|
||||
* @See nsINetDataCache
|
||||
* @See nsINetDataDiskCache
|
||||
* @See nsINetDataCacheManager
|
||||
*/
|
||||
|
||||
interface nsILoadGroup;
|
||||
|
||||
[scriptable, uuid(fdcdd6a0-7461-11d3-90ca-0040056a906e)]
|
||||
interface nsINetDataCacheRecord : nsISupports
|
||||
{
|
||||
/**
|
||||
* As far as the nsINetDataCacheRecord implementation is concerned, the
|
||||
* cache entry database key is an opaque blob, but it's intended to contain
|
||||
* both the URI and any secondary keys, such as HTTP post data.
|
||||
*/
|
||||
void getKey(out unsigned long length, [size_is(length), retval] out string key);
|
||||
|
||||
/**
|
||||
* A persistent record number assigned by the cache which must be unique
|
||||
* among all entries stored within the same cache. The record ID serves as
|
||||
* an alternate key to the cache record. Providing that they satisfy the
|
||||
* afforementioned uniqueness requirement, record IDs can be assigned any
|
||||
* value by the database except that they may never be zero.
|
||||
*/
|
||||
readonly attribute PRInt32 recordID;
|
||||
|
||||
/**
|
||||
* Opaque data which can be updated for each cache entry independently of
|
||||
* the content data. This data is a combination of protocol-independent
|
||||
* data provided by the cache manager and protocol-specific meta-data,
|
||||
* e.g. HTTP headers.
|
||||
*/
|
||||
void getMetaData(out PRUint32 length, [size_is(length), retval] out string metaData);
|
||||
void setMetaData(in PRUint32 length, [size_is(length)] in string data);
|
||||
|
||||
/**
|
||||
* Number of content bytes stored in the cache, i.e. via the nsIChannel
|
||||
* streaming APIs. This may be less than the complete content length if a
|
||||
* partial cache fill occurred. Additionally, the cached content can be
|
||||
* truncated by reducing the value of this attribute. When this attribute
|
||||
* is set to zero the associated cache disk file, if any, should be
|
||||
* deleted.
|
||||
*/
|
||||
attribute PRUint32 storedContentLength;
|
||||
|
||||
/**
|
||||
* Delete this cache entry and its associated content.
|
||||
*/
|
||||
void delete();
|
||||
|
||||
/**
|
||||
* Create a channel for reading or writing a stream of content into the
|
||||
* entry. However, many of the nsIChannel methods may return
|
||||
* NS_NOT_IMPLEMENTED, including:
|
||||
*
|
||||
* + GetURI()
|
||||
* + GetContentType()
|
||||
* + GetContentLength()
|
||||
*/
|
||||
nsIChannel newChannel(in nsILoadGroup loadGroup);
|
||||
|
||||
/**
|
||||
* If a cache is implemented such that it stores each URI's content in an
|
||||
* individual disk file, this method will identify the file corresponding
|
||||
* to this record. This may be used to implement the "stream-as-file"
|
||||
* semantics required by some plugins and by the 'jar:' protocol handler.
|
||||
* However, not all cache implementations are *required* to store the data
|
||||
* from each URI in an individual file, so it is acceptable for an
|
||||
* implementation of this method to signal NS_NOT_IMPLEMENTED.
|
||||
*/
|
||||
readonly attribute nsIFileSpec filename;
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
@@ -20,30 +20,23 @@
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsTextAreaWidget_h__
|
||||
#define nsTextAreaWidget_h__
|
||||
#include "nsINetDataCache.idl"
|
||||
|
||||
#include "nsTextHelper.h"
|
||||
#include "nsITextAreaWidget.h"
|
||||
interface nsIFileSpec;
|
||||
|
||||
/**
|
||||
* Native GTK+ multi-line edit control wrapper.
|
||||
/**
|
||||
* A network-data disk cache is used to persistently cache the responses to
|
||||
* network retrieval commands. Each cache entry may contain both content,
|
||||
* e.g. GIF image data, and associated metadata, e.g. HTTP headers.
|
||||
*/
|
||||
|
||||
class nsTextAreaWidget : public nsTextHelper
|
||||
[scriptable, uuid(6408e390-6f13-11d3-90c8-000064657374)]
|
||||
interface nsINetDataDiskCache : nsINetDataCache
|
||||
{
|
||||
|
||||
public:
|
||||
nsTextAreaWidget();
|
||||
virtual ~nsTextAreaWidget();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
virtual void SetFontNative(GdkFont *aFont);
|
||||
|
||||
protected:
|
||||
NS_METHOD CreateNative(GtkObject *parentWindow);
|
||||
/**
|
||||
* This attribute must be set before calling any other methods of this
|
||||
* interface.
|
||||
*/
|
||||
attribute nsIFileSpec diskCacheFolder;
|
||||
};
|
||||
|
||||
|
||||
#endif // nsTextAreaWidget_h__
|
||||
106
mozilla/netwerk/cache/public/nsIStreamAsFile.idl
vendored
Normal file
106
mozilla/netwerk/cache/public/nsIStreamAsFile.idl
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
#include "nsrootidl.idl"
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIFileSpec;
|
||||
interface nsIStreamAsFileObserver;
|
||||
|
||||
/**
|
||||
* In addition to enhancing effective network response time via caching, the
|
||||
* cache manager serves a second purpose by providing the stream-as-file
|
||||
* service required by traditional browser plugins and the jar: protocol
|
||||
* handler. The interface below provides a means for a client to determine the
|
||||
* filename associated with a stream and to detect modification/deletion of
|
||||
* that file.
|
||||
*/
|
||||
[scriptable, uuid(0eedbbf0-92d9-11d3-90d3-0040056a906e)]
|
||||
interface nsIStreamAsFile : nsISupports
|
||||
{
|
||||
/**
|
||||
* Filename containing stream-as-file
|
||||
*/
|
||||
readonly attribute nsIFileSpec fileSpec;
|
||||
|
||||
/**
|
||||
* Add an observer for this cache record. When the cache wants to delete
|
||||
* or truncate a record, so as to make space for another cache entry's
|
||||
* content data, it will call <code>aObserver</code>'s Observe() method,
|
||||
* passing the nsIStreamAsFile instance as the <code>aSubject</code>
|
||||
* argument and an appropriate message. If the observer does not wish to
|
||||
* inhibit deletion/truncation, it should Release() any references it has to the
|
||||
* cache record.
|
||||
*
|
||||
* @See nsIStreamAsFileObserver
|
||||
*/
|
||||
void addObserver(in nsIStreamAsFileObserver aObserver);
|
||||
|
||||
/**
|
||||
* Delete an observer that was added by the AddObserver() method.
|
||||
*/
|
||||
void removeObserver(in nsIStreamAsFileObserver aObserver);
|
||||
};
|
||||
|
||||
/**
|
||||
* This interface can be implemented by a client to receive notifications of
|
||||
* either modification or deletion of a file created by the cache manager using
|
||||
* the stream-as-file semantics.
|
||||
*/
|
||||
[scriptable, uuid(a26e27c0-92da-11d3-90d3-0040056a906e)]
|
||||
interface nsIStreamAsFileObserver : nsISupports
|
||||
{
|
||||
/**
|
||||
* Flag bits for argument to Observe() method.
|
||||
*/
|
||||
const long NOTIFY_AVAILABLE = 1 << 0; // Stream-as-file now available for reading
|
||||
const long NOTIFY_ERROR = 1 << 1; // Error while loading stream / creating file
|
||||
const long REQUEST_DELETION = 1 << 2; // Cache manager wishes to delete/truncate file
|
||||
const long INVALIDATE = 1 << 3; // File is out-of-date
|
||||
|
||||
// Convenience value
|
||||
const long MAKE_UNAVAILABLE = REQUEST_DELETION | INVALIDATE;
|
||||
|
||||
/**
|
||||
* Receive either a notification or a request concerning a file that has
|
||||
* been opened using stream-as-file. The aMessage and aError arguments
|
||||
* have varying values depending on the nature of the notification.
|
||||
* aMessage is set to NOTIFY_AVAILABLE when a complete stream has been read
|
||||
* and stored on disk in a file. At that point, and no sooner, may the
|
||||
* filename attribute of the associated nsIStreamAsFile be accessed via the
|
||||
* associated nsIStreamAsFile interface. If the aMessage argument is
|
||||
* NOTIFY_ERROR, the aError argument contains the relevant error code. If
|
||||
* the aMessage argument is either REQUEST_DELETION or REQUEST_TRUNCATION,
|
||||
* the callee should immediately Release() all references to the
|
||||
* nsIStreamAsFile (and any references to its associated nsICachedNetData
|
||||
* instances), unless it wishes to inhibit the requested file modification.
|
||||
* If the aMessage argument is INVALIDATE, the cache manager is replacing
|
||||
* the file with a more recent version. If a client wants to continue
|
||||
* using the (now out-of-date) file, it must delete it when it has finished,
|
||||
* as the cache manager will effectively relinquished ownership of the
|
||||
* file.
|
||||
*/
|
||||
void ObserveStreamAsFile(in nsIStreamAsFile aStreamAsFile,
|
||||
in PRUint32 aMessage,
|
||||
in nsresult aError);
|
||||
};
|
||||
39
mozilla/netwerk/makefile.win
Normal file
39
mozilla/netwerk/makefile.win
Normal file
@@ -0,0 +1,39 @@
|
||||
#!gmake
|
||||
#
|
||||
# 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 = ..
|
||||
|
||||
MODULE = necko
|
||||
|
||||
DIRS= \
|
||||
base \
|
||||
dns \
|
||||
build \
|
||||
protocol \
|
||||
socket \
|
||||
util \
|
||||
mime \
|
||||
streamconv \
|
||||
cache \
|
||||
test \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
@@ -1,4 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
@@ -20,22 +20,13 @@
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef __nsSound_h__
|
||||
#define __nsSound_h__
|
||||
|
||||
#include "nsISound.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
class nsSound : public nsISound {
|
||||
public:
|
||||
|
||||
nsSound();
|
||||
virtual ~nsSound();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISOUND
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIAtom;
|
||||
|
||||
[scriptable, uuid(a3ec67f0-465a-11d3-9a89-0080c7cb1080)]
|
||||
interface nsIHTTPHeader : nsISupports
|
||||
{
|
||||
nsIAtom GetField();
|
||||
string GetValue();
|
||||
};
|
||||
|
||||
#endif /* __nsSound_h__ */
|
||||
603
mozilla/netwerk/test/TestCacheMgr.cpp
Normal file
603
mozilla/netwerk/test/TestCacheMgr.cpp
Normal file
@@ -0,0 +1,603 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIStreamObserver.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIEventQueue.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsINetDataCacheManager.h"
|
||||
#include "nsICachedNetData.h"
|
||||
|
||||
|
||||
// Number of test entries to be placed in the cache
|
||||
// FIXME - temporary
|
||||
#define NUM_CACHE_ENTRIES 25
|
||||
|
||||
// Cache content stream length will have random length between zero and
|
||||
// MAX_CONTENT_LENGTH bytes
|
||||
#define MAX_CONTENT_LENGTH 20000
|
||||
|
||||
// Limits, converted to KB
|
||||
#define DISK_CACHE_CAPACITY ((MAX_CONTENT_LENGTH * 4) >> 10)
|
||||
#define MEM_CACHE_CAPACITY ((MAX_CONTENT_LENGTH * 3) >> 10)
|
||||
|
||||
// Length of random-data cache entry URI key
|
||||
#define CACHE_KEY_LENGTH 13
|
||||
|
||||
// Length of random-data cache entry secondary key
|
||||
#define CACHE_SECONDARY_KEY_LENGTH 10
|
||||
|
||||
// Length of random-data cache entry meta-data
|
||||
#define CACHE_PROTOCOL_PRIVATE_LENGTH 10
|
||||
|
||||
// Mapping from test case number to RecordID
|
||||
static PRInt32 recordID[NUM_CACHE_ENTRIES];
|
||||
|
||||
static PRInt32
|
||||
mapRecordIdToTestNum(PRInt32 aRecordID)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NUM_CACHE_ENTRIES; i++) {
|
||||
if (recordID[i] == aRecordID)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// A supply of stream data to either store or compare with
|
||||
class nsITestDataStream {
|
||||
public:
|
||||
virtual ~nsITestDataStream() {};
|
||||
virtual PRUint32 Next() = 0;
|
||||
virtual void Read(char* aBuf, PRUint32 aCount) = 0;
|
||||
virtual void ReadString(char* aBuf, PRUint32 aCount) = 0;
|
||||
|
||||
virtual PRBool Match(char* aBuf, PRUint32 aCount) = 0;
|
||||
virtual PRBool MatchString(char* aBuf, PRUint32 aCount) = 0;
|
||||
virtual void Skip(PRUint32 aCount) = 0;
|
||||
virtual void SkipString(PRUint32 aCount) = 0;
|
||||
};
|
||||
|
||||
// A reproducible stream of random data.
|
||||
class RandomStream : public nsITestDataStream {
|
||||
public:
|
||||
RandomStream(PRUint32 aSeed) {
|
||||
mStartSeed = mState = aSeed;
|
||||
}
|
||||
|
||||
PRUint32 GetStartSeed() {
|
||||
return mStartSeed;
|
||||
}
|
||||
|
||||
PRUint32 Next() {
|
||||
mState = 1103515245 * mState + 12345 ^ (mState >> 16);
|
||||
return mState;
|
||||
}
|
||||
|
||||
PRUint8 NextChar() {
|
||||
PRUint8 c;
|
||||
do {
|
||||
c = Next();
|
||||
} while (!isalnum(c));
|
||||
return c;
|
||||
}
|
||||
|
||||
void Read(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
*aBuf++ = Next();
|
||||
}
|
||||
}
|
||||
|
||||
// Same as Read(), but using only printable chars and
|
||||
// with a terminating NUL
|
||||
void ReadString(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
*aBuf++ = NextChar();
|
||||
}
|
||||
*aBuf = 0;
|
||||
}
|
||||
|
||||
PRBool
|
||||
Match(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
if (*aBuf++ != (char)(Next() & 0xff))
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
MatchString(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
if (*aBuf++ != (char)(NextChar() & 0xff))
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Check for terminating NUL character
|
||||
if (*aBuf)
|
||||
return PR_FALSE;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Skip(PRUint32 aCount) {
|
||||
while (aCount--)
|
||||
Next();
|
||||
}
|
||||
|
||||
void
|
||||
SkipString(PRUint32 aCount) {
|
||||
while (aCount--)
|
||||
NextChar();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mState;
|
||||
PRUint32 mStartSeed;
|
||||
};
|
||||
|
||||
static int gNumReaders = 0;
|
||||
static PRUint32 gTotalBytesRead = 0;
|
||||
static PRUint32 gTotalBytesWritten = 0;
|
||||
static PRUint32 gTotalDuration = 0;
|
||||
|
||||
class nsReader : public nsIStreamListener {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsReader()
|
||||
: mStartTime(0), mBytesRead(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
gNumReaders++;
|
||||
}
|
||||
|
||||
virtual ~nsReader() {
|
||||
delete mTestDataStream;
|
||||
gNumReaders--;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Init(nsITestDataStream* aRandomStream, PRUint32 aExpectedStreamLength) {
|
||||
mTestDataStream = aRandomStream;
|
||||
mExpectedStreamLength = aExpectedStreamLength;
|
||||
mRefCnt = 1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStartRequest(nsIChannel* channel,
|
||||
nsISupports* context) {
|
||||
mStartTime = PR_IntervalNow();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnDataAvailable(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsIInputStream *aIStream,
|
||||
PRUint32 aSourceOffset,
|
||||
PRUint32 aLength) {
|
||||
char buf[1025];
|
||||
while (aLength > 0) {
|
||||
PRUint32 amt;
|
||||
PRBool match;
|
||||
aIStream->Read(buf, sizeof buf, &amt);
|
||||
if (amt == 0) break;
|
||||
aLength -= amt;
|
||||
mBytesRead += amt;
|
||||
match = mTestDataStream->Match(buf, amt);
|
||||
NS_ASSERTION(match, "Stored data was corrupted on read");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStopRequest(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsresult aStatus,
|
||||
const PRUnichar* aMsg) {
|
||||
PRIntervalTime endTime;
|
||||
PRIntervalTime duration;
|
||||
|
||||
endTime = PR_IntervalNow();
|
||||
duration = (endTime - mStartTime);
|
||||
|
||||
if (NS_FAILED(aStatus)) printf("channel failed.\n");
|
||||
// printf("read %d bytes\n", mBytesRead);
|
||||
|
||||
//FIXME NS_ASSERTION(mBytesRead == mExpectedStreamLength,
|
||||
// "Stream in cache is wrong length");
|
||||
|
||||
gTotalBytesRead += mBytesRead;
|
||||
gTotalDuration += duration;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
PRIntervalTime mStartTime;
|
||||
PRUint32 mBytesRead;
|
||||
nsITestDataStream* mTestDataStream;
|
||||
PRUint32 mExpectedStreamLength;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsReader, nsIStreamListener, nsIStreamObserver)
|
||||
|
||||
static nsIEventQueue* eventQueue;
|
||||
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
|
||||
nsresult
|
||||
InitQueue() {
|
||||
nsresult rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue service");
|
||||
|
||||
rv = eventQService->CreateThreadEventQueue();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create event queue");
|
||||
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQueue);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue for main thread");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Process events until all streams are OnStopRequest'ed
|
||||
nsresult
|
||||
WaitForEvents() {
|
||||
while (gNumReaders) {
|
||||
eventQueue->ProcessPendingEvents();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Read data for a single cache record and compare against testDataStream
|
||||
nsresult
|
||||
TestReadStream(nsICachedNetData *cacheEntry, nsITestDataStream *testDataStream,
|
||||
PRUint32 expectedStreamLength)
|
||||
{
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsresult rv;
|
||||
PRUint32 actualContentLength;
|
||||
|
||||
rv = cacheEntry->NewChannel(0, 0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = cacheEntry->GetStoredContentLength(&actualContentLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
// FIXME NS_ASSERTION(actualContentLength == expectedStreamLength,
|
||||
// "nsICachedNetData::GetContentLength() busted ?");
|
||||
|
||||
nsReader *reader = new nsReader;
|
||||
reader->AddRef();
|
||||
rv = reader->Init(testDataStream, expectedStreamLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = channel->AsyncRead(0, -1, 0, reader);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
reader->Release();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Convert PRTime to unix-style time_t, i.e. seconds since the epoch
|
||||
static PRUint32
|
||||
convertPRTimeToSeconds(PRTime aTime64)
|
||||
{
|
||||
double fpTime;
|
||||
LL_L2D(fpTime, aTime64);
|
||||
return (PRUint32)(fpTime * 1e-6 + 0.5);
|
||||
}
|
||||
|
||||
// Convert unix-style time_t, i.e. seconds since the epoch, to PRTime
|
||||
static PRTime
|
||||
convertSecondsToPRTime(PRUint32 aSeconds)
|
||||
{
|
||||
PRInt64 t64;
|
||||
LL_L2I(t64, aSeconds);
|
||||
LL_MUL(t64, t64, 1000000);
|
||||
return t64;
|
||||
}
|
||||
|
||||
// Read the test data that was written in FillCache(), checking for
|
||||
// corruption, truncation.
|
||||
nsresult
|
||||
TestRead(nsINetDataCacheManager *aCache, PRUint32 aFlags)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inCache;
|
||||
nsCOMPtr<nsICachedNetData> cacheEntry;
|
||||
RandomStream *randomStream;
|
||||
char uriCacheKey[CACHE_KEY_LENGTH];
|
||||
char secondaryCacheKey[CACHE_SECONDARY_KEY_LENGTH];
|
||||
char *storedUriKey;
|
||||
PRUint32 testNum;
|
||||
|
||||
gTotalBytesRead = 0;
|
||||
gTotalDuration = 0;
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->ReadString(uriCacheKey, sizeof uriCacheKey - 1);
|
||||
randomStream->Read(secondaryCacheKey, sizeof secondaryCacheKey);
|
||||
|
||||
// Ensure that entry is in the cache
|
||||
rv = aCache->Contains(uriCacheKey,
|
||||
secondaryCacheKey, sizeof secondaryCacheKey,
|
||||
aFlags, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(inCache, "nsINetDataCacheManager::Contains error");
|
||||
|
||||
rv = aCache->GetCachedNetData(uriCacheKey,
|
||||
secondaryCacheKey, sizeof secondaryCacheKey,
|
||||
aFlags,
|
||||
getter_AddRefs(cacheEntry));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
// Test GetUriSpec() method
|
||||
rv = cacheEntry->GetUriSpec(&storedUriKey);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) &&
|
||||
!memcmp(storedUriKey, &uriCacheKey[0], sizeof uriCacheKey),
|
||||
"nsICachedNetData::GetKey failed");
|
||||
nsAllocator::Free(storedUriKey);
|
||||
|
||||
// Test GetSecondaryKey() method
|
||||
PRUint32 storedSecondaryKeyLength;
|
||||
char* storedSecondaryKey;
|
||||
rv = cacheEntry->GetSecondaryKey(&storedSecondaryKeyLength, &storedSecondaryKey);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) &&
|
||||
!memcmp(storedSecondaryKey, &secondaryCacheKey[0],
|
||||
sizeof secondaryCacheKey),
|
||||
"nsICachedNetData::GetSecondaryKey failed");
|
||||
|
||||
// Compare against stored protocol data
|
||||
char *storedProtocolData;
|
||||
PRUint32 storedProtocolDataLength;
|
||||
rv = cacheEntry->GetAnnotation("test data", &storedProtocolDataLength, &storedProtocolData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) &&
|
||||
storedProtocolDataLength == CACHE_PROTOCOL_PRIVATE_LENGTH,
|
||||
"nsICachedNetData::GetAnnotation() failed");
|
||||
randomStream->Match(storedProtocolData, storedProtocolDataLength);
|
||||
|
||||
// Test GetAllowPartial()
|
||||
PRBool allowPartial;
|
||||
rv = cacheEntry->GetAllowPartial(&allowPartial);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) &&
|
||||
(allowPartial == (PRBool)(randomStream->Next() & 1)),
|
||||
"nsICachedNetData::GetAllowPartial() failed");
|
||||
|
||||
// Test GetExpirationTime()
|
||||
PRTime expirationTime;
|
||||
PRTime expectedExpirationTime = convertSecondsToPRTime(randomStream->Next() & 0xffffff);
|
||||
rv = cacheEntry->GetExpirationTime(&expirationTime);
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) && LL_EQ(expirationTime, expectedExpirationTime),
|
||||
"nsICachedNetData::GetExpirationTime() failed");
|
||||
|
||||
PRUint32 expectedStreamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
|
||||
|
||||
TestReadStream(cacheEntry, randomStream, expectedStreamLength);
|
||||
}
|
||||
|
||||
WaitForEvents();
|
||||
|
||||
// Compute rate in MB/s
|
||||
double rate = gTotalBytesRead / PR_IntervalToMilliseconds(gTotalDuration);
|
||||
rate *= NUM_CACHE_ENTRIES;
|
||||
rate *= 1000;
|
||||
rate /= (1024 * 1024);
|
||||
printf("Read %7d bytes at a rate of %5.1f MB per second \n",
|
||||
gTotalBytesRead, rate);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Create entries in the network data cache, using random data for the
|
||||
// key, the meta-data and the stored content data.
|
||||
nsresult
|
||||
FillCache(nsINetDataCacheManager *aCache, PRUint32 aFlags, PRUint32 aCacheCapacity)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inCache;
|
||||
nsCOMPtr<nsICachedNetData> cacheEntry;
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsIOutputStream> outStream;
|
||||
nsCOMPtr<nsINetDataCache> containingCache;
|
||||
char buf[1000];
|
||||
PRUint32 protocolDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char secondaryCacheKey[CACHE_SECONDARY_KEY_LENGTH];
|
||||
char protocolData[CACHE_PROTOCOL_PRIVATE_LENGTH];
|
||||
PRUint32 testNum;
|
||||
RandomStream *randomStream;
|
||||
|
||||
gTotalBytesWritten = 0;
|
||||
PRIntervalTime startTime = PR_IntervalNow();
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->ReadString(cacheKey, sizeof cacheKey - 1);
|
||||
randomStream->Read(secondaryCacheKey, sizeof secondaryCacheKey);
|
||||
|
||||
// No entry should be in cache until we add it
|
||||
rv = aCache->Contains(cacheKey,
|
||||
secondaryCacheKey, sizeof secondaryCacheKey,
|
||||
aFlags, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(!inCache, "nsINetDataCacheManager::Contains error");
|
||||
|
||||
rv = aCache->GetCachedNetData(cacheKey,
|
||||
secondaryCacheKey, sizeof secondaryCacheKey,
|
||||
aFlags,
|
||||
getter_AddRefs(cacheEntry));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access cacheEntry via cache key");
|
||||
|
||||
// Test nsINetDataCacheManager::GetNumEntries()
|
||||
PRUint32 numEntries = (PRUint32)-1;
|
||||
rv = aCache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == testNum + 1, "GetNumEntries failure");
|
||||
|
||||
// Record meta-data should be initially empty
|
||||
char *protocolDatap;
|
||||
rv = cacheEntry->GetAnnotation("test data", &protocolDataLength, &protocolDatap);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
if ((protocolDataLength != 0) || (protocolDatap != 0))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Store random data as meta-data
|
||||
randomStream->Read(protocolData, sizeof protocolData);
|
||||
cacheEntry->SetAnnotation("test data", sizeof protocolData, protocolData);
|
||||
|
||||
// Store random data as allow-partial flag
|
||||
PRBool allowPartial = randomStream->Next() & 1;
|
||||
rv = cacheEntry->SetAllowPartial(allowPartial);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"nsICachedNetData::SetAllowPartial() failed");
|
||||
|
||||
// Store random data as expiration time
|
||||
PRTime expirationTime = convertSecondsToPRTime(randomStream->Next() & 0xffffff);
|
||||
rv = cacheEntry->SetExpirationTime(expirationTime);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"nsICachedNetData::SetExpirationTime() failed");
|
||||
|
||||
// Cache manager complains if expiration set without setting last-modified time
|
||||
rv = cacheEntry->SetLastModifiedTime(expirationTime);
|
||||
|
||||
rv = cacheEntry->NewChannel(0, 0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = cacheEntry->GetCache(getter_AddRefs(containingCache));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = channel->OpenOutputStream(0, getter_AddRefs(outStream));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
int streamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
|
||||
int remaining = streamLength;
|
||||
while (remaining) {
|
||||
PRUint32 numWritten;
|
||||
int amount = PR_MIN(sizeof buf, remaining);
|
||||
randomStream->Read(buf, amount);
|
||||
|
||||
rv = outStream->Write(buf, amount, &numWritten);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(numWritten == (PRUint32)amount, "Write() bug?");
|
||||
|
||||
remaining -= amount;
|
||||
|
||||
PRUint32 storageInUse;
|
||||
rv = containingCache->GetStorageInUse(&storageInUse);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) && (storageInUse <= aCacheCapacity),
|
||||
"Cache manager failed to limit cache growth");
|
||||
}
|
||||
outStream->Close();
|
||||
gTotalBytesWritten += streamLength;
|
||||
|
||||
// *Now* there should be an entry in the cache
|
||||
rv = aCache->Contains(cacheKey,
|
||||
secondaryCacheKey, sizeof secondaryCacheKey,
|
||||
aFlags, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(inCache, "nsINetDataCacheManager::Contains error");
|
||||
|
||||
delete randomStream;
|
||||
}
|
||||
|
||||
PRIntervalTime endTime = PR_IntervalNow();
|
||||
|
||||
// Compute rate in MB/s
|
||||
double rate = gTotalBytesWritten / PR_IntervalToMilliseconds(endTime - startTime);
|
||||
rate *= 1000;
|
||||
rate /= (1024 * 1024);
|
||||
printf("Wrote %7d bytes at a rate of %5.1f MB per second \n",
|
||||
gTotalBytesWritten, rate);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult NS_AutoregisterComponents()
|
||||
{
|
||||
nsresult rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup,
|
||||
NULL /* default */);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Test(nsINetDataCacheManager *aCache, PRUint32 aFlags, PRUint32 aCacheCapacity)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = aCache->RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
|
||||
|
||||
PRUint32 numEntries = (PRUint32)-1;
|
||||
rv = aCache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
|
||||
|
||||
rv = FillCache(aCache, aFlags, aCacheCapacity);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't fill cache with random test data");
|
||||
|
||||
rv = TestRead(aCache, aFlags);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't read random test data from cache");
|
||||
|
||||
rv = aCache->RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
|
||||
|
||||
rv = aCache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
|
||||
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheManager> cache;
|
||||
|
||||
rv = NS_AutoregisterComponents();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't register XPCOM components");
|
||||
|
||||
rv = nsComponentManager::CreateInstance(NS_NETWORK_CACHE_MANAGER_PROGID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsINetDataCacheManager),
|
||||
getter_AddRefs(cache));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create cache manager factory") ;
|
||||
|
||||
cache->SetDiskCacheCapacity(DISK_CACHE_CAPACITY);
|
||||
cache->SetMemCacheCapacity(MEM_CACHE_CAPACITY);
|
||||
|
||||
InitQueue();
|
||||
|
||||
Test(cache, nsINetDataCacheManager::BYPASS_PERSISTENT_CACHE, MEM_CACHE_CAPACITY);
|
||||
Test(cache, nsINetDataCacheManager::BYPASS_MEMORY_CACHE, DISK_CACHE_CAPACITY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
820
mozilla/netwerk/test/TestRawCache.cpp
Normal file
820
mozilla/netwerk/test/TestRawCache.cpp
Normal file
@@ -0,0 +1,820 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIStreamObserver.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIEventQueue.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsINetDataDiskCache.h"
|
||||
#include "nsINetDataCacheRecord.h"
|
||||
#include "nsMemCacheCID.h"
|
||||
// file cache include
|
||||
#include "nsNetDiskCacheCID.h"
|
||||
#include "nsIPref.h"
|
||||
#include "prenv.h"
|
||||
#include "nsIFileStream.h"
|
||||
|
||||
|
||||
// Number of test entries to be placed in the cache
|
||||
#define NUM_CACHE_ENTRIES 250
|
||||
|
||||
// Cache content stream length will have random length between zero and
|
||||
// MAX_CONTENT_LENGTH bytes
|
||||
#define MAX_CONTENT_LENGTH 20000
|
||||
|
||||
// Length of random-data cache entry key
|
||||
#define CACHE_KEY_LENGTH 15
|
||||
|
||||
// Length of random-data cache entry meta-data
|
||||
#define CACHE_METADATA_LENGTH 100
|
||||
|
||||
static NS_DEFINE_CID(kMemCacheCID, NS_MEM_CACHE_FACTORY_CID);
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
|
||||
// file cache cid
|
||||
static NS_DEFINE_CID(kDiskCacheCID, NS_NETDISKCACHE_CID) ;
|
||||
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
|
||||
static NS_DEFINE_IID(kIPrefIID, NS_IPREF_IID);
|
||||
|
||||
// Mapping from test case number to RecordID
|
||||
static PRInt32 recordID[NUM_CACHE_ENTRIES];
|
||||
|
||||
static PRInt32
|
||||
mapRecordIdToTestNum(PRInt32 aRecordID)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NUM_CACHE_ENTRIES; i++) {
|
||||
if (recordID[i] == aRecordID)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// A supply of stream data to either store or compare with
|
||||
class nsITestDataStream {
|
||||
public:
|
||||
virtual ~nsITestDataStream() {};
|
||||
virtual PRUint32 Next() = 0;
|
||||
virtual void Read(char* aBuf, PRUint32 aCount) = 0;
|
||||
|
||||
virtual PRBool Match(char* aBuf, PRUint32 aCount) = 0;
|
||||
virtual void Skip(PRUint32 aCount) = 0;
|
||||
};
|
||||
|
||||
// A reproducible stream of random data.
|
||||
class RandomStream : public nsITestDataStream {
|
||||
public:
|
||||
RandomStream(PRUint32 aSeed) {
|
||||
mStartSeed = mState = aSeed;
|
||||
}
|
||||
|
||||
PRUint32 GetStartSeed() {
|
||||
return mStartSeed;
|
||||
}
|
||||
|
||||
PRUint32 Next() {
|
||||
mState = 1103515245 * mState + 12345;
|
||||
return mState;
|
||||
}
|
||||
|
||||
void Read(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
*aBuf++ = Next();
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
Match(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
if (*aBuf++ != (char)(Next() & 0xff))
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Skip(PRUint32 aCount) {
|
||||
while (aCount--)
|
||||
Next();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mState;
|
||||
PRUint32 mStartSeed;
|
||||
};
|
||||
|
||||
// A stream of data that increments on each byte that is read, modulo 256
|
||||
class CounterStream : public nsITestDataStream {
|
||||
public:
|
||||
CounterStream(PRUint32 aSeed) {
|
||||
mStartSeed = mState = aSeed;
|
||||
}
|
||||
|
||||
PRUint32 GetStartSeed() {
|
||||
return mStartSeed;
|
||||
}
|
||||
|
||||
PRUint32 Next() {
|
||||
mState += 1;
|
||||
mState &= 0xff;
|
||||
return mState;
|
||||
}
|
||||
|
||||
void Read(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
*aBuf++ = Next();
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
Match(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
if (*aBuf++ != (char)Next())
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Skip(PRUint32 aCount) {
|
||||
mState += aCount;
|
||||
mState &= 0xff;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mState;
|
||||
PRUint32 mStartSeed;
|
||||
};
|
||||
|
||||
static int gNumReaders = 0;
|
||||
static PRUint32 gTotalBytesRead = 0;
|
||||
static PRUint32 gTotalDuration = 0;
|
||||
|
||||
class nsReader : public nsIStreamListener {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsReader()
|
||||
: mStartTime(0), mBytesRead(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
gNumReaders++;
|
||||
}
|
||||
|
||||
virtual ~nsReader() {
|
||||
delete mTestDataStream;
|
||||
gNumReaders--;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Init(nsITestDataStream* aRandomStream, PRUint32 aExpectedStreamLength) {
|
||||
mTestDataStream = aRandomStream;
|
||||
mExpectedStreamLength = aExpectedStreamLength;
|
||||
mRefCnt = 1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStartRequest(nsIChannel* channel,
|
||||
nsISupports* context) {
|
||||
mStartTime = PR_IntervalNow();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnDataAvailable(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsIInputStream *aIStream,
|
||||
PRUint32 aSourceOffset,
|
||||
PRUint32 aLength) {
|
||||
char buf[1025];
|
||||
while (aLength > 0) {
|
||||
PRUint32 amt;
|
||||
PRBool match;
|
||||
aIStream->Read(buf, sizeof buf, &amt);
|
||||
if (amt == 0) break;
|
||||
aLength -= amt;
|
||||
mBytesRead += amt;
|
||||
match = mTestDataStream->Match(buf, amt);
|
||||
NS_ASSERTION(match, "Stored data was corrupted on read");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStopRequest(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsresult aStatus,
|
||||
const PRUnichar* aMsg) {
|
||||
PRIntervalTime endTime;
|
||||
PRIntervalTime duration;
|
||||
|
||||
endTime = PR_IntervalNow();
|
||||
duration = (endTime - mStartTime);
|
||||
|
||||
if (NS_FAILED(aStatus)) printf("channel failed.\n");
|
||||
// printf("read %d bytes\n", mBytesRead);
|
||||
|
||||
NS_ASSERTION(mBytesRead == mExpectedStreamLength,
|
||||
"Stream in cache is wrong length");
|
||||
|
||||
gTotalBytesRead += mBytesRead;
|
||||
gTotalDuration += duration;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
PRIntervalTime mStartTime;
|
||||
PRUint32 mBytesRead;
|
||||
nsITestDataStream* mTestDataStream;
|
||||
PRUint32 mExpectedStreamLength;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsReader, nsIStreamListener, nsIStreamObserver)
|
||||
|
||||
static nsIEventQueue* eventQueue;
|
||||
|
||||
nsresult
|
||||
InitQueue() {
|
||||
nsresult rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue service");
|
||||
|
||||
rv = eventQService->CreateThreadEventQueue();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create event queue");
|
||||
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQueue);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue for main thread");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Process events until all streams are OnStopRequest'ed
|
||||
nsresult
|
||||
WaitForEvents() {
|
||||
while (gNumReaders) {
|
||||
eventQueue->ProcessPendingEvents();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Read data for a single cache record and compare against testDataStream
|
||||
nsresult
|
||||
TestReadStream(nsINetDataCacheRecord *record, nsITestDataStream *testDataStream,
|
||||
PRUint32 expectedStreamLength)
|
||||
{
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsresult rv;
|
||||
PRUint32 actualContentLength;
|
||||
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = record->GetStoredContentLength(&actualContentLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(actualContentLength == expectedStreamLength,
|
||||
"nsINetDataCacheRecord::GetContentLength() busted ?");
|
||||
|
||||
nsReader *reader = new nsReader;
|
||||
rv = reader->Init(testDataStream, expectedStreamLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = channel->AsyncRead(0, -1, 0, reader);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
reader->Release();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check that records can be retrieved using their record-ID, in addition
|
||||
// to using the opaque key.
|
||||
nsresult
|
||||
TestRecordID(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char *metaData;
|
||||
PRUint32 testNum;
|
||||
PRBool match;
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
rv = cache->GetCachedNetDataByID(recordID[testNum], getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't obtain record using record ID");
|
||||
|
||||
// Match against previously stored meta-data
|
||||
rv = record->GetMetaData(&metaDataLength, &metaData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
|
||||
match = randomStream->Match(metaData, metaDataLength);
|
||||
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
|
||||
|
||||
nsAllocator::Free(metaData);
|
||||
delete randomStream;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check that all cache entries in the database are enumerated and that
|
||||
// no duplicates appear.
|
||||
nsresult
|
||||
TestEnumeration(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCOMPtr<nsISupports> tempISupports;
|
||||
nsCOMPtr<nsISimpleEnumerator> iterator;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char *metaData;
|
||||
PRUint32 testNum;
|
||||
PRBool match;
|
||||
PRInt32 recID;
|
||||
|
||||
int numRecords = 0;
|
||||
|
||||
// Iterate over all records in the cache
|
||||
rv = cache->NewCacheEntryIterator(getter_AddRefs(iterator));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create new cache entry iterator");
|
||||
|
||||
PRBool notDone;
|
||||
while (1) {
|
||||
|
||||
// Done iterating ?
|
||||
rv = iterator->HasMoreElements(¬Done);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!notDone)
|
||||
break;
|
||||
|
||||
// Get next record in iteration
|
||||
rv = iterator->GetNext(getter_AddRefs(tempISupports));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "iterator bustage");
|
||||
record = do_QueryInterface(tempISupports);
|
||||
|
||||
numRecords++;
|
||||
|
||||
// Get record ID
|
||||
rv = record->GetRecordID(&recID);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
|
||||
testNum = mapRecordIdToTestNum(recID);
|
||||
NS_ASSERTION(testNum != -1, "Corrupted Record ID ?");
|
||||
|
||||
// Erase mapping from table, so that duplicate enumerations are detected
|
||||
recordID[testNum] = -1;
|
||||
|
||||
// Make sure stream matches test data
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
// Match against previously stored meta-data
|
||||
rv = record->GetMetaData(&metaDataLength, &metaData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
|
||||
match = randomStream->Match(metaData, metaDataLength);
|
||||
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
|
||||
nsAllocator::Free(metaData);
|
||||
|
||||
delete randomStream;
|
||||
}
|
||||
|
||||
NS_ASSERTION(numRecords == NUM_CACHE_ENTRIES, "Iteration bug");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Read the test data that was written in FillCache(), checking for
|
||||
// corruption, truncation.
|
||||
nsresult
|
||||
TestRead(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inCache;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char *metaData, *storedCacheKey;
|
||||
PRUint32 testNum, storedCacheKeyLength;
|
||||
PRBool match;
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
// Ensure that entry is in the cache
|
||||
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
// Match against previously stored meta-data
|
||||
match = record->GetMetaData(&metaDataLength, &metaData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
match = randomStream->Match(metaData, metaDataLength);
|
||||
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
|
||||
nsAllocator::Free(metaData);
|
||||
|
||||
// Test GetKey() method
|
||||
rv = record->GetKey(&storedCacheKeyLength, &storedCacheKey);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) &&
|
||||
(storedCacheKeyLength == sizeof cacheKey) &&
|
||||
!memcmp(storedCacheKey, &cacheKey[0], sizeof cacheKey),
|
||||
"nsINetDataCacheRecord::GetKey failed");
|
||||
nsAllocator::Free(storedCacheKey);
|
||||
|
||||
PRUint32 expectedStreamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
|
||||
|
||||
TestReadStream(record, randomStream, expectedStreamLength);
|
||||
}
|
||||
|
||||
WaitForEvents();
|
||||
|
||||
// Compute rate in MB/s
|
||||
double rate = gTotalBytesRead / PR_IntervalToMilliseconds(gTotalDuration);
|
||||
rate *= NUM_CACHE_ENTRIES;
|
||||
rate *= 1000;
|
||||
rate /= (1024 * 1024);
|
||||
printf("Read %d bytes at a rate of %5.1f MB per second \n",
|
||||
gTotalBytesRead, rate);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Repeatedly call SetStoredContentLength() on a cache entry and make
|
||||
// read the stream's data to ensure that it's not corrupted by the effect
|
||||
nsresult
|
||||
TestTruncation(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
RandomStream *randomStream;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
|
||||
randomStream = new RandomStream(0);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
randomStream->Skip(CACHE_METADATA_LENGTH);
|
||||
PRUint32 initialStreamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
|
||||
delete randomStream;
|
||||
|
||||
PRUint32 i;
|
||||
PRUint32 delta = initialStreamLength / 64;
|
||||
for (i = initialStreamLength; i >= delta; i -= delta) {
|
||||
PRUint32 expectedStreamLength = i;
|
||||
|
||||
// Do the truncation
|
||||
record->SetStoredContentLength(expectedStreamLength);
|
||||
randomStream = new RandomStream(0);
|
||||
randomStream->Skip(CACHE_KEY_LENGTH + CACHE_METADATA_LENGTH + 1);
|
||||
|
||||
PRUint32 afterContentLength;
|
||||
rv = record->GetStoredContentLength(&afterContentLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
NS_ASSERTION(afterContentLength == expectedStreamLength,
|
||||
"nsINetDataCacheRecord::SetContentLength() failed to truncate record");
|
||||
|
||||
TestReadStream(record, randomStream, expectedStreamLength);
|
||||
WaitForEvents();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Write known data to random offsets in a single cache entry and test
|
||||
// resulting stream for correctness.
|
||||
nsresult
|
||||
TestOffsetWrites(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsIOutputStream> outStream;
|
||||
char buf[512];
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
RandomStream *randomStream;
|
||||
|
||||
randomStream = new RandomStream(0);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
|
||||
|
||||
|
||||
// Write buffer-fulls of data at random offsets into the cache entry.
|
||||
// Data written is (offset % 0xff)
|
||||
PRUint32 startingOffset;
|
||||
PRUint32 streamLength = 0;
|
||||
CounterStream *counterStream;
|
||||
int i;
|
||||
for (i = 0; i < 100; i++) {
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
startingOffset = streamLength ? streamLength - (randomStream->Next() % sizeof buf): 0;
|
||||
rv = channel->OpenOutputStream(startingOffset, getter_AddRefs(outStream));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
counterStream = new CounterStream(startingOffset);
|
||||
counterStream->Read(buf, sizeof buf);
|
||||
|
||||
PRUint32 numWritten;
|
||||
rv = outStream->Write(buf, sizeof buf, &numWritten);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(numWritten == sizeof buf, "Write() bug?");
|
||||
streamLength = startingOffset + sizeof buf;
|
||||
|
||||
rv = outStream->Close();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't close channel");
|
||||
delete counterStream;
|
||||
}
|
||||
|
||||
delete randomStream;
|
||||
|
||||
counterStream = new CounterStream(0);
|
||||
TestReadStream(record, counterStream, streamLength);
|
||||
WaitForEvents();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Create entries in the network data cache, using random data for the
|
||||
// key, the meta-data and the stored content data.
|
||||
nsresult
|
||||
FillCache(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inCache;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsIOutputStream> outStream;
|
||||
char buf[1000];
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char metaData[CACHE_METADATA_LENGTH];
|
||||
PRUint32 testNum;
|
||||
char *data;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 totalBytesWritten = 0;
|
||||
|
||||
PRIntervalTime startTime = PR_IntervalNow();
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
// No entry should be in cache until we add it
|
||||
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(!inCache, "nsINetDataCache::Contains error");
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
|
||||
|
||||
// Test nsINetDataCacheRecord::GetRecordID()
|
||||
rv = record->GetRecordID(&recordID[testNum]);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
|
||||
|
||||
// Test nsINetDataCache::GetNumEntries()
|
||||
PRUint32 numEntries = (PRUint32)-1;
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == testNum + 1, "GetNumEntries failure");
|
||||
|
||||
// Record meta-data should be initially empty
|
||||
rv = record->GetMetaData(&metaDataLength, &data);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
if ((metaDataLength != 0) || (data != 0))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Store random data as meta-data
|
||||
randomStream->Read(metaData, sizeof metaData);
|
||||
record->SetMetaData(sizeof metaData, metaData);
|
||||
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = channel->OpenOutputStream(0, getter_AddRefs(outStream));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
PRUint32 beforeOccupancy;
|
||||
rv = cache->GetStorageInUse(&beforeOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
|
||||
int streamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
|
||||
int remaining = streamLength;
|
||||
while (remaining) {
|
||||
PRUint32 numWritten;
|
||||
int amount = PR_MIN(sizeof buf, remaining);
|
||||
randomStream->Read(buf, amount);
|
||||
|
||||
rv = outStream->Write(buf, amount, &numWritten);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(numWritten == (PRUint32)amount, "Write() bug?");
|
||||
|
||||
remaining -= amount;
|
||||
}
|
||||
outStream->Close();
|
||||
totalBytesWritten += streamLength;
|
||||
|
||||
PRUint32 afterOccupancy;
|
||||
rv = cache->GetStorageInUse(&afterOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
PRUint32 streamLengthInKB = streamLength >> 10;
|
||||
NS_ASSERTION((afterOccupancy - beforeOccupancy) >= streamLengthInKB,
|
||||
"nsINetDataCache::GetStorageInUse() is busted");
|
||||
|
||||
|
||||
// *Now* there should be an entry in the cache
|
||||
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
|
||||
|
||||
delete randomStream;
|
||||
}
|
||||
|
||||
PRIntervalTime endTime = PR_IntervalNow();
|
||||
|
||||
// Compute rate in MB/s
|
||||
double rate = totalBytesWritten / PR_IntervalToMilliseconds(endTime - startTime);
|
||||
rate *= 1000;
|
||||
rate /= (1024 * 1024);
|
||||
printf("Wrote %7d bytes at a rate of %5.1f MB per second \n",
|
||||
totalBytesWritten, rate);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult NS_AutoregisterComponents()
|
||||
{
|
||||
nsresult rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup,
|
||||
NULL /* default */);
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRBool initPref ()
|
||||
{
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIPref, prefPtr, kPrefCID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
nsCOMPtr<nsIFileSpec> fileSpec;
|
||||
rv = NS_NewFileSpec (getter_AddRefs(fileSpec));
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
nsCString defaultPrefFile = PR_GetEnv ("MOZILLA_FIVE_HOME");
|
||||
if (defaultPrefFile.Length())
|
||||
defaultPrefFile += "/";
|
||||
else
|
||||
defaultPrefFile = "./";
|
||||
defaultPrefFile += "default_prefs.js";
|
||||
|
||||
fileSpec->SetUnixStyleFilePath (defaultPrefFile.GetBuffer());
|
||||
|
||||
PRBool exists = false;
|
||||
fileSpec->Exists(&exists);
|
||||
if (exists)
|
||||
prefPtr->ReadUserPrefsFrom(fileSpec);
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if(argc <2) {
|
||||
printf(" %s -f to test filecache\n", argv[0]) ;
|
||||
printf(" %s -m to test memcache\n", argv[0]) ;
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
|
||||
rv = NS_AutoregisterComponents();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't register XPCOM components");
|
||||
|
||||
nsCOMPtr<nsINetDataCache> cache;
|
||||
|
||||
if (PL_strcasecmp(argv[1], "-m") == 0) {
|
||||
rv = nsComponentManager::CreateInstance(kMemCacheCID, nsnull,
|
||||
NS_GET_IID(nsINetDataCache),
|
||||
getter_AddRefs(cache));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create memory cache factory");
|
||||
} else if (PL_strcasecmp(argv[1], "-f") == 0) {
|
||||
|
||||
nsCOMPtr<nsINetDataDiskCache> diskcache ;
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kDiskCacheCID, nsnull,
|
||||
NS_GET_IID(nsINetDataDiskCache),
|
||||
getter_AddRefs(diskcache));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create disk cache factory") ;
|
||||
|
||||
nsCOMPtr<nsIFileSpec> folder ;
|
||||
NS_NewFileSpec(getter_AddRefs(folder)) ;
|
||||
folder->SetUnixStyleFilePath("/tmp") ;
|
||||
diskcache->SetDiskCacheFolder(folder) ;
|
||||
|
||||
cache = diskcache ;
|
||||
|
||||
} else {
|
||||
printf(" %s -f to test filecache\n", argv[0]) ;
|
||||
printf(" %s -m to test memcache\n", argv[0]) ;
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
InitQueue();
|
||||
|
||||
PRUnichar* description;
|
||||
rv = cache->GetDescription(&description);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache description");
|
||||
nsCAutoString descStr(description);
|
||||
printf("Testing: %s\n", descStr.GetBuffer());
|
||||
|
||||
rv = cache->RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
|
||||
|
||||
PRUint32 startOccupancy;
|
||||
rv = cache->GetStorageInUse(&startOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
|
||||
PRUint32 numEntries = (PRUint32)-1;
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
|
||||
|
||||
rv = FillCache(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't fill cache with random test data");
|
||||
|
||||
rv = TestRead(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't read random test data from cache");
|
||||
|
||||
rv = TestRecordID(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't index records using record ID");
|
||||
|
||||
rv = TestEnumeration(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully enumerate records");
|
||||
|
||||
rv = TestTruncation(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully truncate records");
|
||||
|
||||
rv = TestOffsetWrites(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully write to records using non-zero offsets");
|
||||
|
||||
rv = cache->RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
|
||||
|
||||
PRUint32 endOccupancy;
|
||||
rv = cache->GetStorageInUse(&endOccupancy);
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
|
||||
NS_ASSERTION(startOccupancy == endOccupancy, "Cache occupancy not correctly computed ?");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
82
mozilla/netwerk/test/makefile.win
Normal file
82
mozilla/netwerk/test/makefile.win
Normal file
@@ -0,0 +1,82 @@
|
||||
#!nmake
|
||||
#
|
||||
# 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=..\..
|
||||
|
||||
MAKE_OBJ_TYPE = EXE
|
||||
PROG1 = .\$(OBJDIR)\TestFileInput.exe
|
||||
PROG2 = .\$(OBJDIR)\TestSocketInput.exe
|
||||
PROG3 = .\$(OBJDIR)\TestSocketIO.exe
|
||||
PROG4 = .\$(OBJDIR)\TestProtocols.exe
|
||||
PROG5 = .\$(OBJDIR)\TestSocketTransport.exe
|
||||
PROG6 = .\$(OBJDIR)\urltest.exe
|
||||
PROG7 = .\$(OBJDIR)\TestFileInput2.exe
|
||||
PROG8 = .\$(OBJDIR)\TestFileTransport.exe
|
||||
PROG9 = .\$(OBJDIR)\TestRes.exe
|
||||
PROGA = .\$(OBJDIR)\TestRawCache.exe
|
||||
PROGB = .\$(OBJDIR)\TestCacheMgr.exe
|
||||
PROGRAMS = \
|
||||
#$(PROG1) $(PROG2) $(PROG3) $(PROG4) $(PROG5) $(PROG6) $(PROG7) $(PROG8) $(PROG9)\
|
||||
$(PROGA) $(PROGB)
|
||||
|
||||
LCFLAGS=-DUSE_NSREG -GX
|
||||
|
||||
REQUIRES=libreg
|
||||
|
||||
INCS = $(INCS) \
|
||||
-I$(DEPTH)\dist\include \
|
||||
$(NULL)
|
||||
|
||||
LLIBS= \
|
||||
$(DIST)\lib\xpcom.lib \
|
||||
$(LIBNSPR) \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
install:: $(PROGRAMS)
|
||||
-for %p in ($(PROGRAMS)) do $(MAKE_INSTALL) %p $(DIST)\bin
|
||||
|
||||
clobber::
|
||||
-for %p in ($(PROGRAMS)) do $(RM) %p $(DIST)\bin\%p
|
||||
|
||||
$(PROG1): $(OBJDIR) TestFileInput.cpp
|
||||
|
||||
$(PROG2): $(OBJDIR) TestSocketInput.cpp
|
||||
|
||||
$(PROG3): $(OBJDIR) TestSocketIO.cpp
|
||||
|
||||
$(PROG4): $(OBJDIR) TestProtocols.cpp
|
||||
|
||||
$(PROG5): $(OBJDIR) TestSocketTransport.cpp
|
||||
|
||||
$(PROG6): $(OBJDIR) urltest.cpp
|
||||
|
||||
$(PROG7): $(OBJDIR) TestFileInput2.cpp
|
||||
|
||||
$(PROG8): $(OBJDIR) TestFileTransport.cpp
|
||||
|
||||
$(PROG9): $(OBJDIR) TestRes.cpp
|
||||
|
||||
$(PROGA): $(OBJDIR) TestRawCache.cpp
|
||||
|
||||
$(PROGB): $(OBJDIR) TestCacheMgr.cpp
|
||||
|
||||
1857
mozilla/string/obsolete/nsString.cpp
Normal file
1857
mozilla/string/obsolete/nsString.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,197 +0,0 @@
|
||||
#
|
||||
# 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
|
||||
|
||||
DIRS = public
|
||||
|
||||
PROGRAM = viewer
|
||||
|
||||
CPPSRCS = \
|
||||
$(TOOLKIT_CPPSRCS) \
|
||||
nsBaseDialog.cpp \
|
||||
nsFindDialog.cpp \
|
||||
nsXPBaseWindow.cpp \
|
||||
nsTableInspectorDialog.cpp \
|
||||
nsImageInspectorDialog.cpp \
|
||||
nsPrintSetupDialog.cpp \
|
||||
nsBrowserWindow.cpp \
|
||||
nsEditorMode.cpp \
|
||||
nsSetupRegistry.cpp \
|
||||
nsThrobber.cpp \
|
||||
nsViewerApp.cpp \
|
||||
nsWebCrawler.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORT_RESOURCE_SAMPLES := \
|
||||
$(wildcard $(srcdir)/samples/test*.html) \
|
||||
$(wildcard $(srcdir)/samples/toolbarTest*.xul) \
|
||||
$(wildcard $(srcdir)/samples/treeTest*.xul) \
|
||||
$(wildcard $(srcdir)/samples/treeTest*.css) \
|
||||
$(wildcard $(srcdir)/samples/slider*.xul) \
|
||||
$(wildcard $(srcdir)/samples/scrollbar*.xul) \
|
||||
$(srcdir)/resources/find.html \
|
||||
$(srcdir)/resources/printsetup.html \
|
||||
$(srcdir)/resources/image_props.html \
|
||||
$(srcdir)/samples/aform.css \
|
||||
$(srcdir)/samples/bform.css \
|
||||
$(srcdir)/samples/cform.css \
|
||||
$(srcdir)/samples/demoform.css \
|
||||
$(srcdir)/samples/mozform.css \
|
||||
$(srcdir)/samples/xulTest.css \
|
||||
$(srcdir)/samples/Anieyes.gif \
|
||||
$(srcdir)/samples/gear1.gif \
|
||||
$(srcdir)/samples/rock_gra.gif \
|
||||
$(srcdir)/samples/beeptest.html \
|
||||
$(srcdir)/samples/soundtest.html \
|
||||
$(srcdir)/samples/bg.jpg \
|
||||
$(srcdir)/samples/raptor.jpg \
|
||||
$(srcdir)/samples/test.wav \
|
||||
$(srcdir)/samples/checkboxTest.xul \
|
||||
$(NULL)
|
||||
|
||||
EXPORT_RESOURCE_THROBBER := $(wildcard $(srcdir)/throbber/anim*.gif)
|
||||
|
||||
ifeq (,$(filter beos os2 rhapsody photon,$(MOZ_WIDGET_TOOLKIT)))
|
||||
DIRS += unix
|
||||
UNIX_VIEWER_TK_LIBS = $(DIST)/lib/libviewer_$(MOZ_WIDGET_TOOLKIT)_s.a
|
||||
else
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),beos)
|
||||
BEOS_PROGRAM_RESOURCE = $(srcdir)/viewer-beos.rsrc
|
||||
TOOLKIT_CPPSRCS = nsBeOSMain.cpp
|
||||
endif
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),photon)
|
||||
TOOLKIT_CPPSRCS = nsPhMain.cpp nsPhMenu.cpp
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk)
|
||||
GTK_GLUE = -lgtksuperwin
|
||||
endif
|
||||
|
||||
ifdef MOZ_OJI
|
||||
JSJ_LIB = -ljsj
|
||||
endif
|
||||
|
||||
XP_DIST_LIBS = \
|
||||
-lraptorgfx \
|
||||
-lmozjs \
|
||||
-lxpcom \
|
||||
$(JSJ_LIB) \
|
||||
$(NULL)
|
||||
|
||||
XP_NS_UNDERBAR_CRAP = \
|
||||
$(MOZ_NECKO_UTIL_LIBS) \
|
||||
$(MOZ_TIMER_LIBS) \
|
||||
$(MOZ_WIDGET_SUPPORT_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
XP_LIBS = \
|
||||
$(XP_NS_UNDERBAR_CRAP) \
|
||||
$(XP_DIST_LIBS) \
|
||||
$(NSPR_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_FULLCIRCLE
|
||||
XP_LIBS += $(FULLCIRCLE_LIBS)
|
||||
endif
|
||||
|
||||
LIBS = \
|
||||
$(UNIX_VIEWER_TK_LIBS) \
|
||||
$(GTK_GLUE) \
|
||||
$(XP_LIBS) \
|
||||
$(TK_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
MOTIF_LIBS = -lviewer_motif_s $(XP_LIBS) $(MOZ_MOTIF_LDFLAGS)
|
||||
QT_LIBS = -lviewer_qt_s $(XP_LIBS) $(MOZ_QT_LDFLAGS)
|
||||
XLIB_LIBS = -lviewer_xlib_s $(XP_LIBS) $(MOZ_XLIB_LDFLAGS)
|
||||
GTK_LIBS = -lviewer_gtk_s -lgtksuperwin $(XP_LIBS) $(MOZ_GTK_LDFLAGS)
|
||||
|
||||
EXTRA_DEPS = \
|
||||
$(addprefix $(DIST)/,$(patsubst -l%,bin/lib%.$(DLL_SUFFIX),$(XP_DIST_LIBS:-l%_s=lib/lib%_s.a))) \
|
||||
$(UNIX_VIEWER_TK_LIBS) \
|
||||
$(XP_NS_UNDERBAR_CRAP) \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
CXXFLAGS += $(MOZ_TOOLKIT_REGISTRY_CFLAGS)
|
||||
|
||||
install:: $(PROGRAM) $(srcdir)/mozilla-viewer.sh
|
||||
$(INSTALL) $(EXPORT_RESOURCE_SAMPLES) $(DIST)/bin/res/samples
|
||||
$(INSTALL) $(EXPORT_RESOURCE_THROBBER) $(DIST)/bin/res/throbber
|
||||
$(INSTALL) $(srcdir)/resources/viewer.properties $(DIST)/bin/res
|
||||
$(INSTALL) $(srcdir)/mozilla-viewer.sh $(DIST)/bin
|
||||
|
||||
$(PROGRAM)_gtk: $(PROGOBJS) $(EXTRA_DEPS) Makefile Makefile.in $(DIST)/lib/libviewer_gtk_s.a
|
||||
$(CCC) -o $@ $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(GTK_LIBS) $(OS_LIBS)
|
||||
$(MOZ_POST_PROGRAM_COMMAND) $@
|
||||
|
||||
$(PROGRAM)_motif: $(PROGOBJS) $(EXTRA_DEPS) Makefile Makefile.in $(DIST)/lib/libviewer_motif_s.a
|
||||
$(CCC) -o $@ $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(MOTIF_LIBS) $(OS_LIBS)
|
||||
$(MOZ_POST_PROGRAM_COMMAND) $@
|
||||
|
||||
$(PROGRAM)_qt: $(PROGOBJS) $(EXTRA_DEPS) Makefile Makefile.in $(DIST)/lib/libviewer_qt_s.a
|
||||
$(CCC) -o $@ $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(QT_LIBS) $(OS_LIBS)
|
||||
$(MOZ_POST_PROGRAM_COMMAND) $@
|
||||
|
||||
$(PROGRAM)_xlib: $(PROGOBJS) $(EXTRA_DEPS) Makefile Makefile.in $(DIST)/lib/libviewer_xlib_s.a
|
||||
$(CCC) -o $@ $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(XLIB_LIBS) $(OS_LIBS)
|
||||
$(MOZ_POST_PROGRAM_COMMAND) $@
|
||||
|
||||
ifdef MOZ_ENABLE_GTK
|
||||
install:: $(PROGRAM)_gtk
|
||||
$(INSTALL) -m 555 $< $(DIST)/bin
|
||||
|
||||
clobber::
|
||||
rm -f $(PROGRAM)_gtk
|
||||
endif
|
||||
|
||||
ifdef MOZ_ENABLE_MOTIF
|
||||
install:: $(PROGRAM)_motif
|
||||
$(INSTALL) -m 555 $< $(DIST)/bin
|
||||
|
||||
clobber::
|
||||
rm -f $(PROGRAM)_motif
|
||||
endif
|
||||
|
||||
ifdef MOZ_ENABLE_QT
|
||||
install:: $(PROGRAM)_qt
|
||||
$(INSTALL) -m 555 $< $(DIST)/bin
|
||||
|
||||
clobber::
|
||||
rm -f $(PROGRAM)_qt
|
||||
endif
|
||||
|
||||
ifdef MOZ_ENABLE_XLIB
|
||||
install:: $(PROGRAM)_xlib
|
||||
$(INSTALL) -m 555 $< $(DIST)/bin
|
||||
|
||||
clobber::
|
||||
rm -f $(PROGRAM)_xlib
|
||||
endif
|
||||
|
||||
@@ -1,179 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "gdksuperwin.h"
|
||||
#include "gtkmozbox.h"
|
||||
|
||||
#include "nsBrowserWindow.h"
|
||||
#include "resources.h"
|
||||
#include "nscore.h"
|
||||
|
||||
#include "stdio.h"
|
||||
|
||||
typedef GtkItemFactoryCallback GIFC;
|
||||
|
||||
void gtk_ifactory_cb (nsBrowserWindow *nbw,
|
||||
guint callback_action,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
nbw->DispatchMenuItem(callback_action);
|
||||
}
|
||||
|
||||
GtkItemFactoryEntry menu_items[] =
|
||||
{
|
||||
{ "/_File", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/File/_New Window", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_WINDOW_OPEN, nsnull },
|
||||
{ "/File/_Open...", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_FILE_OPEN, nsnull },
|
||||
{ "/File/_View Source", nsnull, (GIFC)gtk_ifactory_cb, VIEW_SOURCE, nsnull },
|
||||
{ "/File/_Samples", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/File/Samples/demo #0", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO0, nsnull },
|
||||
{ "/File/Samples/demo #1", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO1, nsnull },
|
||||
{ "/File/Samples/demo #2", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO2, nsnull },
|
||||
{ "/File/Samples/demo #3", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO3, nsnull },
|
||||
{ "/File/Samples/demo #4", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO4, nsnull },
|
||||
{ "/File/Samples/demo #5", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO5, nsnull },
|
||||
{ "/File/Samples/demo #6", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO6, nsnull },
|
||||
{ "/File/Samples/demo #7", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO7, nsnull },
|
||||
{ "/File/Samples/demo #8", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO8, nsnull },
|
||||
{ "/File/Samples/demo #9", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO9, nsnull },
|
||||
{ "/File/Samples/demo #10", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO10, nsnull },
|
||||
{ "/File/Samples/demo #11", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO11, nsnull },
|
||||
{ "/File/Samples/demo #12", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO12, nsnull },
|
||||
{ "/File/Samples/demo #13", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO13, nsnull },
|
||||
{ "/File/Samples/demo #14", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO14, nsnull },
|
||||
{ "/File/Samples/demo #15", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO15, nsnull },
|
||||
{ "/File/Samples/demo #16", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO16, nsnull },
|
||||
{ "/File/Samples/demo #17", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO17, nsnull },
|
||||
{ "/File/_Test Sites", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOP100, nsnull },
|
||||
{ "/File/XPToolkit Tests", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/File/XPToolkit Tests/Toolbar Test 1", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_XPTOOLKITTOOLBAR1, nsnull },
|
||||
{ "/File/XPToolkit Tests/Tree Test 1", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_XPTOOLKITTREE1, nsnull },
|
||||
{ "/File/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/File/Print Preview", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_ONE_COLUMN, nsnull },
|
||||
{ "/File/Print", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_PRINT, nsnull },
|
||||
{ "/File/Print Setup", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_PRINT_SETUP, nsnull },
|
||||
{ "/File/sep2", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/File/_Exit", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EXIT, nsnull },
|
||||
|
||||
{ "/_Edit", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/Edit/Cu_t", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_CUT, nsnull },
|
||||
{ "/Edit/_Copy", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_COPY, nsnull },
|
||||
{ "/Edit/_Paste", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_PASTE, nsnull },
|
||||
{ "/Edit/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Edit/Select All", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_SELECTALL, nsnull },
|
||||
{ "/Edit/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Edit/Find in Page", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_FINDINPAGE, nsnull },
|
||||
|
||||
//#ifdef DEBUG // turning off for now
|
||||
{ "/_Debug", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/Debug/_Visual Debugging", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_VISUAL_DEBUGGING,nsnull },
|
||||
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Debug/Event Debugging/Toggle Paint Flashing", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_PAINT_FLASHING,nsnull },
|
||||
{ "/Debug/Event Debugging/Toggle Paint Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_PAINT_DUMPING,nsnull },
|
||||
{ "/Debug/Event Debugging/Toggle Invalidate Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_INVALIDATE_DUMPING,nsnull },
|
||||
{ "/Debug/Event Debugging/Toggle Event Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_EVENT_DUMPING,nsnull },
|
||||
{ "/Debug/Event Debugging/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Debug/Event Debugging/Toggle Motion Event Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_MOTION_EVENT_DUMPING,nsnull },
|
||||
{ "/Debug/Event Debugging/Toggle Crossing Event Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_CROSSING_EVENT_DUMPING,nsnull },
|
||||
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Debug/_Reflow Test", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_REFLOW_TEST, nsnull },
|
||||
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Debug/Dump _Content", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_CONTENT, nsnull },
|
||||
{ "/Debug/Dump _Frames", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_FRAMES, nsnull },
|
||||
{ "/Debug/Dump _Views", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_VIEWS, nsnull },
|
||||
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Debug/Dump _Style Sheets", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_STYLE_SHEETS, nsnull },
|
||||
{ "/Debug/Dump _Style Contexts", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_STYLE_CONTEXTS, nsnull},
|
||||
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Debug/Show Content Size", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SHOW_CONTENT_SIZE,nsnull },
|
||||
{ "/Debug/Show Frame Size", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SHOW_FRAME_SIZE, nsnull },
|
||||
{ "/Debug/Show Style Size", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SHOW_STYLE_SIZE, nsnull },
|
||||
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Debug/Debug Save", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEBUGSAVE, nsnull },
|
||||
{ "/Debug/Debug Output Text", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DISPLAYTEXT, nsnull },
|
||||
{ "/Debug/Debug Output HTML", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DISPLAYHTML, nsnull },
|
||||
{ "/Debug/Debug Toggle Selection", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_SELECTION,nsnull },
|
||||
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Debug/Debug Robot", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEBUGROBOT, nsnull },
|
||||
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Debug/Show Content Quality", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SHOW_CONTENT_QUALITY, nsnull },
|
||||
{ "/_Style", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/Style/Select _Style Sheet", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/Style/Select Style Sheet/List Available Sheets", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_LIST, nsnull },
|
||||
{ "/Style/Select Style Sheet/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Style/Select Style Sheet/Select Default", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_DEFAULT, nsnull },
|
||||
{ "/Style/Select Style Sheet/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Style/Select Style Sheet/Select Alternative 1", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_ONE, nsnull },
|
||||
{ "/Style/Select Style Sheet/Select Alternative 2", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_TWO, nsnull },
|
||||
{ "/Style/Select Style Sheet/Select Alternative 3", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_THREE, nsnull },
|
||||
{ "/Style/Select Style Sheet/Select Alternative 4", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_FOUR, nsnull },
|
||||
{ "/Style/_Compatibility Mode", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/Style/Compatibility Mode/Nav Quirks", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_NAV_QUIRKS_MODE, nsnull },
|
||||
{ "/Style/Compatibility Mode/Standard", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_STANDARD_MODE, nsnull },
|
||||
|
||||
{ "/Style/_Widget Render Mode", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/Style/Widget Render Mode/Native", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_NATIVE_WIDGET_MODE, nsnull },
|
||||
{ "/Style/Widget Render Mode/Gfx", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_GFX_WIDGET_MODE, nsnull },
|
||||
//#endif
|
||||
|
||||
{ "/_Tools", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/Tools/_JavaScript Console", nsnull, (GIFC)gtk_ifactory_cb, JS_CONSOLE, nsnull },
|
||||
{ "/Tools/_Editor Mode", nsnull, (GIFC)gtk_ifactory_cb, EDITOR_MODE, nsnull }
|
||||
};
|
||||
|
||||
void CreateViewerMenus(nsIWidget * aParent,
|
||||
gpointer data,
|
||||
GtkWidget ** aMenuBarOut)
|
||||
{
|
||||
NS_ASSERTION(nsnull != aParent,"null parent.");
|
||||
NS_ASSERTION(nsnull != aMenuBarOut,"null out param.");
|
||||
|
||||
GtkItemFactory *item_factory;
|
||||
GtkWidget *menubar;
|
||||
|
||||
GdkSuperWin *gdkSuperWin;
|
||||
GtkWidget *mozBox;
|
||||
|
||||
gdkSuperWin = (GdkSuperWin*)aParent->GetNativeData(NS_NATIVE_WIDGET);
|
||||
|
||||
int nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
|
||||
item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", nsnull);
|
||||
|
||||
gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, data);
|
||||
|
||||
menubar = gtk_item_factory_get_widget (item_factory, "<main>");
|
||||
|
||||
gtk_menu_bar_set_shadow_type (GTK_MENU_BAR(menubar), GTK_SHADOW_NONE);
|
||||
|
||||
NS_ASSERTION(GDK_IS_SUPERWIN(gdkSuperWin), "code assumes a gdksuperwin.");
|
||||
mozBox = gtk_mozbox_new(gdkSuperWin->bin_window);
|
||||
NS_ASSERTION((mozBox != NULL), "failed to create mozBox.");
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(mozBox), menubar);
|
||||
gtk_mozbox_set_position(GTK_MOZBOX(mozBox), 0, 0 );
|
||||
gtk_widget_show(mozBox);
|
||||
gtk_widget_show(menubar);
|
||||
|
||||
*aMenuBarOut = menubar;
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
LIBRARY_NAME = widget_gtk
|
||||
|
||||
REQUIRES = util img xpcom raptor netlib
|
||||
|
||||
CPPSRCS = \
|
||||
nsAppShell.cpp \
|
||||
nsButton.cpp \
|
||||
nsCheckButton.cpp \
|
||||
nsClipboard.cpp \
|
||||
nsComboBox.cpp \
|
||||
nsContextMenu.cpp \
|
||||
nsDragService.cpp \
|
||||
nsFilePicker.cpp \
|
||||
nsFileWidget.cpp \
|
||||
nsFontRetrieverService.cpp \
|
||||
nsFontSizeIterator.cpp \
|
||||
nsGtkEventHandler.cpp \
|
||||
nsGtkUtils.cpp \
|
||||
nsLabel.cpp \
|
||||
nsListBox.cpp \
|
||||
nsLookAndFeel.cpp \
|
||||
nsMenu.cpp \
|
||||
nsMenuBar.cpp \
|
||||
nsMenuItem.cpp \
|
||||
nsPopUpMenu.cpp \
|
||||
nsRadioButton.cpp \
|
||||
nsScrollbar.cpp \
|
||||
nsSound.cpp \
|
||||
nsTextAreaWidget.cpp \
|
||||
nsTextHelper.cpp \
|
||||
nsTextWidget.cpp \
|
||||
nsToolkit.cpp \
|
||||
nsWidget.cpp \
|
||||
nsWidgetFactory.cpp \
|
||||
nsWindow.cpp \
|
||||
$(NULL)
|
||||
|
||||
SHARED_LIBRARY_LIBS = $(DIST)/lib/libraptorbasewidget_s.a
|
||||
|
||||
EXTRA_DSO_LDOPTS = \
|
||||
$(MKSHLIB_FORCE_ALL) \
|
||||
$(SHARED_LIBRARY_LIBS) \
|
||||
$(MKSHLIB_UNFORCE_ALL) \
|
||||
$(MOZ_COMPONENT_LIBS) \
|
||||
-lraptorgfx \
|
||||
$(NULL)
|
||||
|
||||
ifndef MOZ_MONOLITHIC_TOOLKIT
|
||||
EXTRA_DSO_LDOPTS += -L$(DIST)/lib -lgtksuperwin $(MOZ_GTK_LDFLAGS)
|
||||
else
|
||||
EXTRA_DSO_LDOPTS += $(TK_LIBS)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifndef MOZ_MONOLITHIC_TOOLKIT
|
||||
CXXFLAGS += $(MOZ_GTK_CFLAGS)
|
||||
CFLAGS += $(MOZ_GTK_CFLAGS)
|
||||
else
|
||||
CXXFLAGS += $(TK_CFLAGS)
|
||||
CFLAGS += $(TK_CFLAGS)
|
||||
endif
|
||||
|
||||
DEFINES += -D_IMPL_NS_WIDGET -DUSE_XIM
|
||||
|
||||
ifeq ($(OS_ARCH), Linux)
|
||||
DEFINES += -D_BSD_SOURCE
|
||||
endif
|
||||
|
||||
INCLUDES += \
|
||||
-I$(srcdir)/../xpwidgets \
|
||||
-I$(srcdir) \
|
||||
$(NULL)
|
||||
|
||||
$(LIBRARY) $(SHARED_LIBRARY): $(SHARED_LIBRARY_LIBS) Makefile
|
||||
|
||||
@@ -1,292 +0,0 @@
|
||||
/* XPM */
|
||||
static char * mozilla_icon_xpm[] = {
|
||||
"32 32 257 2",
|
||||
" c None",
|
||||
". c #AA7303",
|
||||
"+ c #A67003",
|
||||
"@ c #B77C03",
|
||||
"# c #8D6003",
|
||||
"$ c #8D6004",
|
||||
"% c #6C4A04",
|
||||
"& c #3A2804",
|
||||
"* c #6B4802",
|
||||
"= c #9B6903",
|
||||
"- c #5A2C04",
|
||||
"; c #411B04",
|
||||
"> c #9D6A03",
|
||||
", c #7A5203",
|
||||
"' c #510D04",
|
||||
") c #6B1104",
|
||||
"! c #7D5503",
|
||||
"~ c #674604",
|
||||
"{ c #C21E04",
|
||||
"] c #C21D04",
|
||||
"^ c #523804",
|
||||
"/ c #513702",
|
||||
"( c #552904",
|
||||
"_ c #DD2204",
|
||||
": c #DF2204",
|
||||
"< c #582904",
|
||||
"[ c #5F3F02",
|
||||
"} c #6B2504",
|
||||
"| c #FE2604",
|
||||
"1 c #AB7303",
|
||||
"2 c #9B6904",
|
||||
"3 c #C31F04",
|
||||
"4 c #FE2704",
|
||||
"5 c #A81904",
|
||||
"6 c #926304",
|
||||
"7 c #4D3302",
|
||||
"8 c #483104",
|
||||
"9 c #C61E04",
|
||||
"0 c #B11B04",
|
||||
"a c #891604",
|
||||
"b c #761204",
|
||||
"c c #614304",
|
||||
"d c #775102",
|
||||
"e c #795102",
|
||||
"f c #785102",
|
||||
"g c #C58603",
|
||||
"h c #642404",
|
||||
"i c #B21A04",
|
||||
"j c #1F0604",
|
||||
"k c #550E04",
|
||||
"l c #631004",
|
||||
"m c #402404",
|
||||
"n c #AF7703",
|
||||
"o c #3D2902",
|
||||
"p c #7F5602",
|
||||
"q c #805604",
|
||||
"r c #0C0904",
|
||||
"s c #080604",
|
||||
"t c #080706",
|
||||
"u c #090604",
|
||||
"v c #060404",
|
||||
"w c #620F04",
|
||||
"x c #7A1304",
|
||||
"y c #030204",
|
||||
"z c #570E04",
|
||||
"A c #721204",
|
||||
"B c #270704",
|
||||
"C c #080504",
|
||||
"D c #0A0604",
|
||||
"E c #533804",
|
||||
"F c #A56F02",
|
||||
"G c #B87C03",
|
||||
"H c #3B2804",
|
||||
"I c #A51904",
|
||||
"J c #FC2704",
|
||||
"K c #D62004",
|
||||
"L c #691004",
|
||||
"M c #C01E04",
|
||||
"N c #6D1004",
|
||||
"O c #9C1804",
|
||||
"P c #B31C04",
|
||||
"Q c #150404",
|
||||
"R c #801404",
|
||||
"S c #DD2304",
|
||||
"T c #120404",
|
||||
"U c #130404",
|
||||
"V c #500C04",
|
||||
"W c #CC1E04",
|
||||
"X c #AA1A04",
|
||||
"Y c #100904",
|
||||
"Z c #B47A03",
|
||||
"` c #A77103",
|
||||
" . c #513704",
|
||||
".. c #891704",
|
||||
"+. c #F62604",
|
||||
"@. c #BA1D04",
|
||||
"#. c #3C0A04",
|
||||
"$. c #EB2304",
|
||||
"%. c #DE2304",
|
||||
"&. c #560E04",
|
||||
"*. c #E82304",
|
||||
"=. c #FE2804",
|
||||
"-. c #BE1D04",
|
||||
";. c #F12404",
|
||||
">. c #661004",
|
||||
",. c #020204",
|
||||
"'. c #5E0F04",
|
||||
"). c #A61A04",
|
||||
"!. c #4A3204",
|
||||
"~. c #BC7E03",
|
||||
"{. c #8E6002",
|
||||
"]. c #684604",
|
||||
"^. c #390D04",
|
||||
"/. c #EE2404",
|
||||
"(. c #FE2904",
|
||||
"_. c #7D1304",
|
||||
":. c #8C1504",
|
||||
"<. c #200604",
|
||||
"[. c #A81A04",
|
||||
"}. c #E72204",
|
||||
"|. c #DA2004",
|
||||
"1. c #070204",
|
||||
"2. c #280704",
|
||||
"3. c #543904",
|
||||
"4. c #9F6C02",
|
||||
"5. c #674602",
|
||||
"6. c #B47B04",
|
||||
"7. c #311004",
|
||||
"8. c #B11C04",
|
||||
"9. c #AA1B04",
|
||||
"0. c #6A1104",
|
||||
"a. c #801504",
|
||||
"b. c #2B0704",
|
||||
"c. c #09090A",
|
||||
"d. c #450B04",
|
||||
"e. c #360904",
|
||||
"f. c #DC2204",
|
||||
"g. c #EE2504",
|
||||
"h. c #C11D04",
|
||||
"i. c #6F1104",
|
||||
"j. c #704B04",
|
||||
"k. c #9C6902",
|
||||
"l. c #A56F03",
|
||||
"m. c #5F4004",
|
||||
"n. c #8D1604",
|
||||
"o. c #440A04",
|
||||
"p. c #1A0504",
|
||||
"q. c #931604",
|
||||
"r. c #621004",
|
||||
"s. c #7F1404",
|
||||
"t. c #921704",
|
||||
"u. c #F82504",
|
||||
"v. c #F52504",
|
||||
"w. c #981804",
|
||||
"x. c #241804",
|
||||
"y. c #5B3E04",
|
||||
"z. c #D82204",
|
||||
"A. c #D02004",
|
||||
"B. c #DA2104",
|
||||
"C. c #D52104",
|
||||
"D. c #2A1A04",
|
||||
"E. c #AC7403",
|
||||
"F. c #2B1C04",
|
||||
"G. c #D04004",
|
||||
"H. c #FC3C04",
|
||||
"I. c #F94E04",
|
||||
"J. c #881504",
|
||||
"K. c #FC2604",
|
||||
"L. c #792804",
|
||||
"M. c #AC7503",
|
||||
"N. c #9A6803",
|
||||
"O. c #782804",
|
||||
"P. c #F66504",
|
||||
"Q. c #F94B04",
|
||||
"R. c #F46804",
|
||||
"S. c #F46604",
|
||||
"T. c #F76504",
|
||||
"U. c #FB4204",
|
||||
"V. c #C13D04",
|
||||
"W. c #5D0E04",
|
||||
"X. c #DA2204",
|
||||
"Y. c #741604",
|
||||
"Z. c #8C5E03",
|
||||
"`. c #885B03",
|
||||
" + c #8B1904",
|
||||
".+ c #DE2204",
|
||||
"++ c #D22D04",
|
||||
"@+ c #C42D04",
|
||||
"#+ c #580E04",
|
||||
"$+ c #9F1804",
|
||||
"%+ c #895D04",
|
||||
"&+ c #D62204",
|
||||
"*+ c #371904",
|
||||
"=+ c #2C1A04",
|
||||
"-+ c #4A0C04",
|
||||
";+ c #140404",
|
||||
">+ c #AB1A04",
|
||||
",+ c #DA2304",
|
||||
"'+ c #6A4702",
|
||||
")+ c #754F02",
|
||||
"!+ c #821404",
|
||||
"~+ c #462B04",
|
||||
"{+ c #B37A03",
|
||||
"]+ c #B17803",
|
||||
"^+ c #714C04",
|
||||
"/+ c #580F04",
|
||||
"(+ c #E32204",
|
||||
"_+ c #DD2104",
|
||||
":+ c #611D04",
|
||||
"<+ c #BA7F03",
|
||||
"[+ c #B27803",
|
||||
"}+ c #6F1D04",
|
||||
"|+ c #FD2704",
|
||||
"1+ c #F22504",
|
||||
"2+ c #634304",
|
||||
"3+ c #875B03",
|
||||
"4+ c #734F02",
|
||||
"5+ c #805704",
|
||||
"6+ c #1D0504",
|
||||
"7+ c #DB2204",
|
||||
"8+ c #EA2404",
|
||||
"9+ c #2E0804",
|
||||
"0+ c #815803",
|
||||
"a+ c #941704",
|
||||
"b+ c #C11E04",
|
||||
"c+ c #391B04",
|
||||
"d+ c #A77104",
|
||||
"e+ c #B67C04",
|
||||
"f+ c #371D04",
|
||||
"g+ c #360A04",
|
||||
"h+ c #573A04",
|
||||
"i+ c #372604",
|
||||
"j+ c #3E2104",
|
||||
"k+ c #B57A03",
|
||||
"l+ c #B57B03",
|
||||
"m+ c #603F04",
|
||||
"n+ c #430A04",
|
||||
"o+ c #351904",
|
||||
"p+ c #A36E03",
|
||||
"q+ c #BE8103",
|
||||
"r+ c #1D1404",
|
||||
"s+ c #483004",
|
||||
"t+ c #A26E03",
|
||||
"u+ c #6D4B02",
|
||||
"v+ c #825804",
|
||||
"w+ c #0B0804",
|
||||
"x+ c #976603",
|
||||
"y+ c #815703",
|
||||
"z+ c #926404",
|
||||
"A+ c #895D03",
|
||||
"B+ c #614202",
|
||||
"C+ c #9A6804",
|
||||
"D+ c #C88704",
|
||||
"E+ c #C18303",
|
||||
"F+ c #654302",
|
||||
"G+ c #744F02",
|
||||
"H+ c #704B02",
|
||||
" ",
|
||||
" . ",
|
||||
" + @ ",
|
||||
" # $ ",
|
||||
" % & * ",
|
||||
" = - ; > ",
|
||||
" , ' ) ! ",
|
||||
" ~ { ] ^ ",
|
||||
" / ( _ : < [ ",
|
||||
" . } | | } 1 ",
|
||||
" 2 3 | 4 5 6 ",
|
||||
" 7 8 9 0 a b c ",
|
||||
" d e f f f d d d d d d g h i j k l m n d d d d d d d d d d d o ",
|
||||
" p q r s s s s t s s u v w x y z A B C D D D D D s s s s E F ",
|
||||
" G H I J 4 | 4 | K L L M N O P Q R | S T U V W X Y Z ",
|
||||
" ` ...+.| 4 @.#.$.4 | %.&.*.4 =.-.;.>.,.'.).!.~. ",
|
||||
" {.].^./.(.X _.;.| :.T <.[.| }.z | |.1.2.3.4. ",
|
||||
" 5.6.7.8.9.0.a.b.c.d.e.f.g.h.&.| i.u j.k. ",
|
||||
" l.m.n.o.p.q._.r.a.s.t.u.v.w.x.Z ",
|
||||
" {.y.P z.R A.v.x j B.| C.D.E. ",
|
||||
" F.G.H.I.4 | 4 t.J.f.K.L.M. ",
|
||||
" N.O.P.Q.R.S.T.U.V.W.X.4 Y.Z. ",
|
||||
" `. +4 =.| | .+++@+#+$+| K %+ ",
|
||||
" %+&+| | | I *+=+-+;+>+,+&+x.'+ ",
|
||||
" )+=+X.=.| !+~+{+]+^+,./+(+_+:+<+ ",
|
||||
" [+}+|+1+) 2+3+ 4+5+6+7+8+9+0+ ",
|
||||
" $ a+b+c+d+ e+f+0.g+h+ ",
|
||||
" i+A j+k+ l+m+n+o+p+ ",
|
||||
" q+r+s+t+ u+v+w+x+ ",
|
||||
" y+z+A+ B+C+2 ",
|
||||
" D+ E+F+ ",
|
||||
" G+ H+ "};
|
||||
@@ -1,63 +0,0 @@
|
||||
/* XPM */
|
||||
static char * mozicon50_xpm[] = {
|
||||
"50 51 9 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"+ c #FF0000",
|
||||
"@ c #808000",
|
||||
"# c #800000",
|
||||
"$ c #FF6633",
|
||||
"% c #990066",
|
||||
"& c #FF00FF",
|
||||
"* c #222222",
|
||||
" ",
|
||||
" @ ",
|
||||
" $@ ",
|
||||
" @@ ",
|
||||
" @@$ ",
|
||||
" $@*@ ",
|
||||
" @@.@ ",
|
||||
" @..@ ",
|
||||
" $@..@@ ",
|
||||
" $@##*@ ",
|
||||
" @*#+.@ ",
|
||||
" @.++.@$ ",
|
||||
" $@.++.@$ ",
|
||||
" @*#++#*@ ",
|
||||
" @.++++.@ ",
|
||||
" $@.++++.@$ ",
|
||||
" @*#++++**@ ",
|
||||
" @.#++++#.@ ",
|
||||
" $@.++####.@ ",
|
||||
" @@*+#*##*.@@ ",
|
||||
"*@@@@@@@@@@@@@@@@@@@.#+..*##*#@@@@@@@@@@@@@@@@@@@*",
|
||||
" *@@*................+#..*###.................@@* ",
|
||||
" %@@@.#++++++++++++#**#*#++.###++*...#+++#.*@@* ",
|
||||
" *@@.#+++++++++#.##++#+#+*.#+++#..##++#.@@@% ",
|
||||
" $@..+++++++.#++++++##++++#++#...++*.@@$ ",
|
||||
" @@*.#+++++.#+++++*.#++++##++#.*...@@ ",
|
||||
" $@@.#+++#*++++#....#+++*#+++...*@$ ",
|
||||
" *@@..++#*++#**.*.*+++#.#++*..@@$ ",
|
||||
" $@*.++******#+++++#+#+++..@@ ",
|
||||
" $@@.##..*$#**#+#*#++++..@@ ",
|
||||
" $@@.#+#***##...#++++.*@@ ",
|
||||
" %@@*++++++++#.#++++.@@ ",
|
||||
" @.#+++++++++.##+++.@$ ",
|
||||
" @.+$$$$$+$$$#*#+++*@@ ",
|
||||
" $@*+$$$$$$$+$#.#+++#.@ ",
|
||||
" @*#+++++++++++.#++++.@ ",
|
||||
" @.#+++++++#*++.##+++.@$ ",
|
||||
" $@.+++++++....#..+#++*@@ ",
|
||||
" @@*+++++#.*@@@...*+++#.@ ",
|
||||
" @.#++++#.@@@ @@..#++++.@ ",
|
||||
" @.++++*.@@$ %@@..+++#.@@ ",
|
||||
" $@.+++..@@* $@*.#+#**@ ",
|
||||
" @@#+#.*@$% $@@.##..@ ",
|
||||
" @.##.@@ @@..#.@$ ",
|
||||
" $@.*.@@$ @@**.@$ ",
|
||||
" $@.*@@ %$@@.*@ ",
|
||||
" @.@@$ *@@.@ ",
|
||||
" @@@$ %@@@$ ",
|
||||
" $@@% %@@@ ",
|
||||
" @@ $@ ",
|
||||
" $ * "};
|
||||
@@ -1,459 +0,0 @@
|
||||
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include "prmon.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAppShell.h"
|
||||
#include "nsIAppShell.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsICmdLineService.h"
|
||||
#include "nsGtkEventHandler.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef MOZ_GLE
|
||||
#include <gle/gle.h>
|
||||
#endif
|
||||
|
||||
#include "nsIWidget.h"
|
||||
#include "nsIPref.h"
|
||||
|
||||
|
||||
#include "glib.h"
|
||||
|
||||
struct OurGdkIOClosure {
|
||||
GdkInputFunction function;
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
our_gdk_io_invoke(GIOChannel* source, GIOCondition condition, gpointer data)
|
||||
{
|
||||
OurGdkIOClosure* ioc = (OurGdkIOClosure*) data;
|
||||
if (ioc) {
|
||||
(*ioc->function)(ioc->data, g_io_channel_unix_get_fd(source),
|
||||
GDK_INPUT_READ);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
our_gdk_io_destroy(gpointer data)
|
||||
{
|
||||
OurGdkIOClosure* ioc = (OurGdkIOClosure*) data;
|
||||
if (ioc) {
|
||||
g_free(ioc);
|
||||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
our_gdk_input_add (gint source,
|
||||
GdkInputFunction function,
|
||||
gpointer data,
|
||||
gint priority)
|
||||
{
|
||||
guint result;
|
||||
OurGdkIOClosure *closure = g_new (OurGdkIOClosure, 1);
|
||||
GIOChannel *channel;
|
||||
|
||||
closure->function = function;
|
||||
closure->data = data;
|
||||
|
||||
channel = g_io_channel_unix_new (source);
|
||||
result = g_io_add_watch_full (channel, priority, G_IO_IN,
|
||||
our_gdk_io_invoke,
|
||||
closure, our_gdk_io_destroy);
|
||||
g_io_channel_unref (channel);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// XPCOM CIDs
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
static NS_DEFINE_CID(kCmdLineServiceCID, NS_COMMANDLINE_SERVICE_CID);
|
||||
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
||||
|
||||
// a linked, ordered list of event queues and their tokens
|
||||
class EventQueueToken {
|
||||
public:
|
||||
EventQueueToken(nsIEventQueue *aQueue, const gint aToken);
|
||||
virtual ~EventQueueToken();
|
||||
nsIEventQueue *mQueue;
|
||||
gint mToken;
|
||||
EventQueueToken *mNext;
|
||||
};
|
||||
|
||||
EventQueueToken::EventQueueToken(nsIEventQueue *aQueue, const gint aToken) {
|
||||
mQueue = aQueue;
|
||||
NS_IF_ADDREF(mQueue);
|
||||
mToken = aToken;
|
||||
mNext = 0;
|
||||
}
|
||||
|
||||
EventQueueToken::~EventQueueToken(){
|
||||
NS_IF_RELEASE(mQueue);
|
||||
}
|
||||
|
||||
class EventQueueTokenQueue {
|
||||
public:
|
||||
EventQueueTokenQueue();
|
||||
virtual ~EventQueueTokenQueue();
|
||||
nsresult PushToken(nsIEventQueue *aQueue, gint aToken);
|
||||
PRBool PopToken(nsIEventQueue *aQueue, gint *aToken);
|
||||
|
||||
private:
|
||||
EventQueueToken *mHead;
|
||||
};
|
||||
|
||||
EventQueueTokenQueue::EventQueueTokenQueue() {
|
||||
mHead = 0;
|
||||
}
|
||||
|
||||
EventQueueTokenQueue::~EventQueueTokenQueue() {
|
||||
|
||||
// if we reach this point with an empty token queue, well, fab. however,
|
||||
// we expect the first event queue to still be active. so we take
|
||||
// special care to unhook that queue (not that failing to do so seems
|
||||
// to hurt anything). more queues than that would be an error.
|
||||
//NS_ASSERTION(!mHead || !mHead->mNext, "event queue token list deleted when not empty");
|
||||
// (and skip the assertion for now. we're leaking event queues because they
|
||||
// are referenced by things that leak, so this assertion goes off a lot.)
|
||||
if (mHead) {
|
||||
gdk_input_remove(mHead->mToken);
|
||||
delete mHead;
|
||||
// and leak the rest. it's an error, anyway
|
||||
}
|
||||
}
|
||||
|
||||
nsresult EventQueueTokenQueue::PushToken(nsIEventQueue *aQueue, gint aToken) {
|
||||
EventQueueToken *newToken = new EventQueueToken(aQueue, aToken);
|
||||
NS_ASSERTION(newToken, "couldn't allocate token queue element");
|
||||
if (!newToken)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
newToken->mNext = mHead;
|
||||
mHead = newToken;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool EventQueueTokenQueue::PopToken(nsIEventQueue *aQueue, gint *aToken) {
|
||||
EventQueueToken *token, *lastToken;
|
||||
PRBool found = PR_FALSE;
|
||||
NS_ASSERTION(mHead, "attempt to retrieve event queue token from empty queue");
|
||||
if (mHead)
|
||||
NS_ASSERTION(mHead->mQueue == aQueue, "retrieving event queue from past head of queue queue");
|
||||
|
||||
token = mHead;
|
||||
lastToken = 0;
|
||||
while (token && token->mQueue != aQueue) {
|
||||
lastToken = token;
|
||||
token = token->mNext;
|
||||
}
|
||||
if (token) {
|
||||
if (lastToken)
|
||||
lastToken->mNext = token->mNext;
|
||||
else
|
||||
mHead = token->mNext;
|
||||
found = PR_TRUE;
|
||||
*aToken = token->mToken;
|
||||
delete token;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsAppShell constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsAppShell::nsAppShell()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mDispatchListener = 0;
|
||||
mEventQueueTokens = new EventQueueTokenQueue();
|
||||
// throw on error would really be civilized here
|
||||
NS_ASSERTION(mEventQueueTokens, "couldn't allocate event queue token queue");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsAppShell destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsAppShell::~nsAppShell()
|
||||
{
|
||||
delete mEventQueueTokens;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsISupports implementation macro
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsAppShell, nsIAppShell)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsAppShell::SetDispatchListener(nsDispatchListener* aDispatchListener)
|
||||
{
|
||||
mDispatchListener = aDispatchListener;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void event_processor_callback(gpointer data,
|
||||
gint source,
|
||||
GdkInputCondition condition)
|
||||
{
|
||||
nsIEventQueue *eventQueue = (nsIEventQueue*)data;
|
||||
if (eventQueue)
|
||||
eventQueue->ProcessPendingEvents();
|
||||
}
|
||||
|
||||
#define PREF_NCOLS "browser.ncols"
|
||||
#define PREF_INSTALLCMAP "browser.installcmap"
|
||||
|
||||
static void
|
||||
HandleColormapPrefs( void )
|
||||
{
|
||||
PRInt32 ivalue = 0;
|
||||
PRBool bvalue;
|
||||
nsresult rv;
|
||||
|
||||
/* The default is to do nothing. INSTALLCMAP has precedence over
|
||||
NCOLS. Ignore the fact we can't do this if it fails, as it is
|
||||
not critical */
|
||||
|
||||
NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv);
|
||||
if (NS_FAILED(rv) || (!prefs))
|
||||
return;
|
||||
|
||||
/* first check ncols */
|
||||
|
||||
rv = prefs->GetIntPref(PREF_NCOLS, &ivalue);
|
||||
if (NS_SUCCEEDED(rv) && ivalue >= 0 && ivalue <= 255 ) {
|
||||
gdk_rgb_set_min_colors( ivalue );
|
||||
return;
|
||||
}
|
||||
|
||||
/* next check installcmap */
|
||||
|
||||
rv = prefs->GetBoolPref(PREF_INSTALLCMAP, &bvalue);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if ( PR_TRUE == bvalue )
|
||||
gdk_rgb_set_min_colors( 255 ); // force it
|
||||
else
|
||||
gdk_rgb_set_min_colors( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the application shell
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP nsAppShell::Create(int *bac, char **bav)
|
||||
{
|
||||
gchar *home=nsnull;
|
||||
gchar *path=nsnull;
|
||||
|
||||
int argc = bac ? *bac : 0;
|
||||
char **argv = bav;
|
||||
#if 1
|
||||
nsresult rv;
|
||||
|
||||
NS_WITH_SERVICE(nsICmdLineService, cmdLineArgs, kCmdLineServiceCID, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = cmdLineArgs->GetArgc(&argc);
|
||||
if(NS_FAILED(rv))
|
||||
argc = bac ? *bac : 0;
|
||||
|
||||
rv = cmdLineArgs->GetArgv(&argv);
|
||||
if(NS_FAILED(rv))
|
||||
argv = bav;
|
||||
}
|
||||
#endif
|
||||
|
||||
gtk_set_locale ();
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
// It is most convenient for us to intercept our events after
|
||||
// they have been converted to GDK, but before GTK+ gets them
|
||||
gdk_event_handler_set (handle_gdk_event, NULL, NULL);
|
||||
|
||||
#ifdef MOZ_GLE
|
||||
gle_init (&argc, &argv);
|
||||
#endif
|
||||
|
||||
// delete the cmdLineArgs thing?
|
||||
|
||||
HandleColormapPrefs();
|
||||
gdk_rgb_init();
|
||||
|
||||
home = g_get_home_dir();
|
||||
if ((char*)nsnull != home) {
|
||||
path = g_strdup_printf("%s%c%s", home, G_DIR_SEPARATOR, ".gtkrc");
|
||||
if ((char *)nsnull != path) {
|
||||
gtk_rc_parse(path);
|
||||
g_free(path);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Spinup - do any preparation necessary for running a message loop
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsAppShell::Spinup()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Spindown - do any cleanup necessary for finishing a message loop
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsAppShell::Spindown()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Run
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsAppShell::Run()
|
||||
{
|
||||
NS_ADDREF_THIS();
|
||||
nsresult rv = NS_OK;
|
||||
nsIEventQueue * EQueue = nsnull;
|
||||
|
||||
// Get the event queue service
|
||||
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ASSERTION("Could not obtain event queue service", PR_FALSE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Got the event queue from the service\n");
|
||||
#endif /* DEBUG */
|
||||
|
||||
//Get the event queue for the thread.
|
||||
rv = eventQService->GetThreadEventQueue(PR_GetCurrentThread(), &EQueue);
|
||||
|
||||
// If a queue already present use it.
|
||||
if (EQueue)
|
||||
goto done;
|
||||
|
||||
// Create the event queue for the thread
|
||||
rv = eventQService->CreateThreadEventQueue();
|
||||
if (NS_OK != rv) {
|
||||
NS_ASSERTION("Could not create the thread event queue", PR_FALSE);
|
||||
return rv;
|
||||
}
|
||||
//Get the event queue for the thread
|
||||
rv = eventQService->GetThreadEventQueue(PR_GetCurrentThread(), &EQueue);
|
||||
if (NS_OK != rv) {
|
||||
NS_ASSERTION("Could not obtain the thread event queue", PR_FALSE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
done:
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Calling gdk_input_add with event queue\n");
|
||||
#endif /* DEBUG */
|
||||
|
||||
// (has to be called explicitly for this, the primordial appshell, because
|
||||
// of startup ordering problems.)
|
||||
ListenToEventQueue(EQueue, PR_TRUE);
|
||||
|
||||
gtk_main();
|
||||
|
||||
NS_IF_RELEASE(EQueue);
|
||||
Release();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Exit a message handler loop
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP nsAppShell::Exit()
|
||||
{
|
||||
gtk_main_quit ();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// does nothing. used by xp code with non-gtk expectations.
|
||||
// this method will be removed once xp eventloops are working.
|
||||
NS_IMETHODIMP nsAppShell::GetNativeEvent(PRBool &aRealEvent, void *& aEvent)
|
||||
{
|
||||
aRealEvent = PR_FALSE;
|
||||
aEvent = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// simply executes one iteration of the event loop. used by xp code with
|
||||
// non-gtk expectations.
|
||||
// this method will be removed once xp eventloops are working.
|
||||
NS_IMETHODIMP nsAppShell::DispatchNativeEvent(PRBool aRealEvent, void *aEvent)
|
||||
{
|
||||
g_main_iteration(PR_TRUE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAppShell::ListenToEventQueue(nsIEventQueue *aQueue,
|
||||
PRBool aListen)
|
||||
{
|
||||
// tell gdk to listen to the event queue or not
|
||||
|
||||
gint queueToken;
|
||||
if (aListen) {
|
||||
queueToken = our_gdk_input_add(aQueue->GetEventQueueSelectFD(),
|
||||
event_processor_callback,
|
||||
aQueue, G_PRIORITY_DEFAULT_IDLE);
|
||||
mEventQueueTokens->PushToken(aQueue, queueToken);
|
||||
} else {
|
||||
if (mEventQueueTokens->PopToken(aQueue, &queueToken))
|
||||
gdk_input_remove(queueToken);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef nsAppShell_h__
|
||||
#define nsAppShell_h__
|
||||
|
||||
#include "nsIAppShell.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/**
|
||||
* Native GTK+ Application shell wrapper
|
||||
*/
|
||||
|
||||
class EventQueueTokenQueue;
|
||||
|
||||
class nsAppShell : public nsIAppShell
|
||||
{
|
||||
public:
|
||||
nsAppShell();
|
||||
virtual ~nsAppShell();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIAPPSHELL
|
||||
|
||||
private:
|
||||
nsDispatchListener *mDispatchListener;
|
||||
EventQueueTokenQueue *mEventQueueTokens;
|
||||
};
|
||||
|
||||
#endif // nsAppShell_h__
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "nsGtkEventHandler.h"
|
||||
|
||||
#include "nsButton.h"
|
||||
#include "nsString.h"
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsButton, nsWidget)
|
||||
NS_IMPL_RELEASE_INHERITED(nsButton, nsWidget)
|
||||
NS_IMPL_QUERY_INTERFACE2(nsButton, nsIButton, nsIWidget)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsButton constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsButton::nsButton() : nsWidget() , nsIButton()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the native Button widget
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsButton::CreateNative(GtkObject *parentWindow)
|
||||
{
|
||||
#ifdef USE_SUPERWIN
|
||||
if (!GDK_IS_SUPERWIN(parentWindow)) {
|
||||
g_print("Damn, brother. That's not a superwin.\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
GdkSuperWin *superwin = GDK_SUPERWIN(parentWindow);
|
||||
|
||||
mMozBox = gtk_mozbox_new(superwin->bin_window);
|
||||
|
||||
#endif
|
||||
|
||||
mWidget = gtk_button_new_with_label("");
|
||||
gtk_widget_set_name(mWidget, "nsButton");
|
||||
|
||||
#ifdef USE_SUPERWIN
|
||||
|
||||
// make sure that we put the scrollbar into the mozbox
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(mMozBox), mWidget);
|
||||
|
||||
#endif /* USE_SUPERWIN */
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsButton destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsButton::~nsButton()
|
||||
{
|
||||
}
|
||||
|
||||
void nsButton::InitCallbacks(char * aName)
|
||||
{
|
||||
InstallButtonPressSignal(mWidget);
|
||||
InstallButtonReleaseSignal(mWidget);
|
||||
|
||||
InstallEnterNotifySignal(mWidget);
|
||||
InstallLeaveNotifySignal(mWidget);
|
||||
|
||||
// These are needed so that the events will go to us and not our parent.
|
||||
AddToEventMask(mWidget,
|
||||
GDK_BUTTON_PRESS_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_ENTER_NOTIFY_MASK |
|
||||
GDK_EXPOSURE_MASK |
|
||||
GDK_FOCUS_CHANGE_MASK |
|
||||
GDK_KEY_PRESS_MASK |
|
||||
GDK_KEY_RELEASE_MASK |
|
||||
GDK_LEAVE_NOTIFY_MASK |
|
||||
GDK_POINTER_MOTION_MASK);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set this button label
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsButton::SetLabel(const nsString& aText)
|
||||
{
|
||||
NS_ALLOC_STR_BUF(label, aText, 256);
|
||||
|
||||
gtk_label_set(GTK_LABEL(GTK_BIN (mWidget)->child), label);
|
||||
|
||||
NS_FREE_STR_BUF(label);
|
||||
return (NS_OK);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get this button label
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsButton::GetLabel(nsString& aBuffer)
|
||||
{
|
||||
char * text;
|
||||
|
||||
gtk_label_get(GTK_LABEL(GTK_BIN (mWidget)->child), &text);
|
||||
aBuffer.SetLength(0);
|
||||
aBuffer.Append(text);
|
||||
|
||||
return (NS_OK);
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// set font for button
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
/* virtual */
|
||||
void nsButton::SetFontNative(GdkFont *aFont)
|
||||
{
|
||||
GtkStyle *style = gtk_style_copy(GTK_BIN (mWidget)->child->style);
|
||||
// gtk_style_copy ups the ref count of the font
|
||||
gdk_font_unref (style->font);
|
||||
|
||||
style->font = aFont;
|
||||
gdk_font_ref(style->font);
|
||||
|
||||
gtk_widget_set_style(GTK_BIN (mWidget)->child, style);
|
||||
|
||||
gtk_style_unref(style);
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef nsButton_h__
|
||||
#define nsButton_h__
|
||||
|
||||
#include "nsWidget.h"
|
||||
#include "nsIButton.h"
|
||||
|
||||
/**
|
||||
* Native GTK+ button wrapper
|
||||
*/
|
||||
class nsButton : public nsWidget,
|
||||
public nsIButton
|
||||
{
|
||||
|
||||
public:
|
||||
nsButton();
|
||||
virtual ~nsButton();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIButton part
|
||||
NS_IMETHOD SetLabel(const nsString& aText);
|
||||
NS_IMETHOD GetLabel(nsString& aBuffer);
|
||||
|
||||
virtual void SetFontNative(GdkFont *aFont);
|
||||
|
||||
protected:
|
||||
NS_METHOD CreateNative(GtkObject *parentWindow);
|
||||
virtual void InitCallbacks(char * aName = nsnull);
|
||||
};
|
||||
|
||||
#endif // nsButton_h__
|
||||
@@ -1,250 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include "nsCheckButton.h"
|
||||
#include "nsString.h"
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsCheckButton, nsWidget)
|
||||
NS_IMPL_RELEASE_INHERITED(nsCheckButton, nsWidget)
|
||||
NS_IMPL_QUERY_INTERFACE2(nsCheckButton, nsICheckButton, nsIWidget)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsCheckButton constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsCheckButton::nsCheckButton() : nsWidget() , nsICheckButton()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mLabel = nsnull;
|
||||
mCheckButton = nsnull;
|
||||
mState = PR_FALSE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsCheckButton destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsCheckButton::~nsCheckButton()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsCheckButton::OnDestroySignal(GtkWidget* aGtkWidget)
|
||||
{
|
||||
if (aGtkWidget == mCheckButton) {
|
||||
mCheckButton = nsnull;
|
||||
}
|
||||
else if (aGtkWidget == mLabel) {
|
||||
mLabel = nsnull;
|
||||
}
|
||||
else {
|
||||
nsWidget::OnDestroySignal(aGtkWidget);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the native CheckButton widget
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsCheckButton::CreateNative(GtkObject *parentWindow)
|
||||
{
|
||||
mWidget = gtk_event_box_new();
|
||||
mCheckButton = gtk_check_button_new();
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(mWidget), mCheckButton);
|
||||
|
||||
gtk_widget_show(mCheckButton);
|
||||
|
||||
gtk_widget_set_name(mWidget, "nsCheckButton");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsCheckButton::InitCallbacks(char * aName)
|
||||
{
|
||||
InstallButtonPressSignal(mCheckButton);
|
||||
InstallButtonReleaseSignal(mCheckButton);
|
||||
|
||||
InstallEnterNotifySignal(mWidget);
|
||||
InstallLeaveNotifySignal(mWidget);
|
||||
|
||||
// These are needed so that the events will go to us and not our parent.
|
||||
AddToEventMask(mWidget,
|
||||
GDK_BUTTON_PRESS_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_ENTER_NOTIFY_MASK |
|
||||
GDK_EXPOSURE_MASK |
|
||||
GDK_FOCUS_CHANGE_MASK |
|
||||
GDK_KEY_PRESS_MASK |
|
||||
GDK_KEY_RELEASE_MASK |
|
||||
GDK_LEAVE_NOTIFY_MASK |
|
||||
GDK_POINTER_MOTION_MASK);
|
||||
|
||||
// Add in destroy callback
|
||||
gtk_signal_connect(GTK_OBJECT(mCheckButton),
|
||||
"destroy",
|
||||
GTK_SIGNAL_FUNC(DestroySignal),
|
||||
this);
|
||||
|
||||
InstallSignal((GtkWidget *)mCheckButton,
|
||||
(gchar *)"toggled",
|
||||
GTK_SIGNAL_FUNC(nsCheckButton::ToggledSignal));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set this button label
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsCheckButton::SetState(const PRBool aState)
|
||||
{
|
||||
mState = aState;
|
||||
|
||||
if (mWidget && mCheckButton)
|
||||
{
|
||||
GtkToggleButton * item = GTK_TOGGLE_BUTTON(mCheckButton);
|
||||
|
||||
item->active = (gboolean) mState;
|
||||
|
||||
gtk_widget_queue_draw(GTK_WIDGET(item));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set this button label
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsCheckButton::GetState(PRBool& aState)
|
||||
{
|
||||
aState = mState;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set this Checkbox label
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsCheckButton::SetLabel(const nsString& aText)
|
||||
{
|
||||
if (mWidget) {
|
||||
NS_ALLOC_STR_BUF(label, aText, 256);
|
||||
if (mLabel) {
|
||||
gtk_label_set(GTK_LABEL(mLabel), label);
|
||||
} else {
|
||||
mLabel = gtk_label_new(label);
|
||||
gtk_misc_set_alignment (GTK_MISC (mLabel), 0.0, 0.5);
|
||||
gtk_container_add(GTK_CONTAINER(mCheckButton), mLabel);
|
||||
gtk_widget_show(mLabel);
|
||||
gtk_signal_connect(GTK_OBJECT(mLabel),
|
||||
"destroy",
|
||||
GTK_SIGNAL_FUNC(DestroySignal),
|
||||
this);
|
||||
}
|
||||
NS_FREE_STR_BUF(label);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get this button label
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsCheckButton::GetLabel(nsString& aBuffer)
|
||||
{
|
||||
aBuffer.SetLength(0);
|
||||
if (mWidget) {
|
||||
char * text;
|
||||
if (mLabel) {
|
||||
gtk_label_get(GTK_LABEL(mLabel), &text);
|
||||
aBuffer.Append(text);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
nsCheckButton::OnToggledSignal(const gboolean aState)
|
||||
{
|
||||
// Untoggle the sonofabitch
|
||||
if (mWidget && mCheckButton)
|
||||
{
|
||||
GtkToggleButton * item = GTK_TOGGLE_BUTTON(mCheckButton);
|
||||
|
||||
item->active = !item->active;
|
||||
|
||||
gtk_widget_queue_draw(GTK_WIDGET(item));
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* static */ gint
|
||||
nsCheckButton::ToggledSignal(GtkWidget * aWidget,
|
||||
gpointer aData)
|
||||
{
|
||||
NS_ASSERTION( nsnull != aWidget, "widget is null");
|
||||
|
||||
nsCheckButton * button = (nsCheckButton *) aData;
|
||||
|
||||
NS_ASSERTION( nsnull != button, "instance pointer is null");
|
||||
|
||||
button->OnToggledSignal(GTK_TOGGLE_BUTTON(aWidget)->active);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// SetBackgroundColor for CheckButton
|
||||
/*virtual*/
|
||||
void nsCheckButton::SetBackgroundColorNative(GdkColor *aColorNor,
|
||||
GdkColor *aColorBri,
|
||||
GdkColor *aColorDark)
|
||||
{
|
||||
// use same style copy as SetFont
|
||||
GtkStyle *style = gtk_style_copy(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0))->style);
|
||||
|
||||
style->bg[GTK_STATE_NORMAL]=*aColorNor;
|
||||
|
||||
// Mouse over button
|
||||
style->bg[GTK_STATE_PRELIGHT]=*aColorBri;
|
||||
|
||||
// Button is down
|
||||
style->bg[GTK_STATE_ACTIVE]=*aColorDark;
|
||||
|
||||
// other states too? (GTK_STATE_ACTIVE, GTK_STATE_PRELIGHT,
|
||||
// GTK_STATE_SELECTED, GTK_STATE_INSENSITIVE)
|
||||
gtk_widget_set_style(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0)), style);
|
||||
// set style for eventbox too
|
||||
gtk_widget_set_style(mWidget, style);
|
||||
|
||||
gtk_style_unref(style);
|
||||
}
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef nsCheckButton_h__
|
||||
#define nsCheckButton_h__
|
||||
|
||||
#include "nsWidget.h"
|
||||
#include "nsICheckButton.h"
|
||||
|
||||
/**
|
||||
* Native GTK+ Checkbox wrapper
|
||||
*/
|
||||
|
||||
|
||||
class nsCheckButton : public nsWidget,
|
||||
public nsICheckButton
|
||||
{
|
||||
|
||||
public:
|
||||
nsCheckButton();
|
||||
virtual ~nsCheckButton();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsICheckButton part
|
||||
NS_IMETHOD SetLabel(const nsString &aText);
|
||||
NS_IMETHOD GetLabel(nsString &aBuffer);
|
||||
NS_IMETHOD SetState(const PRBool aState);
|
||||
NS_IMETHOD GetState(PRBool& aState);
|
||||
|
||||
virtual void OnToggledSignal(const gboolean aState);
|
||||
|
||||
protected:
|
||||
NS_IMETHOD CreateNative(GtkObject *parentWindow);
|
||||
virtual void InitCallbacks(char * aName = nsnull);
|
||||
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
|
||||
|
||||
// Sets background for checkbutton
|
||||
virtual void SetBackgroundColorNative(GdkColor *aColorNor,
|
||||
GdkColor *aColorBri,
|
||||
GdkColor *aColorDark);
|
||||
|
||||
GtkWidget *mLabel;
|
||||
GtkWidget *mCheckButton;
|
||||
|
||||
// We need to maintain our own state to be in sync with the
|
||||
// gecko check controlling frame.
|
||||
PRBool mState;
|
||||
|
||||
private:
|
||||
|
||||
static gint ToggledSignal(GtkWidget * aWidget,
|
||||
gpointer aData);
|
||||
};
|
||||
|
||||
#endif // nsCheckButton_h__
|
||||
@@ -1,872 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include "nsClipboard.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsIClipboardOwner.h"
|
||||
#include "nsITransferable.h" // kTextMime
|
||||
#include "nsISupportsPrimitives.h"
|
||||
|
||||
#include "nsIWidget.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsPrimitiveHelpers.h"
|
||||
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
|
||||
// The class statics:
|
||||
GtkWidget* nsClipboard::sWidget = 0;
|
||||
|
||||
|
||||
#if defined(DEBUG_mcafee) || defined(DEBUG_pavlov)
|
||||
#define DEBUG_CLIPBOARD
|
||||
#endif
|
||||
|
||||
enum {
|
||||
TARGET_NONE,
|
||||
TARGET_TEXT_PLAIN,
|
||||
TARGET_TEXT_XIF,
|
||||
TARGET_TEXT_UNICODE,
|
||||
TARGET_TEXT_HTML,
|
||||
TARGET_AOLMAIL,
|
||||
TARGET_IMAGE_PNG,
|
||||
TARGET_IMAGE_JPEG,
|
||||
TARGET_IMAGE_GIF,
|
||||
// compatibility types
|
||||
TARGET_UTF8,
|
||||
TARGET_UNKNOWN,
|
||||
TARGET_LAST
|
||||
};
|
||||
|
||||
static GdkAtom sSelTypes[TARGET_LAST];
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsClipboard constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsClipboard::nsClipboard() : nsBaseClipboard()
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print("nsClipboard::nsClipboard()\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
//NS_INIT_REFCNT();
|
||||
mIgnoreEmptyNotification = PR_FALSE;
|
||||
mClipboardOwner = nsnull;
|
||||
mTransferable = nsnull;
|
||||
mSelectionData.data = nsnull;
|
||||
mSelectionData.length = 0;
|
||||
|
||||
// initialize the widget, etc we're binding to
|
||||
Init();
|
||||
}
|
||||
|
||||
// XXX if GTK's internal code changes this isn't going to work
|
||||
// copied from gtk code because it is a static function we can't get to it.
|
||||
// need to bug owen taylor about getting this code public.
|
||||
|
||||
typedef struct _GtkSelectionTargetList GtkSelectionTargetList;
|
||||
|
||||
struct _GtkSelectionTargetList {
|
||||
GdkAtom selection;
|
||||
GtkTargetList *list;
|
||||
};
|
||||
|
||||
static const char *gtk_selection_handler_key = "gtk-selection-handlers";
|
||||
|
||||
void __gtk_selection_target_list_remove (GtkWidget *widget)
|
||||
{
|
||||
GtkSelectionTargetList *sellist;
|
||||
GList *tmp_list;
|
||||
GList *lists;
|
||||
lists = (GList*)gtk_object_get_data (GTK_OBJECT (widget), gtk_selection_handler_key);
|
||||
tmp_list = lists;
|
||||
while (tmp_list)
|
||||
{
|
||||
sellist = (GtkSelectionTargetList*)tmp_list->data;
|
||||
gtk_target_list_unref (sellist->list);
|
||||
g_free (sellist);
|
||||
tmp_list = tmp_list->next;
|
||||
}
|
||||
g_list_free (lists);
|
||||
gtk_object_set_data (GTK_OBJECT (widget), gtk_selection_handler_key, NULL);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsClipboard destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsClipboard::~nsClipboard()
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf("nsClipboard::~nsClipboard()\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
// Remove all our event handlers:
|
||||
if (sWidget &&
|
||||
(gdk_selection_owner_get(GDK_SELECTION_PRIMARY) == sWidget->window))
|
||||
gtk_selection_remove_all(sWidget);
|
||||
|
||||
// free the selection data, if any
|
||||
if (mSelectionData.data != nsnull)
|
||||
g_free(mSelectionData.data);
|
||||
|
||||
nsClipboard *cb = (nsClipboard*)gtk_object_get_data(GTK_OBJECT(sWidget), "cb");
|
||||
if (cb != nsnull)
|
||||
{
|
||||
NS_RELEASE(cb);
|
||||
gtk_object_remove_data(GTK_OBJECT(sWidget), "cb");
|
||||
}
|
||||
|
||||
if (sWidget)
|
||||
{
|
||||
gtk_widget_destroy(sWidget);
|
||||
sWidget = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GTK Weirdness!
|
||||
// This is here in the hope of being able to call
|
||||
// gtk_selection_add_targets(w, GDK_SELECTION_PRIMARY,
|
||||
// targets,
|
||||
// 1);
|
||||
// instead of
|
||||
// gtk_selection_add_target(sWidget,
|
||||
// GDK_SELECTION_PRIMARY,
|
||||
// GDK_SELECTION_TYPE_STRING,
|
||||
// GDK_SELECTION_TYPE_STRING);
|
||||
// but it turns out that this changes the whole gtk selection model;
|
||||
// when calling add_targets copy uses selection_clear_event and the
|
||||
// data structure needs to be filled in in a way that we haven't
|
||||
// figured out; when using add_target copy uses selection_get and
|
||||
// the data structure is already filled in as much as it needs to be.
|
||||
// Some gtk internals wizard will need to solve this mystery before
|
||||
// we can use add_targets().
|
||||
//static GtkTargetEntry targets[] = {
|
||||
// { "strings n stuff", GDK_SELECTION_TYPE_STRING, GDK_SELECTION_TYPE_STRING }
|
||||
//};
|
||||
//
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void nsClipboard::Init(void)
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print("nsClipboard::Init\n");
|
||||
#endif
|
||||
|
||||
sSelTypes[TARGET_NONE] = GDK_NONE;
|
||||
sSelTypes[TARGET_TEXT_PLAIN] = gdk_atom_intern(kTextMime, FALSE);
|
||||
sSelTypes[TARGET_TEXT_XIF] = gdk_atom_intern(kXIFMime, FALSE);
|
||||
sSelTypes[TARGET_TEXT_UNICODE] = gdk_atom_intern(kUnicodeMime, FALSE);
|
||||
sSelTypes[TARGET_UTF8] = gdk_atom_intern("UTF8", FALSE);
|
||||
sSelTypes[TARGET_TEXT_HTML] = gdk_atom_intern(kHTMLMime, FALSE);
|
||||
sSelTypes[TARGET_AOLMAIL] = gdk_atom_intern(kAOLMailMime, FALSE);
|
||||
sSelTypes[TARGET_IMAGE_PNG] = gdk_atom_intern(kPNGImageMime, FALSE);
|
||||
sSelTypes[TARGET_IMAGE_JPEG] = gdk_atom_intern(kJPEGImageMime, FALSE);
|
||||
sSelTypes[TARGET_IMAGE_GIF] = gdk_atom_intern(kGIFImageMime, FALSE);
|
||||
// compatibility with other apps
|
||||
|
||||
|
||||
// create invisible widget to use for the clipboard
|
||||
sWidget = gtk_invisible_new();
|
||||
|
||||
// add the clipboard pointer to the widget so we can get it.
|
||||
gtk_object_set_data(GTK_OBJECT(sWidget), "cb", this);
|
||||
|
||||
NS_ADDREF_THIS();
|
||||
|
||||
// Handle selection requests if we called gtk_selection_add_target:
|
||||
gtk_signal_connect(GTK_OBJECT(sWidget), "selection_get",
|
||||
GTK_SIGNAL_FUNC(nsClipboard::SelectionGetCB),
|
||||
nsnull);
|
||||
|
||||
// When someone else takes the selection away:
|
||||
gtk_signal_connect(GTK_OBJECT(sWidget), "selection_clear_event",
|
||||
GTK_SIGNAL_FUNC(nsClipboard::SelectionClearCB),
|
||||
nsnull);
|
||||
|
||||
// Set up the paste handler:
|
||||
gtk_signal_connect(GTK_OBJECT(sWidget), "selection_received",
|
||||
GTK_SIGNAL_FUNC(nsClipboard::SelectionReceivedCB),
|
||||
nsnull);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsClipboard::SetNativeClipboardData()
|
||||
{
|
||||
mIgnoreEmptyNotification = PR_TRUE;
|
||||
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf(" nsClipboard::SetNativeClipboardData()\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
// make sure we have a good transferable
|
||||
if (nsnull == mTransferable) {
|
||||
printf("nsClipboard::SetNativeClipboardData(): no transferable!\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// are we already the owner?
|
||||
if (gdk_selection_owner_get(GDK_SELECTION_PRIMARY) == sWidget->window)
|
||||
{
|
||||
// if so, clear all the targets
|
||||
__gtk_selection_target_list_remove(sWidget);
|
||||
// gtk_selection_remove_all(sWidget);
|
||||
}
|
||||
|
||||
// we arn't already the owner, so we will become it
|
||||
gint have_selection = gtk_selection_owner_set(sWidget,
|
||||
GDK_SELECTION_PRIMARY,
|
||||
GDK_CURRENT_TIME);
|
||||
if (have_selection == 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// get flavor list that includes all flavors that can be written (including ones
|
||||
// obtained through conversion)
|
||||
nsCOMPtr<nsISupportsArray> flavorList;
|
||||
nsresult errCode = mTransferable->FlavorsTransferableCanExport ( getter_AddRefs(flavorList) );
|
||||
if ( NS_FAILED(errCode) )
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRUint32 cnt;
|
||||
flavorList->Count(&cnt);
|
||||
for ( PRUint32 i=0; i<cnt; ++i )
|
||||
{
|
||||
nsCOMPtr<nsISupports> genericFlavor;
|
||||
flavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) );
|
||||
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericFlavor) );
|
||||
if ( currentFlavor ) {
|
||||
nsXPIDLCString flavorStr;
|
||||
currentFlavor->ToString(getter_Copies(flavorStr));
|
||||
gint format = GetFormat(flavorStr);
|
||||
|
||||
// add these types as selection targets
|
||||
RegisterFormat(format);
|
||||
}
|
||||
}
|
||||
|
||||
mIgnoreEmptyNotification = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsClipboard::AddTarget(GdkAtom aAtom)
|
||||
{
|
||||
gtk_selection_add_target(sWidget,
|
||||
GDK_SELECTION_PRIMARY,
|
||||
aAtom, aAtom);
|
||||
}
|
||||
|
||||
gint nsClipboard::GetFormat(const char* aMimeStr)
|
||||
{
|
||||
gint type = TARGET_NONE;
|
||||
nsCAutoString mimeStr ( CBufDescriptor(NS_CONST_CAST(char*,aMimeStr), PR_TRUE, PL_strlen(aMimeStr)+1) );
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" nsClipboard::GetFormat(%s)\n", aMimeStr);
|
||||
#endif
|
||||
if (mimeStr.Equals(kTextMime)) {
|
||||
type = TARGET_TEXT_PLAIN;
|
||||
} else if (mimeStr.Equals("STRING")) {
|
||||
type = TARGET_TEXT_PLAIN;
|
||||
} else if (mimeStr.Equals(kXIFMime)) {
|
||||
type = TARGET_TEXT_XIF;
|
||||
} else if (mimeStr.Equals(kUnicodeMime)) {
|
||||
type = TARGET_TEXT_UNICODE;
|
||||
} else if (mimeStr.Equals(kHTMLMime)) {
|
||||
type = TARGET_TEXT_HTML;
|
||||
} else if (mimeStr.Equals(kAOLMailMime)) {
|
||||
type = TARGET_AOLMAIL;
|
||||
} else if (mimeStr.Equals(kPNGImageMime)) {
|
||||
type = TARGET_IMAGE_PNG;
|
||||
} else if (mimeStr.Equals(kJPEGImageMime)) {
|
||||
type = TARGET_IMAGE_JPEG;
|
||||
} else if (mimeStr.Equals(kGIFImageMime)) {
|
||||
type = TARGET_IMAGE_GIF;
|
||||
}
|
||||
|
||||
#ifdef WE_DO_DND
|
||||
else if (mimeStr.Equals(kDropFilesMime)) {
|
||||
format = CF_HDROP;
|
||||
} else {
|
||||
format = ::RegisterClipboardFormat(aMimeStr);
|
||||
}
|
||||
#endif
|
||||
return type;
|
||||
}
|
||||
|
||||
void nsClipboard::RegisterFormat(gint format)
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" nsClipboard::RegisterFormat(%s)\n", gdk_atom_name(sSelTypes[format]));
|
||||
#endif
|
||||
|
||||
/* when doing the selection_add_target, each case should have the same last parameter
|
||||
which matches the case match */
|
||||
switch(format)
|
||||
{
|
||||
case TARGET_TEXT_PLAIN:
|
||||
// text/plain (default)
|
||||
AddTarget(sSelTypes[format]);
|
||||
|
||||
// STRING (what X uses)
|
||||
AddTarget(GDK_SELECTION_TYPE_STRING);
|
||||
break;
|
||||
|
||||
|
||||
case TARGET_TEXT_XIF:
|
||||
// text/xif (default)
|
||||
AddTarget(sSelTypes[format]);
|
||||
break;
|
||||
|
||||
|
||||
case TARGET_TEXT_UNICODE:
|
||||
// text/unicode (default)
|
||||
AddTarget(sSelTypes[format]);
|
||||
|
||||
// UTF8 (what X uses)
|
||||
AddTarget(sSelTypes[TARGET_UTF8]);
|
||||
break;
|
||||
|
||||
|
||||
case TARGET_TEXT_HTML:
|
||||
// text/html (default)
|
||||
AddTarget(sSelTypes[format]);
|
||||
break;
|
||||
|
||||
|
||||
case TARGET_AOLMAIL:
|
||||
// text/aolmail (default)
|
||||
AddTarget(sSelTypes[format]);
|
||||
break;
|
||||
|
||||
|
||||
case TARGET_IMAGE_PNG:
|
||||
// image/png (default)
|
||||
AddTarget(sSelTypes[format]);
|
||||
break;
|
||||
|
||||
|
||||
case TARGET_IMAGE_JPEG:
|
||||
// image/jpeg (default)
|
||||
AddTarget(sSelTypes[format]);
|
||||
break;
|
||||
|
||||
|
||||
case TARGET_IMAGE_GIF:
|
||||
// image/gif (default)
|
||||
AddTarget(sSelTypes[format]);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
// if we don't match something above, then just add it like its something we know about...
|
||||
AddTarget(sSelTypes[format]);
|
||||
}
|
||||
}
|
||||
|
||||
PRBool nsClipboard::DoRealConvert(GdkAtom type)
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" nsClipboard::DoRealConvert(%li)\n {\n", type);
|
||||
#endif
|
||||
int e = 0;
|
||||
// Set a flag saying that we're blocking waiting for the callback:
|
||||
mBlocking = PR_TRUE;
|
||||
|
||||
//
|
||||
// ask X what kind of data we can get
|
||||
//
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" Doing real conversion of atom type '%s'\n", gdk_atom_name(type));
|
||||
#endif
|
||||
gtk_selection_convert(sWidget,
|
||||
GDK_SELECTION_PRIMARY,
|
||||
type,
|
||||
GDK_CURRENT_TIME);
|
||||
|
||||
// Now we need to wait until the callback comes in ...
|
||||
// i is in case we get a runaway (yuck).
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf(" Waiting for the callback... mBlocking = %d\n", mBlocking);
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
for (e=0; mBlocking == PR_TRUE && e < 1000; ++e)
|
||||
{
|
||||
gtk_main_iteration_do(PR_TRUE);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" }\n");
|
||||
#endif
|
||||
|
||||
if (mSelectionData.length > 0)
|
||||
return PR_TRUE;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/* return PR_TRUE if we have converted or PR_FALSE if we havn't and need to keep being called */
|
||||
PRBool nsClipboard::DoConvert(gint format)
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" nsClipboard::DoConvert(%s)\n", gdk_atom_name(sSelTypes[format]));
|
||||
#endif
|
||||
|
||||
/* when doing the selection_add_target, each case should have the same last parameter
|
||||
which matches the case match */
|
||||
PRBool r = PR_FALSE;
|
||||
|
||||
switch(format)
|
||||
{
|
||||
case TARGET_TEXT_PLAIN:
|
||||
r = DoRealConvert(sSelTypes[format]);
|
||||
if (r) return r;
|
||||
r = DoRealConvert(GDK_SELECTION_TYPE_STRING);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case TARGET_TEXT_XIF:
|
||||
r = DoRealConvert(sSelTypes[format]);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case TARGET_TEXT_UNICODE:
|
||||
r = DoRealConvert(sSelTypes[format]);
|
||||
if (r) return r;
|
||||
r = DoRealConvert(sSelTypes[TARGET_UTF8]);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case TARGET_TEXT_HTML:
|
||||
r = DoRealConvert(sSelTypes[format]);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case TARGET_AOLMAIL:
|
||||
r = DoRealConvert(sSelTypes[format]);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case TARGET_IMAGE_PNG:
|
||||
r = DoRealConvert(sSelTypes[format]);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case TARGET_IMAGE_JPEG:
|
||||
r = DoRealConvert(sSelTypes[format]);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case TARGET_IMAGE_GIF:
|
||||
r = DoRealConvert(sSelTypes[format]);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_print("DoConvert called with bogus format\n");
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// The blocking Paste routine
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP
|
||||
nsClipboard::GetNativeClipboardData(nsITransferable * aTransferable)
|
||||
{
|
||||
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf("nsClipboard::GetNativeClipboardData()\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
// make sure we have a good transferable
|
||||
if (nsnull == aTransferable) {
|
||||
printf(" GetNativeClipboardData: Transferable is null!\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// get flavor list that includes all acceptable flavors (including ones obtained through
|
||||
// conversion)
|
||||
nsCOMPtr<nsISupportsArray> flavorList;
|
||||
nsresult errCode = aTransferable->FlavorsTransferableCanImport ( getter_AddRefs(flavorList) );
|
||||
if ( NS_FAILED(errCode) )
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Walk through flavors and see which flavor matches the one being pasted:
|
||||
PRUint32 cnt;
|
||||
flavorList->Count(&cnt);
|
||||
nsCAutoString foundFlavor;
|
||||
for ( PRUint32 i = 0; i < cnt; ++i ) {
|
||||
nsCOMPtr<nsISupports> genericFlavor;
|
||||
flavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) );
|
||||
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericFlavor) );
|
||||
if ( currentFlavor ) {
|
||||
nsXPIDLCString flavorStr;
|
||||
currentFlavor->ToString ( getter_Copies(flavorStr) );
|
||||
gint format = GetFormat(flavorStr);
|
||||
if (DoConvert(format)) {
|
||||
foundFlavor = flavorStr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf(" Got the callback: '%s', %d\n",
|
||||
mSelectionData.data, mSelectionData.length);
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
// We're back from the callback, no longer blocking:
|
||||
mBlocking = PR_FALSE;
|
||||
|
||||
//
|
||||
// Now we have data in mSelectionData.data.
|
||||
// We just have to copy it to the transferable.
|
||||
//
|
||||
|
||||
#if 0
|
||||
// pinkerton - we have the flavor already from above, so we don't need
|
||||
// to re-derrive it.
|
||||
nsString *name = new nsString((const char*)gdk_atom_name(mSelectionData.type));
|
||||
int format = GetFormat(*name);
|
||||
df->SetString((const char*)gdk_atom_name(sSelTypes[format]));
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsISupports> genericDataWrapper;
|
||||
nsPrimitiveHelpers::CreatePrimitiveForData ( foundFlavor, mSelectionData.data, mSelectionData.length, getter_AddRefs(genericDataWrapper) );
|
||||
aTransferable->SetTransferData(foundFlavor,
|
||||
genericDataWrapper,
|
||||
mSelectionData.length);
|
||||
|
||||
//delete name;
|
||||
|
||||
// transferable is now copying the data, so we can free it.
|
||||
// g_free(mSelectionData.data);
|
||||
mSelectionData.data = nsnull;
|
||||
mSelectionData.length = 0;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the data from a paste comes in (recieved from gdk_selection_convert)
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aSelectionData gtk selection stuff
|
||||
* @param aTime time the selection was requested
|
||||
*/
|
||||
void
|
||||
nsClipboard::SelectionReceivedCB (GtkWidget *aWidget,
|
||||
GtkSelectionData *aSelectionData,
|
||||
guint aTime)
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf(" nsClipboard::SelectionReceivedCB\n {\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
nsClipboard *cb =(nsClipboard *)gtk_object_get_data(GTK_OBJECT(aWidget),
|
||||
"cb");
|
||||
if (!cb)
|
||||
{
|
||||
g_print("no clipboard found.. this is bad.\n");
|
||||
return;
|
||||
}
|
||||
cb->SelectionReceiver(aWidget, aSelectionData);
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" }\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* local method (called from nsClipboard::SelectionReceivedCB)
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aSelectionData gtk selection stuff
|
||||
*/
|
||||
void
|
||||
nsClipboard::SelectionReceiver (GtkWidget *aWidget,
|
||||
GtkSelectionData *aSD)
|
||||
{
|
||||
gint type;
|
||||
|
||||
mBlocking = PR_FALSE;
|
||||
|
||||
if (aSD->length < 0)
|
||||
{
|
||||
printf(" Error retrieving selection: length was %d\n",
|
||||
aSD->length);
|
||||
return;
|
||||
}
|
||||
|
||||
type = TARGET_NONE;
|
||||
for (int i=0; i < TARGET_LAST; i++)
|
||||
{
|
||||
if (sSelTypes[i] == aSD->type)
|
||||
{
|
||||
type = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GDK_TARGET_STRING:
|
||||
case TARGET_UTF8:
|
||||
case TARGET_TEXT_PLAIN:
|
||||
case TARGET_TEXT_XIF:
|
||||
case TARGET_TEXT_UNICODE:
|
||||
case TARGET_TEXT_HTML:
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" Copying mSelectionData pointer -- ");
|
||||
#endif
|
||||
mSelectionData = *aSD;
|
||||
mSelectionData.data = g_new(guchar, aSD->length + 1);
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" Data = %s\n Length = %i\n", aSD->data, aSD->length);
|
||||
#endif
|
||||
memcpy(mSelectionData.data,
|
||||
aSD->data,
|
||||
aSD->length);
|
||||
// Null terminate in case anyone cares,
|
||||
// and so we can print the string for debugging:
|
||||
mSelectionData.data[aSD->length] = '\0';
|
||||
mSelectionData.length = aSD->length;
|
||||
return;
|
||||
|
||||
default:
|
||||
mSelectionData = *aSD;
|
||||
mSelectionData.data = g_new(guchar, aSD->length + 1);
|
||||
memcpy(mSelectionData.data,
|
||||
aSD->data,
|
||||
aSD->length);
|
||||
mSelectionData.length = aSD->length;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Some platforms support deferred notification for putting data on the clipboard
|
||||
* This method forces the data onto the clipboard in its various formats
|
||||
* This may be used if the application going away.
|
||||
*
|
||||
* @result NS_OK if successful.
|
||||
*/
|
||||
NS_IMETHODIMP nsClipboard::ForceDataToClipboard()
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf(" nsClipboard::ForceDataToClipboard()\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
// make sure we have a good transferable
|
||||
if (nsnull == mTransferable) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsClipboard::HasDataMatchingFlavors(nsISupportsArray* aFlavorList, PRBool * outResult)
|
||||
{
|
||||
*outResult = PR_TRUE; // say we always do.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is the callback which is called when another app
|
||||
* requests the selection.
|
||||
*
|
||||
* @param widget The widget
|
||||
* @param aSelectionData Selection data
|
||||
* @param info Value passed in from the callback init
|
||||
* @param time Time when the selection request came in
|
||||
*/
|
||||
void nsClipboard::SelectionGetCB(GtkWidget *widget,
|
||||
GtkSelectionData *aSelectionData,
|
||||
guint aInfo,
|
||||
guint aTime)
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf("nsClipboard::SelectionGetCB\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
nsClipboard *cb = (nsClipboard *)gtk_object_get_data(GTK_OBJECT(widget),
|
||||
"cb");
|
||||
|
||||
void *clipboardData;
|
||||
PRUint32 dataLength;
|
||||
nsresult rv;
|
||||
|
||||
// Make sure we have a transferable:
|
||||
if (!cb->mTransferable) {
|
||||
printf("Clipboard has no transferable!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" aInfo == %d -", aInfo);
|
||||
#endif
|
||||
|
||||
char* dataFlavor = nsnull;
|
||||
|
||||
// switch aInfo (atom) to our enum
|
||||
int type = (int)aInfo;
|
||||
for (int i=0; i < TARGET_LAST; i++)
|
||||
{
|
||||
if (sSelTypes[i] == aInfo)
|
||||
{
|
||||
type = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case GDK_TARGET_STRING:
|
||||
case TARGET_TEXT_PLAIN:
|
||||
dataFlavor = kTextMime;
|
||||
break;
|
||||
case TARGET_TEXT_XIF:
|
||||
dataFlavor = kXIFMime;
|
||||
break;
|
||||
case TARGET_TEXT_UNICODE:
|
||||
case TARGET_UTF8:
|
||||
dataFlavor = kUnicodeMime;
|
||||
break;
|
||||
case TARGET_TEXT_HTML:
|
||||
dataFlavor = kHTMLMime;
|
||||
break;
|
||||
case TARGET_AOLMAIL:
|
||||
dataFlavor = kAOLMailMime;
|
||||
break;
|
||||
case TARGET_IMAGE_PNG:
|
||||
dataFlavor = kPNGImageMime;
|
||||
break;
|
||||
case TARGET_IMAGE_JPEG:
|
||||
dataFlavor = kJPEGImageMime;
|
||||
break;
|
||||
case TARGET_IMAGE_GIF:
|
||||
dataFlavor = kGIFImageMime;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
/* handle outside things */
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print("- aInfo is for %s\n", gdk_atom_name(aInfo));
|
||||
#endif
|
||||
|
||||
// Get data out of transferable.
|
||||
nsCOMPtr<nsISupports> genericDataWrapper;
|
||||
rv = cb->mTransferable->GetTransferData(dataFlavor,
|
||||
getter_AddRefs(genericDataWrapper),
|
||||
&dataLength);
|
||||
nsPrimitiveHelpers::CreateDataFromPrimitive ( dataFlavor, genericDataWrapper, &clipboardData, dataLength );
|
||||
if (NS_SUCCEEDED(rv) && clipboardData && dataLength > 0) {
|
||||
size_t size = 1;
|
||||
// find the number of bytes in the data for the below thing
|
||||
// size_t size = sizeof((void*)((unsigned char)clipboardData[0]));
|
||||
// g_print("************ ***************** ******************* %i\n", size);
|
||||
|
||||
gtk_selection_data_set(aSelectionData,
|
||||
aInfo, size*8,
|
||||
(unsigned char *)clipboardData,
|
||||
dataLength);
|
||||
nsCRT::free ( NS_REINTERPRET_CAST(char*, clipboardData) );
|
||||
}
|
||||
else
|
||||
printf("Transferable didn't support the data flavor\n");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called when another app requests selection ownership
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aEvent the GdkEvent for the selection
|
||||
* @param aData value passed in from the callback init
|
||||
*/
|
||||
void nsClipboard::SelectionClearCB(GtkWidget *aWidget,
|
||||
GdkEventSelection *aEvent,
|
||||
gpointer aData)
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf(" nsClipboard::SelectionClearCB\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
nsClipboard *cb = (nsClipboard *)gtk_object_get_data(GTK_OBJECT(aWidget),
|
||||
"cb");
|
||||
|
||||
cb->EmptyClipboard();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The routine called when another app asks for the content of the selection
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aSelectionData gtk selection stuff
|
||||
* @param aData value passed in from the callback init
|
||||
*/
|
||||
void
|
||||
nsClipboard::SelectionRequestCB (GtkWidget *aWidget,
|
||||
GtkSelectionData *aSelectionData,
|
||||
gpointer aData)
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf(" nsClipboard::SelectionRequestCB\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
}
|
||||
|
||||
/**
|
||||
* ...
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aSelectionData gtk selection stuff
|
||||
* @param aData value passed in from the callback init
|
||||
*/
|
||||
void
|
||||
nsClipboard::SelectionNotifyCB (GtkWidget *aWidget,
|
||||
GtkSelectionData *aSelectionData,
|
||||
gpointer aData)
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf(" nsClipboard::SelectionNotifyCB\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef nsClipboard_h__
|
||||
#define nsClipboard_h__
|
||||
|
||||
#include "nsBaseClipboard.h"
|
||||
#include <gtk/gtk.h>
|
||||
#include <gtk/gtkinvisible.h>
|
||||
|
||||
class nsITransferable;
|
||||
class nsIClipboardOwner;
|
||||
class nsIWidget;
|
||||
|
||||
/**
|
||||
* Native Gtk Clipboard wrapper
|
||||
*/
|
||||
|
||||
class nsClipboard : public nsBaseClipboard
|
||||
{
|
||||
|
||||
public:
|
||||
nsClipboard();
|
||||
virtual ~nsClipboard();
|
||||
|
||||
// nsIClipboard
|
||||
NS_IMETHOD ForceDataToClipboard();
|
||||
NS_IMETHOD HasDataMatchingFlavors(nsISupportsArray* aFlavorList, PRBool * outResult);
|
||||
|
||||
// invisible widget. also used by dragndrop
|
||||
static GtkWidget *sWidget;
|
||||
|
||||
protected:
|
||||
NS_IMETHOD SetNativeClipboardData();
|
||||
NS_IMETHOD GetNativeClipboardData(nsITransferable * aTransferable);
|
||||
|
||||
PRBool mIgnoreEmptyNotification;
|
||||
|
||||
void AddTarget(GdkAtom aAtom);
|
||||
|
||||
gint GetFormat(const char* aMimeStr);
|
||||
void RegisterFormat(gint format);
|
||||
|
||||
|
||||
PRBool DoRealConvert(GdkAtom type);
|
||||
PRBool DoConvert(gint format);
|
||||
|
||||
void Init(void);
|
||||
|
||||
// Used for communicating pasted data
|
||||
// from the asynchronous X routines back to a blocking paste:
|
||||
GtkSelectionData mSelectionData;
|
||||
PRBool mBlocking;
|
||||
|
||||
void SelectionReceiver(GtkWidget *aWidget,
|
||||
GtkSelectionData *aSD);
|
||||
|
||||
/**
|
||||
* This is the callback which is called when another app
|
||||
* requests the selection.
|
||||
*
|
||||
* @param widget The widget
|
||||
* @param aSelectionData Selection data
|
||||
* @param info Value passed in from the callback init
|
||||
* @param time Time when the selection request came in
|
||||
*/
|
||||
static void SelectionGetCB(GtkWidget *aWidget,
|
||||
GtkSelectionData *aSelectionData,
|
||||
guint /*info*/,
|
||||
guint /*time*/);
|
||||
|
||||
/**
|
||||
* Called when another app requests selection ownership
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aEvent the GdkEvent for the selection
|
||||
* @param aData value passed in from the callback init
|
||||
*/
|
||||
static void SelectionClearCB(GtkWidget *aWidget,
|
||||
GdkEventSelection *aEvent,
|
||||
gpointer aData);
|
||||
|
||||
/**
|
||||
* The routine called when another app asks for the content of the selection
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aSelectionData gtk selection stuff
|
||||
* @param aData value passed in from the callback init
|
||||
*/
|
||||
static void SelectionRequestCB(GtkWidget *aWidget,
|
||||
GtkSelectionData *aSelectionData,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* Called when the data from a paste comes in
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aSelectionData gtk selection stuff
|
||||
* @param aTime time the selection was requested
|
||||
*/
|
||||
static void SelectionReceivedCB(GtkWidget *aWidget,
|
||||
GtkSelectionData *aSelectionData,
|
||||
guint aTime);
|
||||
|
||||
|
||||
static void SelectionNotifyCB(GtkWidget *aWidget,
|
||||
GtkSelectionData *aSelectionData,
|
||||
gpointer aData);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // nsClipboard_h__
|
||||
@@ -1,357 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "nsComboBox.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#define DBG 0
|
||||
|
||||
#define INITIAL_MAX_ITEMS 128
|
||||
#define ITEMS_GROWSIZE 128
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsComboBox, nsWidget)
|
||||
NS_IMPL_RELEASE_INHERITED(nsComboBox, nsWidget)
|
||||
NS_IMPL_QUERY_INTERFACE3(nsComboBox, nsIComboBox, nsIListWidget, nsIWidget)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsComboBox constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsComboBox::nsComboBox() : nsWidget(), nsIListWidget(), nsIComboBox()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mMultiSelect = PR_FALSE;
|
||||
mItems = nsnull;
|
||||
mNumItems = 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsComboBox:: destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsComboBox::~nsComboBox()
|
||||
{
|
||||
if (mItems) {
|
||||
for (GList *items = mItems; items; items = (GList*) g_list_next(items)){
|
||||
g_free(items->data);
|
||||
}
|
||||
g_list_free(mItems);
|
||||
}
|
||||
gtk_widget_destroy(mCombo);
|
||||
}
|
||||
|
||||
void nsComboBox::InitCallbacks(char * aName)
|
||||
{
|
||||
InstallButtonPressSignal(mWidget);
|
||||
InstallButtonReleaseSignal(mWidget);
|
||||
|
||||
InstallEnterNotifySignal(mWidget);
|
||||
InstallLeaveNotifySignal(mWidget);
|
||||
|
||||
// These are needed so that the events will go to us and not our parent.
|
||||
AddToEventMask(mWidget,
|
||||
GDK_BUTTON_PRESS_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_ENTER_NOTIFY_MASK |
|
||||
GDK_EXPOSURE_MASK |
|
||||
GDK_FOCUS_CHANGE_MASK |
|
||||
GDK_KEY_PRESS_MASK |
|
||||
GDK_KEY_RELEASE_MASK |
|
||||
GDK_LEAVE_NOTIFY_MASK |
|
||||
GDK_POINTER_MOTION_MASK);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// initializer
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NS_METHOD nsComboBox::SetMultipleSelection(PRBool aMultipleSelections)
|
||||
{
|
||||
mMultiSelect = aMultipleSelections;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// AddItemAt
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NS_METHOD nsComboBox::AddItemAt(nsString &aItem, PRInt32 aPosition)
|
||||
{
|
||||
NS_ALLOC_STR_BUF(val, aItem, 256);
|
||||
mItems = g_list_insert( mItems, g_strdup(val), aPosition );
|
||||
mNumItems++;
|
||||
if (mCombo) {
|
||||
gtk_combo_set_popdown_strings( GTK_COMBO( mCombo ), mItems );
|
||||
}
|
||||
NS_FREE_STR_BUF(val);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Finds an item at a postion
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRInt32 nsComboBox::FindItem(nsString &aItem, PRInt32 aStartPos)
|
||||
{
|
||||
NS_ALLOC_STR_BUF(val, aItem, 256);
|
||||
int i;
|
||||
PRInt32 inx = -1;
|
||||
GList *items = g_list_nth(mItems, aStartPos);
|
||||
for(i=0; items != NULL; items = (GList *) g_list_next(items), i++ )
|
||||
{
|
||||
if(!strcmp(val, (gchar *) items->data))
|
||||
{
|
||||
inx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
NS_FREE_STR_BUF(val);
|
||||
return inx;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// CountItems - Get Item Count
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRInt32 nsComboBox::GetItemCount()
|
||||
{
|
||||
return (PRInt32)mNumItems;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Removes an Item at a specified location
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool nsComboBox::RemoveItemAt(PRInt32 aPosition)
|
||||
{
|
||||
if (aPosition >= 0 && aPosition < mNumItems) {
|
||||
|
||||
g_free(g_list_nth(mItems, aPosition)->data);
|
||||
mItems = g_list_remove_link(mItems, g_list_nth(mItems, aPosition));
|
||||
mNumItems--;
|
||||
if (mCombo) {
|
||||
gtk_combo_set_popdown_strings(GTK_COMBO( mCombo ), mItems);
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
else
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Removes an Item at a specified location
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool nsComboBox::GetItemAt(nsString& anItem, PRInt32 aPosition)
|
||||
{
|
||||
if (aPosition >= 0 && aPosition < mNumItems) {
|
||||
anItem = (gchar *) g_list_nth(mItems, aPosition)->data;
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Gets the selected of selected item
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsComboBox::GetSelectedItem(nsString& aItem)
|
||||
{
|
||||
aItem.Truncate();
|
||||
if (mCombo) {
|
||||
aItem = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(mCombo)->entry));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Gets the list of selected otems
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRInt32 nsComboBox::GetSelectedIndex()
|
||||
{
|
||||
nsString nsstring;
|
||||
GetSelectedItem(nsstring);
|
||||
return FindItem(nsstring, 0);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// SelectItem
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsComboBox::SelectItem(PRInt32 aPosition)
|
||||
{
|
||||
GList *pos;
|
||||
if (!mItems)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
pos = g_list_nth(mItems, aPosition);
|
||||
if (!pos)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mCombo) {
|
||||
gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(mCombo)->entry),
|
||||
(gchar *) pos->data);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// GetSelectedCount
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRInt32 nsComboBox::GetSelectedCount()
|
||||
{
|
||||
if (!mMultiSelect) {
|
||||
PRInt32 inx = GetSelectedIndex();
|
||||
return (inx == -1? 0 : 1);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// GetSelectedIndices
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsComboBox::GetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize)
|
||||
{
|
||||
// this is an error
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Deselect
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsComboBox::Deselect()
|
||||
{
|
||||
if (mMultiSelect) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the native GtkCombo widget
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsComboBox::CreateNative(GtkObject *parentWindow)
|
||||
{
|
||||
mWidget = ::gtk_event_box_new();
|
||||
|
||||
::gtk_widget_set_name(mWidget, "nsComboBox");
|
||||
mCombo = ::gtk_combo_new();
|
||||
gtk_widget_show(mCombo);
|
||||
|
||||
/* make the stuff uneditable */
|
||||
gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(mCombo)->entry), PR_FALSE);
|
||||
|
||||
gtk_signal_connect(GTK_OBJECT(mCombo),
|
||||
"destroy",
|
||||
GTK_SIGNAL_FUNC(DestroySignal),
|
||||
this);
|
||||
gtk_signal_connect(GTK_OBJECT(GTK_COMBO(mCombo)->popwin),
|
||||
"unmap",
|
||||
GTK_SIGNAL_FUNC(UnmapSignal),
|
||||
this);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(mWidget), mCombo);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsComboBox::OnDestroySignal(GtkWidget* aGtkWidget)
|
||||
{
|
||||
if (aGtkWidget == mCombo) {
|
||||
mCombo = nsnull;
|
||||
}
|
||||
else {
|
||||
nsWidget::OnDestroySignal(aGtkWidget);
|
||||
}
|
||||
}
|
||||
|
||||
gint
|
||||
nsComboBox::UnmapSignal(GtkWidget* aGtkWidget, nsComboBox* aCombo)
|
||||
{
|
||||
if (!aCombo) return PR_FALSE;
|
||||
aCombo->OnUnmapSignal(aGtkWidget);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nsComboBox::OnUnmapSignal(GtkWidget * aWidget)
|
||||
{
|
||||
if (!aWidget) return;
|
||||
|
||||
// Generate a NS_CONTROL_CHANGE event and send it to the frame
|
||||
nsGUIEvent event;
|
||||
event.eventStructType = NS_GUI_EVENT;
|
||||
nsPoint point(0,0);
|
||||
InitEvent(event, NS_CONTROL_CHANGE, &point);
|
||||
DispatchWindowEvent(&event);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get handle for style
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
/*virtual*/
|
||||
void nsComboBox::SetFontNative(GdkFont *aFont)
|
||||
{
|
||||
GtkStyle *style = gtk_style_copy(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0))->style);
|
||||
// gtk_style_copy ups the ref count of the font
|
||||
gdk_font_unref (style->font);
|
||||
|
||||
style->font = aFont;
|
||||
gdk_font_ref(style->font);
|
||||
|
||||
gtk_widget_set_style(GTK_BIN (mWidget)->child, style);
|
||||
|
||||
gtk_style_unref(style);
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef nsComboBox_h__
|
||||
#define nsComboBox_h__
|
||||
|
||||
#include "nsWidget.h"
|
||||
#include "nsIComboBox.h"
|
||||
|
||||
/**
|
||||
* Native GTK+ Listbox wrapper
|
||||
*/
|
||||
|
||||
class nsComboBox : public nsWidget,
|
||||
public nsIListWidget,
|
||||
public nsIComboBox
|
||||
{
|
||||
|
||||
public:
|
||||
nsComboBox();
|
||||
virtual ~nsComboBox();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIComboBox interface
|
||||
NS_IMETHOD AddItemAt(nsString &aItem, PRInt32 aPosition);
|
||||
virtual PRInt32 FindItem(nsString &aItem, PRInt32 aStartPos);
|
||||
virtual PRInt32 GetItemCount();
|
||||
virtual PRBool RemoveItemAt(PRInt32 aPosition);
|
||||
virtual PRBool GetItemAt(nsString& anItem, PRInt32 aPosition);
|
||||
NS_IMETHOD GetSelectedItem(nsString& aItem);
|
||||
virtual PRInt32 GetSelectedIndex();
|
||||
NS_IMETHOD SelectItem(PRInt32 aPosition);
|
||||
NS_IMETHOD Deselect() ;
|
||||
|
||||
// nsIComboBox interface
|
||||
NS_IMETHOD SetMultipleSelection(PRBool aMultipleSelections);
|
||||
PRInt32 GetSelectedCount();
|
||||
NS_IMETHOD GetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize);
|
||||
|
||||
virtual void SetFontNative(GdkFont *aFont);
|
||||
|
||||
protected:
|
||||
NS_IMETHOD CreateNative(GtkObject *parentWindow);
|
||||
virtual void InitCallbacks(char * aName = nsnull);
|
||||
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
|
||||
virtual void OnUnmapSignal(GtkWidget* aWidget);
|
||||
static gint UnmapSignal(GtkWidget* aGtkWidget, nsComboBox* aCombo);
|
||||
|
||||
GtkWidget *mCombo; /* workaround for gtkcombo bug */
|
||||
GList *mItems;
|
||||
PRBool mMultiSelect;
|
||||
int mNumItems;
|
||||
};
|
||||
|
||||
#endif // nsComboBox_h__
|
||||
@@ -1,744 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "nsContextMenu.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIMenuBar.h"
|
||||
#include "nsIMenuItem.h"
|
||||
#include "nsIMenuListener.h"
|
||||
#include "nsString.h"
|
||||
#include "nsGtkEventHandler.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
|
||||
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
|
||||
static NS_DEFINE_CID(kMenuItemCID, NS_MENUITEM_CID);
|
||||
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsresult nsContextMenu::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
*aInstancePtr = NULL;
|
||||
|
||||
if (aIID.Equals(nsIMenu::GetIID())) {
|
||||
*aInstancePtr = (void*)(nsIMenu*) this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kISupportsIID)) {
|
||||
*aInstancePtr = (void*)(nsISupports*)(nsIMenu*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(nsIMenuListener::GetIID())) {
|
||||
*aInstancePtr = (void*)(nsIMenuListener*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMPL_ADDREF(nsContextMenu)
|
||||
NS_IMPL_RELEASE(nsContextMenu)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsContextMenu constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsContextMenu::nsContextMenu()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mNumMenuItems = 0;
|
||||
mMenu = nsnull;
|
||||
mParent = nsnull;
|
||||
mListener = nsnull;
|
||||
mConstructCalled = PR_FALSE;
|
||||
|
||||
mDOMNode = nsnull;
|
||||
mWebShell = nsnull;
|
||||
mDOMElement = nsnull;
|
||||
|
||||
mAlignment = "topleft";
|
||||
mAnchorAlignment = "none";
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsContextMenu destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsContextMenu::~nsContextMenu()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the proper widget
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::Create(nsISupports *aParent,
|
||||
const nsString& anAlignment,
|
||||
const nsString& anAnchorAlignment)
|
||||
{
|
||||
if(aParent)
|
||||
{
|
||||
nsIWidget *parent = nsnull;
|
||||
aParent->QueryInterface(nsIWidget::GetIID(), (void**) &parent);
|
||||
if(parent)
|
||||
{
|
||||
mParent = parent;
|
||||
NS_RELEASE(parent);
|
||||
}
|
||||
}
|
||||
|
||||
mAlignment = anAlignment;
|
||||
mAnchorAlignment = anAnchorAlignment;
|
||||
|
||||
mMenu = gtk_menu_new();
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (mMenu), "map",
|
||||
GTK_SIGNAL_FUNC(menu_map_handler),
|
||||
this);
|
||||
gtk_signal_connect (GTK_OBJECT (mMenu), "unmap",
|
||||
GTK_SIGNAL_FUNC(menu_unmap_handler),
|
||||
this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::GetParent(nsISupports*& aParent)
|
||||
{
|
||||
aParent = nsnull;
|
||||
if (nsnull != mParent) {
|
||||
return mParent->QueryInterface(kISupportsIID,
|
||||
(void**)&aParent);
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::AddItem(nsISupports * aItem)
|
||||
{
|
||||
if(aItem)
|
||||
{
|
||||
nsIMenuItem * menuitem = nsnull;
|
||||
aItem->QueryInterface(nsIMenuItem::GetIID(),
|
||||
(void**)&menuitem);
|
||||
if(menuitem)
|
||||
{
|
||||
AddMenuItem(menuitem); // nsMenu now owns this
|
||||
NS_RELEASE(menuitem);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsIMenu * menu = nsnull;
|
||||
aItem->QueryInterface(nsIMenu::GetIID(),
|
||||
(void**)&menu);
|
||||
if(menu)
|
||||
{
|
||||
AddMenu(menu); // nsMenu now owns this
|
||||
NS_RELEASE(menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::AddMenuItem(nsIMenuItem * aMenuItem)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
void *voidData;
|
||||
|
||||
aMenuItem->GetNativeData(voidData);
|
||||
widget = GTK_WIDGET(voidData);
|
||||
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
|
||||
|
||||
// XXX add aMenuItem to internal data structor list
|
||||
// Need to be adding an nsISupports *, not nsIMenuItem *
|
||||
nsISupports * supports = nsnull;
|
||||
aMenuItem->QueryInterface(kISupportsIID,
|
||||
(void**)&supports);
|
||||
{
|
||||
mMenuItemVoidArray.AppendElement(supports);
|
||||
mNumMenuItems++;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::AddMenu(nsIMenu * aMenu)
|
||||
{
|
||||
nsString Label;
|
||||
GtkWidget *newmenu=nsnull;
|
||||
char *labelStr;
|
||||
void *voidData=NULL;
|
||||
|
||||
aMenu->GetLabel(Label);
|
||||
labelStr = Label.ToNewCString();
|
||||
|
||||
// Create nsMenuItem
|
||||
nsIMenuItem * pnsMenuItem = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(kMenuItemCID,
|
||||
nsnull,
|
||||
nsIMenuItem::GetIID(),
|
||||
(void**)&pnsMenuItem);
|
||||
if (NS_OK == rv) {
|
||||
nsISupports * supports = nsnull;
|
||||
QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pnsMenuItem->Create(supports, labelStr, PR_FALSE); //PR_TRUE);
|
||||
NS_RELEASE(supports);
|
||||
|
||||
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
AddItem(supports); // Parent should now own menu item
|
||||
NS_RELEASE(supports);
|
||||
|
||||
void * menuitem = nsnull;
|
||||
pnsMenuItem->GetNativeData(menuitem);
|
||||
|
||||
voidData = NULL;
|
||||
aMenu->GetNativeData(&voidData);
|
||||
newmenu = GTK_WIDGET(voidData);
|
||||
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), newmenu);
|
||||
|
||||
NS_RELEASE(pnsMenuItem);
|
||||
}
|
||||
|
||||
nsCRT::free(labelStr);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::AddSeparator()
|
||||
{
|
||||
// Create nsMenuItem
|
||||
nsIMenuItem * pnsMenuItem = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(
|
||||
kMenuItemCID, nsnull, nsIMenuItem::GetIID(), (void**)&pnsMenuItem);
|
||||
if (NS_OK == rv) {
|
||||
nsString tmp = "separator";
|
||||
nsISupports * supports = nsnull;
|
||||
QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pnsMenuItem->Create(supports, tmp, PR_TRUE);
|
||||
NS_RELEASE(supports);
|
||||
|
||||
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
AddItem(supports); // Parent should now own menu item
|
||||
NS_RELEASE(supports);
|
||||
|
||||
NS_RELEASE(pnsMenuItem);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::GetItemCount(PRUint32 &aCount)
|
||||
{
|
||||
// this should be right.. does it need to be +1 ?
|
||||
aCount = g_list_length(GTK_MENU_SHELL(mMenu)->children);
|
||||
//g_print("nsMenu::GetItemCount = %i\n", aCount);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::GetItemAt(const PRUint32 aCount, nsISupports *& aMenuItem)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::InsertItemAt(const PRUint32 aCount, nsISupports * aMenuItem)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::InsertSeparator(const PRUint32 aCount)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::RemoveItem(const PRUint32 aCount)
|
||||
{
|
||||
#if 0
|
||||
// this may work here better than Removeall(), but i'm not sure how to test this one
|
||||
nsISupports *item = mMenuItemVoidArray[aPos];
|
||||
delete item;
|
||||
mMenuItemVoidArray.RemoveElementAt(aPos);
|
||||
#endif
|
||||
/*
|
||||
gtk_menu_shell_remove (GTK_MENU_SHELL (mMenu), item);
|
||||
|
||||
nsCRT::free(labelStr);
|
||||
|
||||
voidData = NULL;
|
||||
|
||||
aMenu->GetNativeData(&voidData);
|
||||
newmenu = GTK_WIDGET(voidData);
|
||||
|
||||
gtk_menu_item_remove_submenu (GTK_MENU_ITEM (item));
|
||||
*/
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::RemoveAll()
|
||||
{
|
||||
//g_print("nsMenu::RemoveAll()\n");
|
||||
#undef DEBUG_pavlov
|
||||
#ifdef DEBUG_pavlov
|
||||
// this doesn't work quite right, but this is about all that should really be needed
|
||||
int i=0;
|
||||
nsIMenu *menu = nsnull;
|
||||
nsIMenuItem *menuitem = nsnull;
|
||||
nsISupports *item = nsnull;
|
||||
|
||||
for (i=mMenuItemVoidArray.Count(); i>0; i--)
|
||||
{
|
||||
item = (nsISupports*)mMenuItemVoidArray[i-1];
|
||||
|
||||
if(nsnull != item)
|
||||
{
|
||||
if (NS_OK == item->QueryInterface(nsIMenuItem::GetIID(), (void**)&menuitem))
|
||||
{
|
||||
// we do this twice because we have to do it once for QueryInterface,
|
||||
// then we want to get rid of it.
|
||||
// g_print("remove nsMenuItem\n");
|
||||
NS_RELEASE(menuitem);
|
||||
NS_RELEASE(item);
|
||||
menuitem = nsnull;
|
||||
} else if (NS_OK == item->QueryInterface(nsIMenu::GetIID(), (void**)&menu)) {
|
||||
#ifdef NOISY_MENUS
|
||||
g_print("remove nsMenu\n");
|
||||
#endif
|
||||
NS_RELEASE(menu);
|
||||
NS_RELEASE(item);
|
||||
menu = nsnull;
|
||||
}
|
||||
// mMenuItemVoidArray.RemoveElementAt(i-1);
|
||||
}
|
||||
}
|
||||
mMenuItemVoidArray.Clear();
|
||||
|
||||
return NS_OK;
|
||||
#else
|
||||
for (int i = mMenuItemVoidArray.Count(); i > 0; i--) {
|
||||
if(nsnull != mMenuItemVoidArray[i-1]) {
|
||||
nsIMenuItem * menuitem = nsnull;
|
||||
((nsISupports*)mMenuItemVoidArray[i-1])->QueryInterface(nsIMenuItem::GetIID(),
|
||||
(void**)&menuitem);
|
||||
if(menuitem) {
|
||||
void *gtkmenuitem = nsnull;
|
||||
menuitem->GetNativeData(gtkmenuitem);
|
||||
if (gtkmenuitem) {
|
||||
gtk_widget_ref(GTK_WIDGET(gtkmenuitem));
|
||||
//gtk_widget_destroy(GTK_WIDGET(gtkmenuitem));
|
||||
g_print("%p, %p\n",
|
||||
GTK_WIDGET(GTK_CONTAINER(GTK_MENU_SHELL(GTK_MENU(mMenu)))),
|
||||
GTK_WIDGET(GTK_WIDGET(gtkmenuitem)->parent));
|
||||
gtk_container_remove(GTK_CONTAINER(GTK_MENU_SHELL(GTK_MENU(mMenu))),
|
||||
GTK_WIDGET(gtkmenuitem));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
nsIMenu * menu= nsnull;
|
||||
((nsISupports*)mMenuItemVoidArray[i-1])->QueryInterface(nsIMenu::GetIID(),
|
||||
(void**)&menu);
|
||||
if(menu)
|
||||
{
|
||||
void * gtkmenu = nsnull;
|
||||
menu->GetNativeData(>kmenu);
|
||||
|
||||
if(gtkmenu){
|
||||
g_print("nsMenu::RemoveAll() trying to remove nsMenu");
|
||||
|
||||
//gtk_menu_item_remove_submenu (GTK_MENU_ITEM (item));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
//g_print("end RemoveAll\n");
|
||||
return NS_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::GetNativeData(void ** aData)
|
||||
{
|
||||
*aData = (void *)mMenu;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::AddMenuListener(nsIMenuListener * aMenuListener)
|
||||
{
|
||||
mListener = aMenuListener;
|
||||
NS_ADDREF(mListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::RemoveMenuListener(nsIMenuListener * aMenuListener)
|
||||
{
|
||||
if (aMenuListener == mListener) {
|
||||
NS_IF_RELEASE(mListener);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// nsIMenuListener interface
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsContextMenu::MenuItemSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
if (nsnull != mListener) {
|
||||
mListener->MenuSelected(aMenuEvent);
|
||||
}
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
void menu_popup_position(GtkMenu *menu,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gpointer data)
|
||||
{
|
||||
nsContextMenu *cm = (nsContextMenu*)data;
|
||||
*x = cm->GetX();
|
||||
*y = cm->GetY();
|
||||
}
|
||||
|
||||
nsEventStatus nsContextMenu::MenuSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
MenuConstruct(aMenuEvent,
|
||||
mParent,
|
||||
mDOMNode,
|
||||
mWebShell);
|
||||
|
||||
//GtkWidget *parent = GTK_WIDGET(mParent->GetNativeData(NS_NATIVE_WIDGET));
|
||||
gtk_menu_popup (GTK_MENU(mMenu),
|
||||
(GtkWidget*)nsnull, (GtkWidget*)nsnull,
|
||||
menu_popup_position,
|
||||
this, 1, GDK_CURRENT_TIME);
|
||||
/*
|
||||
if (nsnull != mListener) {
|
||||
mListener->MenuSelected(aMenuEvent);
|
||||
}
|
||||
*/
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsIMenuItem * nsContextMenu::FindMenuItem(nsIContextMenu * aMenu, PRUint32 aId)
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsContextMenu::MenuDeselected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
if (nsnull != mListener) {
|
||||
mListener->MenuDeselected(aMenuEvent);
|
||||
}
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsContextMenu::MenuConstruct(const nsMenuEvent &aMenuEvent,
|
||||
nsIWidget *aParentWindow,
|
||||
void *menuNode,
|
||||
void *aWebShell)
|
||||
{
|
||||
//g_print("nsMenu::MenuConstruct called \n");
|
||||
if(menuNode){
|
||||
SetDOMNode((nsIDOMNode*)menuNode);
|
||||
}
|
||||
|
||||
if(!aWebShell){
|
||||
aWebShell = mWebShell;
|
||||
}
|
||||
|
||||
// First open the menu.
|
||||
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
|
||||
if (domElement)
|
||||
domElement->SetAttribute("open", "true");
|
||||
|
||||
// Begin menuitem inner loop
|
||||
nsCOMPtr<nsIDOMNode> menuitemNode;
|
||||
((nsIDOMNode*)mDOMNode)->GetFirstChild(getter_AddRefs(menuitemNode));
|
||||
|
||||
unsigned short menuIndex = 0;
|
||||
|
||||
while (menuitemNode) {
|
||||
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
|
||||
if (menuitemElement) {
|
||||
nsString menuitemNodeType;
|
||||
nsString menuitemName;
|
||||
menuitemElement->GetNodeName(menuitemNodeType);
|
||||
if (menuitemNodeType.Equals("menuitem")) {
|
||||
// LoadMenuItem
|
||||
LoadMenuItem(this,
|
||||
menuitemElement,
|
||||
menuitemNode,
|
||||
menuIndex,
|
||||
(nsIWebShell*)aWebShell);
|
||||
} else if (menuitemNodeType.Equals("separator")) {
|
||||
AddSeparator();
|
||||
} else if (menuitemNodeType.Equals("menu")) {
|
||||
// Load a submenu
|
||||
LoadSubMenu(this, menuitemElement, menuitemNode);
|
||||
}
|
||||
}
|
||||
|
||||
++menuIndex;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
|
||||
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
|
||||
} // end menu item innner loop
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsContextMenu::MenuDestruct(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
// Close the node.
|
||||
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
|
||||
if (domElement)
|
||||
domElement->RemoveAttribute("open");
|
||||
|
||||
//g_print("nsMenu::MenuDestruct called \n");
|
||||
mConstructCalled = PR_FALSE;
|
||||
RemoveAll();
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
void nsContextMenu::LoadMenuItem(nsIMenu *pParentMenu,
|
||||
nsIDOMElement *menuitemElement,
|
||||
nsIDOMNode *menuitemNode,
|
||||
unsigned short menuitemIndex,
|
||||
nsIWebShell *aWebShell)
|
||||
{
|
||||
static const char* NS_STRING_TRUE = "true";
|
||||
nsString disabled;
|
||||
nsString menuitemName;
|
||||
nsString menuitemCmd;
|
||||
|
||||
menuitemElement->GetAttribute(nsAutoString("disabled"), disabled);
|
||||
menuitemElement->GetAttribute(nsAutoString("name"), menuitemName);
|
||||
menuitemElement->GetAttribute(nsAutoString("cmd"), menuitemCmd);
|
||||
|
||||
// Create nsMenuItem
|
||||
nsIMenuItem * pnsMenuItem = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(kMenuItemCID,
|
||||
nsnull,
|
||||
nsIMenuItem::GetIID(),
|
||||
(void**)&pnsMenuItem);
|
||||
if (NS_OK == rv) {
|
||||
pnsMenuItem->Create(pParentMenu, menuitemName, PR_FALSE);
|
||||
|
||||
nsISupports * supports = nsnull;
|
||||
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pParentMenu->AddItem(supports); // Parent should now own menu item
|
||||
NS_RELEASE(supports);
|
||||
|
||||
if(disabled == NS_STRING_TRUE) {
|
||||
pnsMenuItem->SetEnabled(PR_FALSE);
|
||||
}
|
||||
|
||||
// Create MenuDelegate - this is the intermediator inbetween
|
||||
// the DOM node and the nsIMenuItem
|
||||
// The nsWebShellWindow wacthes for Document changes and then notifies the
|
||||
// the appropriate nsMenuDelegate object
|
||||
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(menuitemNode));
|
||||
if (!domElement) {
|
||||
//return NS_ERROR_FAILURE;
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString cmdAtom("onclick");
|
||||
nsString cmdName;
|
||||
|
||||
domElement->GetAttribute(cmdAtom, cmdName);
|
||||
|
||||
pnsMenuItem->SetCommand(cmdName);
|
||||
// DO NOT use passed in webshell because of messed up windows dynamic loading
|
||||
// code.
|
||||
pnsMenuItem->SetWebShell(mWebShell);
|
||||
pnsMenuItem->SetDOMElement(domElement);
|
||||
|
||||
NS_RELEASE(pnsMenuItem);
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
void nsContextMenu::LoadSubMenu(nsIMenu *pParentMenu,
|
||||
nsIDOMElement *menuElement,
|
||||
nsIDOMNode *menuNode)
|
||||
{
|
||||
nsString menuName;
|
||||
menuElement->GetAttribute(nsAutoString("name"), menuName);
|
||||
//printf("Creating Menu [%s] \n", menuName.ToNewCString()); // this leaks
|
||||
|
||||
// Create nsMenu
|
||||
nsIMenu * pnsMenu = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(kMenuCID,
|
||||
nsnull,
|
||||
nsIMenu::GetIID(),
|
||||
(void**)&pnsMenu);
|
||||
if (NS_OK == rv) {
|
||||
// Call Create
|
||||
nsISupports * supports = nsnull;
|
||||
pParentMenu->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pnsMenu->Create(supports, menuName);
|
||||
NS_RELEASE(supports); // Balance QI
|
||||
|
||||
// Set nsMenu Name
|
||||
pnsMenu->SetLabel(menuName);
|
||||
|
||||
supports = nsnull;
|
||||
pnsMenu->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pParentMenu->AddItem(supports); // parent takes ownership
|
||||
NS_RELEASE(supports);
|
||||
|
||||
pnsMenu->SetWebShell(mWebShell);
|
||||
pnsMenu->SetDOMNode(menuNode);
|
||||
|
||||
/*
|
||||
// Begin menuitem inner loop
|
||||
unsigned short menuIndex = 0;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> menuitemNode;
|
||||
menuNode->GetFirstChild(getter_AddRefs(menuitemNode));
|
||||
while (menuitemNode) {
|
||||
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
|
||||
if (menuitemElement) {
|
||||
nsString menuitemNodeType;
|
||||
menuitemElement->GetNodeName(menuitemNodeType);
|
||||
|
||||
#ifdef DEBUG_saari
|
||||
printf("Type [%s] %d\n", menuitemNodeType.ToNewCString(), menuitemNodeType.Equals("separator"));
|
||||
#endif
|
||||
|
||||
if (menuitemNodeType.Equals("menuitem")) {
|
||||
// Load a menuitem
|
||||
LoadMenuItem(pnsMenu, menuitemElement, menuitemNode, menuIndex, mWebShell);
|
||||
} else if (menuitemNodeType.Equals("separator")) {
|
||||
pnsMenu->AddSeparator();
|
||||
} else if (menuitemNodeType.Equals("menu")) {
|
||||
// Add a submenu
|
||||
LoadSubMenu(pnsMenu, menuitemElement, menuitemNode);
|
||||
}
|
||||
}
|
||||
++menuIndex;
|
||||
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
|
||||
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
|
||||
} // end menu item innner loop
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
void nsContextMenu::LoadMenuItem(nsIContextMenu *pParentMenu,
|
||||
nsIDOMElement *menuitemElement,
|
||||
nsIDOMNode *menuitemNode,
|
||||
unsigned short menuitemIndex,
|
||||
nsIWebShell *aWebShell)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
void nsContextMenu::LoadSubMenu(nsIContextMenu *pParentMenu,
|
||||
nsIDOMElement *menuElement,
|
||||
nsIDOMNode *menuNode)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::SetLocation(PRInt32 aX, PRInt32 aY)
|
||||
{
|
||||
mX = aX;
|
||||
mY = aY;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// local methods
|
||||
gint nsContextMenu::GetX(void)
|
||||
{
|
||||
return mX;
|
||||
}
|
||||
|
||||
gint nsContextMenu::GetY(void)
|
||||
{
|
||||
return mY;
|
||||
}
|
||||
// end silly local methods
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::SetDOMNode(nsIDOMNode *aMenuNode)
|
||||
{
|
||||
mDOMNode = aMenuNode;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::SetDOMElement(nsIDOMElement *aMenuElement)
|
||||
{
|
||||
mDOMElement = aMenuElement;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::SetWebShell(nsIWebShell *aWebShell)
|
||||
{
|
||||
mWebShell = aWebShell;
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef nsContextMenu_h__
|
||||
#define nsContextMenu_h__
|
||||
|
||||
#include "nsIContextMenu.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIWebShell.h"
|
||||
|
||||
class nsIMenuListener;
|
||||
|
||||
/**
|
||||
* Native Win32 button wrapper
|
||||
*/
|
||||
|
||||
class nsContextMenu : public nsIContextMenu, public nsIMenuListener
|
||||
{
|
||||
|
||||
public:
|
||||
nsContextMenu();
|
||||
virtual ~nsContextMenu();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
//nsIMenuListener interface
|
||||
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuConstruct(const nsMenuEvent & aMenuEvent,
|
||||
nsIWidget * aParentWindow,
|
||||
void * menubarNode,
|
||||
void * aWebShell);
|
||||
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
|
||||
|
||||
// nsIMenu Methods
|
||||
NS_IMETHOD Create(nsISupports * aParent,
|
||||
const nsString& anAlignment,
|
||||
const nsString& aAnchorAlign);
|
||||
NS_IMETHOD GetParent(nsISupports *&aParent);
|
||||
|
||||
NS_IMETHOD AddItem(nsISupports * aItem);
|
||||
|
||||
NS_IMETHOD AddSeparator();
|
||||
NS_IMETHOD GetItemCount(PRUint32 &aCount);
|
||||
NS_IMETHOD GetItemAt(const PRUint32 aPos, nsISupports *& aMenuItem);
|
||||
NS_IMETHOD InsertItemAt(const PRUint32 aPos, nsISupports * aMenuItem);
|
||||
NS_IMETHOD RemoveItem(const PRUint32 aPos);
|
||||
NS_IMETHOD RemoveAll();
|
||||
NS_IMETHOD GetNativeData(void** aData);
|
||||
|
||||
NS_IMETHOD AddMenuListener(nsIMenuListener * aMenuListener);
|
||||
NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener);
|
||||
|
||||
//
|
||||
NS_IMETHOD AddMenuItem(nsIMenuItem * aMenuItem);
|
||||
NS_IMETHOD AddMenu(nsIMenu * aMenu);
|
||||
NS_IMETHOD InsertSeparator(const PRUint32 aCount);
|
||||
|
||||
NS_IMETHOD SetDOMNode(nsIDOMNode * menuNode);
|
||||
NS_IMETHOD SetDOMElement(nsIDOMElement * menuElement);
|
||||
NS_IMETHOD SetWebShell(nsIWebShell * aWebShell);
|
||||
NS_IMETHOD SetLocation(PRInt32 aX, PRInt32 aY);
|
||||
|
||||
gint GetX(void);
|
||||
gint GetY(void);
|
||||
|
||||
|
||||
protected:
|
||||
nsIMenuBar * GetMenuBar(nsIMenu * aMenu);
|
||||
nsIWidget * GetParentWidget();
|
||||
char* GetACPString(nsString& aStr);
|
||||
|
||||
void LoadMenuItem(nsIMenu * pParentMenu,
|
||||
nsIDOMElement * menuitemElement,
|
||||
nsIDOMNode * menuitemNode,
|
||||
unsigned short menuitemIndex,
|
||||
nsIWebShell * aWebShell);
|
||||
|
||||
void LoadSubMenu(nsIMenu * pParentMenu,
|
||||
nsIDOMElement * menuElement,
|
||||
nsIDOMNode * menuNode);
|
||||
|
||||
void LoadMenuItem(nsIContextMenu * pParentMenu,
|
||||
nsIDOMElement * menuitemElement,
|
||||
nsIDOMNode * menuitemNode,
|
||||
unsigned short menuitemIndex,
|
||||
nsIWebShell * aWebShell);
|
||||
|
||||
void LoadSubMenu(nsIContextMenu * pParentMenu,
|
||||
nsIDOMElement * menuElement,
|
||||
nsIDOMNode * menuNode);
|
||||
|
||||
nsIMenuItem * FindMenuItem(nsIContextMenu * aMenu, PRUint32 aId);
|
||||
|
||||
nsString mLabel;
|
||||
PRUint32 mNumMenuItems;
|
||||
GtkWidget *mMenu;
|
||||
|
||||
nsVoidArray mMenuItemVoidArray;
|
||||
|
||||
nsIWidget *mParent;
|
||||
nsIMenuListener * mListener;
|
||||
|
||||
PRBool mConstructCalled;
|
||||
nsIDOMNode * mDOMNode;
|
||||
nsIWebShell * mWebShell;
|
||||
nsIDOMElement * mDOMElement;
|
||||
|
||||
nsString mAlignment;
|
||||
nsString mAnchorAlignment;
|
||||
|
||||
PRInt32 mX;
|
||||
PRInt32 mY;
|
||||
};
|
||||
|
||||
#endif // nsContextMenu_h__
|
||||
@@ -1,592 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include "nsDragService.h"
|
||||
|
||||
#include "nsITransferable.h"
|
||||
#include "nsString.h"
|
||||
#include "nsClipboard.h"
|
||||
#include "nsIRegion.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsPrimitiveHelpers.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsXPIDLString.h"
|
||||
|
||||
#include "nsWidgetsCID.h"
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsDragService, nsBaseDragService)
|
||||
NS_IMPL_RELEASE_INHERITED(nsDragService, nsBaseDragService)
|
||||
NS_IMPL_QUERY_INTERFACE2(nsDragService, nsIDragService, nsIDragSession)
|
||||
|
||||
#define DEBUG_DRAG 1
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// DragService constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsDragService::nsDragService()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mWidget = nsnull;
|
||||
mNumFlavors = 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// DragService destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsDragService::~nsDragService()
|
||||
{
|
||||
}
|
||||
|
||||
enum {
|
||||
TARGET_STRING,
|
||||
TARGET_ROOTWIN
|
||||
};
|
||||
|
||||
static GtkTargetEntry target_table[] = {
|
||||
{ "STRING", 0, TARGET_STRING },
|
||||
{ "text/plain", 0, TARGET_STRING },
|
||||
{ "application/x-rootwin-drop", 0, TARGET_ROOTWIN }
|
||||
};
|
||||
|
||||
static guint n_targets = sizeof(target_table) / sizeof(target_table[0]);
|
||||
|
||||
|
||||
NS_IMETHODIMP nsDragService::StartDragSession()
|
||||
{
|
||||
printf("nsDragService::StartDragSession()\n");
|
||||
nsBaseDragService::StartDragSession();
|
||||
|
||||
/*
|
||||
gtk_drag_source_set(mWidget,
|
||||
GDK_MODIFIER_MASK,
|
||||
targetlist,
|
||||
mNumFlavors,
|
||||
action);
|
||||
*/
|
||||
gtk_drag_source_set(mWidget,
|
||||
GDK_MODIFIER_MASK,
|
||||
target_table,
|
||||
n_targets,
|
||||
mActionType);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDragService::EndDragSession()
|
||||
{
|
||||
printf("nsDragService::EndDragSession()\n");
|
||||
nsBaseDragService::EndDragSession();
|
||||
|
||||
gtk_drag_source_unset(mWidget);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsDragService::InvokeDragSession (nsISupportsArray *aTransferableArray,
|
||||
nsIScriptableRegion *aRegion,
|
||||
PRUint32 aActionType)
|
||||
{
|
||||
mWidget = gtk_get_event_widget(gtk_get_current_event());
|
||||
|
||||
// add the flavors from the transferables. Cache this array for the send data proc
|
||||
GtkTargetList *targetlist = RegisterDragItemsAndFlavors(aTransferableArray);
|
||||
|
||||
switch (aActionType)
|
||||
{
|
||||
case DRAGDROP_ACTION_NONE:
|
||||
mActionType = GDK_ACTION_DEFAULT;
|
||||
break;
|
||||
case DRAGDROP_ACTION_COPY:
|
||||
mActionType = GDK_ACTION_COPY;
|
||||
break;
|
||||
case DRAGDROP_ACTION_MOVE:
|
||||
mActionType = GDK_ACTION_MOVE;
|
||||
break;
|
||||
case DRAGDROP_ACTION_LINK:
|
||||
mActionType = GDK_ACTION_LINK;
|
||||
break;
|
||||
}
|
||||
|
||||
StartDragSession();
|
||||
|
||||
// XXX 3rd param ??? & last param should be a real event...
|
||||
gtk_drag_begin(mWidget, targetlist, mActionType, 1, gtk_get_current_event());
|
||||
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
// we have to synthesize the native event because we may be called from JavaScript
|
||||
// through XPConnect. In that case, we only have a DOM event and no way to
|
||||
// get to the native event. As a consequence, we just always fake it.
|
||||
Point globalMouseLoc;
|
||||
::GetMouse(&globalMouseLoc);
|
||||
::LocalToGlobal(&globalMouseLoc);
|
||||
WindowPtr theWindow = nsnull;
|
||||
if ( ::FindWindow(globalMouseLoc, &theWindow) != inContent ) {
|
||||
// debugging sanity check
|
||||
#ifdef NS_DEBUG
|
||||
DebugStr("\pAbout to start drag, but FindWindow() != inContent; g");
|
||||
#endif
|
||||
}
|
||||
EventRecord theEvent;
|
||||
theEvent.what = mouseDown;
|
||||
theEvent.message = reinterpret_cast<UInt32>(theWindow);
|
||||
theEvent.when = 0;
|
||||
theEvent.where = globalMouseLoc;
|
||||
theEvent.modifiers = 0;
|
||||
|
||||
RgnHandle theDragRgn = ::NewRgn();
|
||||
BuildDragRegion ( aDragRgn, globalMouseLoc, theDragRgn );
|
||||
|
||||
// register drag send proc which will call us back when asked for the actual
|
||||
// flavor data (instead of placing it all into the drag manager)
|
||||
::SetDragSendProc ( theDragRef, sDragSendDataUPP, this );
|
||||
|
||||
// start the drag. Be careful, mDragRef will be invalid AFTER this call (it is
|
||||
// reset by the dragTrackingHandler).
|
||||
::TrackDrag ( theDragRef, &theEvent, theDragRgn );
|
||||
|
||||
// clean up after ourselves
|
||||
::DisposeRgn ( theDragRgn );
|
||||
result = ::DisposeDrag ( theDragRef );
|
||||
NS_ASSERTION ( result == noErr, "Error disposing drag" );
|
||||
mDragRef = 0L;
|
||||
mDataItems = nsnull;
|
||||
|
||||
return NS_OK;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
GtkTargetList *
|
||||
nsDragService::RegisterDragItemsAndFlavors(nsISupportsArray *inArray)
|
||||
{
|
||||
unsigned int numDragItems = 0;
|
||||
inArray->Count(&numDragItems);
|
||||
|
||||
GtkTargetList *targetlist;
|
||||
targetlist = gtk_target_list_new(nsnull, numDragItems);
|
||||
|
||||
for (unsigned int i = 0; i < numDragItems; ++i)
|
||||
{
|
||||
nsCOMPtr<nsISupports> genericItem;
|
||||
inArray->GetElementAt (i, getter_AddRefs(genericItem));
|
||||
nsCOMPtr<nsITransferable> currItem (do_QueryInterface(genericItem));
|
||||
if (currItem)
|
||||
{
|
||||
nsCOMPtr<nsISupportsArray> flavorList;
|
||||
if (NS_SUCCEEDED(currItem->FlavorsTransferableCanExport(getter_AddRefs(flavorList))))
|
||||
{
|
||||
flavorList->Count (&mNumFlavors);
|
||||
for (PRUint32 flavorIndex = 0; flavorIndex < mNumFlavors; ++flavorIndex)
|
||||
{
|
||||
nsCOMPtr<nsISupports> genericWrapper;
|
||||
flavorList->GetElementAt ( flavorIndex, getter_AddRefs(genericWrapper) );
|
||||
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericWrapper) );
|
||||
if ( currentFlavor )
|
||||
{
|
||||
nsXPIDLCString flavorStr;
|
||||
currentFlavor->ToString ( getter_Copies(flavorStr) );
|
||||
|
||||
// register native flavors
|
||||
GdkAtom atom = gdk_atom_intern(flavorStr, PR_TRUE);
|
||||
gtk_target_list_add(targetlist, atom, 1, atom);
|
||||
}
|
||||
|
||||
} // foreach flavor in item
|
||||
} // if valid flavor list
|
||||
} // if item is a transferable
|
||||
} // foreach drag item
|
||||
|
||||
return targetlist;
|
||||
}
|
||||
|
||||
|
||||
/* return PR_TRUE if we have converted or PR_FALSE if we havn't and need to keep being called */
|
||||
PRBool nsDragService::DoConvert(GdkAtom type)
|
||||
{
|
||||
#ifdef DEBUG_DRAG
|
||||
g_print(" nsDragService::DoRealConvert(%li)\n {\n", type);
|
||||
#endif
|
||||
int e = 0;
|
||||
// Set a flag saying that we're blocking waiting for the callback:
|
||||
mBlocking = PR_TRUE;
|
||||
|
||||
//
|
||||
// ask X what kind of data we can get
|
||||
//
|
||||
#ifdef DEBUG_DRAG
|
||||
g_print(" Doing real conversion of atom type '%s'\n", gdk_atom_name(type));
|
||||
#endif
|
||||
gtk_selection_convert(mWidget,
|
||||
GDK_SELECTION_PRIMARY,
|
||||
type,
|
||||
GDK_CURRENT_TIME);
|
||||
|
||||
// Now we need to wait until the callback comes in ...
|
||||
// i is in case we get a runaway (yuck).
|
||||
#ifdef DEBUG_DRAG
|
||||
printf(" Waiting for the callback... mBlocking = %d\n", mBlocking);
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
for (e=0; mBlocking == PR_TRUE && e < 1000; ++e)
|
||||
{
|
||||
gtk_main_iteration_do(PR_TRUE);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DRAG
|
||||
g_print(" }\n");
|
||||
#endif
|
||||
|
||||
if (mSelectionData.length > 0)
|
||||
return PR_TRUE;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/**
|
||||
* Called when the data from a drag comes in (recieved from gdk_selection_convert)
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aSelectionData gtk selection stuff
|
||||
* @param aTime time the selection was requested
|
||||
*/
|
||||
void
|
||||
nsDragService::SelectionReceivedCB (GtkWidget *aWidget,
|
||||
GdkDragContext *aContext,
|
||||
gint aX,
|
||||
gint aY,
|
||||
GtkSelectionData *aSelectionData,
|
||||
guint aInfo,
|
||||
guint aTime)
|
||||
{
|
||||
#ifdef DEBUG_DRAG
|
||||
printf(" nsDragService::SelectionReceivedCB\n {\n");
|
||||
#endif
|
||||
nsDragService *ds =(nsDragSession *)gtk_object_get_data(GTK_OBJECT(aWidget),
|
||||
"ds");
|
||||
if (!cb)
|
||||
{
|
||||
g_print("no dragservice found.. this is bad.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ds->SelectionReceiver(aWidget, aSelectionData);
|
||||
#ifdef DEBUG_DRAG
|
||||
g_print(" }\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* local method (called from nsClipboard::SelectionReceivedCB)
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aSelectionData gtk selection stuff
|
||||
*/
|
||||
void
|
||||
nsDragService::SelectionReceiver (GtkWidget *aWidget,
|
||||
GtkSelectionData *aSD)
|
||||
{
|
||||
gint type;
|
||||
|
||||
mBlocking = PR_FALSE;
|
||||
|
||||
if (aSD->length < 0)
|
||||
{
|
||||
printf(" Error retrieving selection: length was %d\n",
|
||||
aSD->length);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GDK_TARGET_STRING:
|
||||
case TARGET_COMPOUND_TEXT:
|
||||
case TARGET_TEXT_PLAIN:
|
||||
case TARGET_TEXT_XIF:
|
||||
case TARGET_TEXT_UNICODE:
|
||||
case TARGET_TEXT_HTML:
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" Copying mSelectionData pointer -- ");
|
||||
#endif
|
||||
mSelectionData = *aSD;
|
||||
mSelectionData.data = g_new(guchar, aSD->length + 1);
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" Data = %s\n Length = %i\n", aSD->data, aSD->length);
|
||||
#endif
|
||||
memcpy(mSelectionData.data,
|
||||
aSD->data,
|
||||
aSD->length);
|
||||
// Null terminate in case anyone cares,
|
||||
// and so we can print the string for debugging:
|
||||
mSelectionData.data[aSD->length] = '\0';
|
||||
mSelectionData.length = aSD->length;
|
||||
return;
|
||||
|
||||
default:
|
||||
mSelectionData = *aSD;
|
||||
mSelectionData.data = g_new(guchar, aSD->length + 1);
|
||||
memcpy(mSelectionData.data,
|
||||
aSD->data,
|
||||
aSD->length);
|
||||
mSelectionData.length = aSD->length;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsDragService::GetNumDropItems (PRUint32 * aNumItems)
|
||||
{
|
||||
*aNumItems = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsDragService::GetData (nsITransferable * aTransferable, PRUint32 anItem)
|
||||
{
|
||||
|
||||
#ifdef DEBUG_DRAG
|
||||
printf("nsClipboard::GetNativeClipboardData()\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
// make sure we have a good transferable
|
||||
if (!aTransferable) {
|
||||
printf(" GetData: Transferable is null!\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// get flavor list that includes all acceptable flavors (including ones obtained through
|
||||
// conversion)
|
||||
nsCOMPtr<nsISupportsArray> flavorList;
|
||||
nsresult errCode = aTransferable->FlavorsTransferableCanImport ( getter_AddRefs(flavorList) );
|
||||
if ( NS_FAILED(errCode) )
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Walk through flavors and see which flavor matches the one being pasted:
|
||||
PRUint32 cnt;
|
||||
flavorList->Count(&cnt);
|
||||
nsCAutoString foundFlavor;
|
||||
for ( PRUint32 i = 0; i < cnt; ++i ) {
|
||||
nsCOMPtr<nsISupports> genericFlavor;
|
||||
flavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) );
|
||||
nsCOMPtr<nsISupportsString> currentFlavor (do_QueryInterface(genericFlavor));
|
||||
if ( currentFlavor ) {
|
||||
nsXPIDLCString flavorStr;
|
||||
currentFlavor->ToString(getter_Copies(flavorStr));
|
||||
if (DoConvert(gdk_atom_intern(flavorStr, 1))) {
|
||||
foundFlavor = flavorStr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf(" Got the callback: '%s', %d\n",
|
||||
mSelectionData.data, mSelectionData.length);
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
// We're back from the callback, no longer blocking:
|
||||
mBlocking = PR_FALSE;
|
||||
|
||||
//
|
||||
// Now we have data in mSelectionData.data.
|
||||
// We just have to copy it to the transferable.
|
||||
//
|
||||
|
||||
#if 0
|
||||
// pinkerton - we have the flavor already from above, so we don't need
|
||||
// to re-derrive it.
|
||||
nsString *name = new nsString((const char*)gdk_atom_name(mSelectionData.type));
|
||||
int format = GetFormat(*name);
|
||||
df->SetString((const char*)gdk_atom_name(sSelTypes[format]));
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsISupports> genericDataWrapper;
|
||||
nsPrimitiveHelpers::CreatePrimitiveForData ( foundFlavor, mSelectionData.data, mSelectionData.length, getter_AddRefs(genericDataWrapper) );
|
||||
aTransferable->SetTransferData(foundFlavor,
|
||||
genericDataWrapper,
|
||||
mSelectionData.length);
|
||||
|
||||
//delete name;
|
||||
|
||||
// transferable is now copying the data, so we can free it.
|
||||
// g_free(mSelectionData.data);
|
||||
mSelectionData.data = nsnull;
|
||||
mSelectionData.length = 0;
|
||||
|
||||
gtk_drag_source_unset(mWidget);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsDragService::IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsDragService::GetCurrentSession (nsIDragSession **aSession)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void
|
||||
nsDragService::DragLeave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time)
|
||||
{
|
||||
g_print("leave\n");
|
||||
//gHaveDrag = PR_FALSE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool
|
||||
nsDragService::DragMotion(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
{
|
||||
g_print("drag motion\n");
|
||||
GtkWidget *source_widget;
|
||||
|
||||
#if 0
|
||||
if (!gHaveDrag) {
|
||||
gHaveDrag = PR_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
source_widget = gtk_drag_get_source_widget (context);
|
||||
g_print("motion, source %s\n", source_widget ?
|
||||
gtk_type_name (GTK_OBJECT (source_widget)->klass->type) :
|
||||
"unknown");
|
||||
|
||||
gdk_drag_status (context, context->suggested_action, time);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool
|
||||
nsDragService::DragDrop(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
{
|
||||
g_print("drop\n");
|
||||
//gHaveDrag = PR_FALSE;
|
||||
|
||||
if (context->targets){
|
||||
gtk_drag_get_data (widget, context,
|
||||
GPOINTER_TO_INT (context->targets->data),
|
||||
time);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void
|
||||
nsDragService::DragDataReceived (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
GtkSelectionData *data,
|
||||
guint info,
|
||||
guint time)
|
||||
{
|
||||
if ((data->length >= 0) && (data->format == 8)) {
|
||||
g_print ("Received \"%s\"\n", (gchar *)data->data);
|
||||
gtk_drag_finish (context, PR_TRUE, PR_FALSE, time);
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_drag_finish (context, PR_FALSE, PR_FALSE, time);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void
|
||||
nsDragService::DragDataGet(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info,
|
||||
guint time,
|
||||
gpointer data)
|
||||
{
|
||||
gtk_selection_data_set (selection_data,
|
||||
selection_data->target,
|
||||
8, (guchar *)"I'm Data!", 9);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void
|
||||
nsDragService::DragDataDelete(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gpointer data)
|
||||
{
|
||||
g_print ("Delete the data!\n");
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef nsDragService_h__
|
||||
#define nsDragService_h__
|
||||
|
||||
#include "nsBaseDragService.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
||||
/**
|
||||
* Native GTK DragService wrapper
|
||||
*/
|
||||
|
||||
class nsDragService : public nsBaseDragService
|
||||
{
|
||||
|
||||
public:
|
||||
nsDragService();
|
||||
virtual ~nsDragService();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIDragService
|
||||
NS_IMETHOD InvokeDragSession (nsISupportsArray * anArrayTransferables,
|
||||
nsIScriptableRegion * aRegion, PRUint32 aActionType);
|
||||
NS_IMETHOD GetCurrentSession (nsIDragSession ** aSession);
|
||||
|
||||
// nsIDragSession
|
||||
NS_IMETHOD GetData (nsITransferable * aTransferable, PRUint32 anItem);
|
||||
NS_IMETHOD GetNumDropItems (PRUint32 * aNumItems);
|
||||
NS_IMETHOD IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval);
|
||||
|
||||
NS_IMETHOD StartDragSession();
|
||||
NS_IMETHOD EndDragSession();
|
||||
|
||||
|
||||
GtkTargetList *RegisterDragItemsAndFlavors(nsISupportsArray *inArray);
|
||||
|
||||
protected:
|
||||
|
||||
PRBool DoConvert(GdkAtom type);
|
||||
|
||||
static PRBool gHaveDrag;
|
||||
|
||||
static void DragLeave(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time);
|
||||
|
||||
static PRBool DragMotion(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
|
||||
static PRBool DragDrop(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
|
||||
static void DragDataReceived(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
GtkSelectionData *data,
|
||||
guint info,
|
||||
guint time);
|
||||
|
||||
static void DragDataGet(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info,
|
||||
guint time,
|
||||
gpointer data);
|
||||
|
||||
static void DragDataDelete(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gpointer data);
|
||||
|
||||
private:
|
||||
GdkDragAction mActionType;
|
||||
PRUint32 mNumFlavors;
|
||||
GtkWidget *mWidget;
|
||||
GdkDragContext *mDragContext;
|
||||
GtkSelectionData mSelectionData;
|
||||
PRBool mBlocking;
|
||||
};
|
||||
|
||||
#endif // nsDragService_h__
|
||||
@@ -1,304 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 the Mozilla browser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stuart Parmenter <pavlov@netscape.com>
|
||||
*/
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsFilePicker.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsFilePicker, nsIFilePicker)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsFilePicker constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsFilePicker::nsFilePicker()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mWidget = nsnull;
|
||||
mDisplayDirectory = nsnull;
|
||||
mFilterMenu = nsnull;
|
||||
mOptionMenu = nsnull;
|
||||
mNumberOfFilters = 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsFilePicker destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsFilePicker::~nsFilePicker()
|
||||
{
|
||||
if (mFilterMenu)
|
||||
{
|
||||
GtkWidget *menu_item;
|
||||
GList *list = g_list_first(GTK_MENU_SHELL(mFilterMenu)->children);
|
||||
|
||||
for (;list; list = list->next)
|
||||
{
|
||||
menu_item = GTK_WIDGET(list->data);
|
||||
gchar *data = (gchar*)gtk_object_get_data(GTK_OBJECT(menu_item), "filters");
|
||||
|
||||
if (data)
|
||||
nsCRT::free(data);
|
||||
}
|
||||
}
|
||||
|
||||
gtk_widget_destroy(mWidget);
|
||||
}
|
||||
|
||||
|
||||
static void file_ok_clicked(GtkWidget *w, PRBool *ret)
|
||||
{
|
||||
g_print("user hit ok\n");
|
||||
*ret = PR_TRUE;
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
static void file_cancel_clicked(GtkWidget *w, PRBool *ret)
|
||||
{
|
||||
g_print("user hit cancel\n");
|
||||
*ret = PR_FALSE;
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
static void filter_item_activated(GtkWidget *w, gpointer data)
|
||||
{
|
||||
// nsFilePicker *f = (nsFilePicker*)data;
|
||||
gchar *foo = (gchar*)gtk_object_get_data(GTK_OBJECT(w), "filters");
|
||||
g_print("filter_item_activated(): %s\n", foo);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Show - Display the file dialog
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFilePicker::Show(PRInt16 *retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(retval);
|
||||
|
||||
PRBool ret;
|
||||
if (mWidget) {
|
||||
// make things shorter
|
||||
GtkFileSelection *fs = GTK_FILE_SELECTION(mWidget);
|
||||
|
||||
if (mNumberOfFilters != 0)
|
||||
{
|
||||
gtk_option_menu_set_menu(GTK_OPTION_MENU(mOptionMenu), mFilterMenu);
|
||||
}
|
||||
else
|
||||
gtk_widget_hide(mOptionMenu);
|
||||
|
||||
#if 0
|
||||
if (mDisplayDirectory)
|
||||
gtk_file_selection_complete(fs, "/");
|
||||
#endif
|
||||
|
||||
// gtk_window_set_modal(GTK_WINDOW(mWidget), PR_TRUE);
|
||||
gtk_widget_show(mWidget);
|
||||
|
||||
// handle close, destroy, etc on the dialog
|
||||
gtk_signal_connect(GTK_OBJECT(fs->ok_button), "clicked",
|
||||
GTK_SIGNAL_FUNC(file_ok_clicked),
|
||||
&ret);
|
||||
gtk_signal_connect(GTK_OBJECT(fs->cancel_button), "clicked",
|
||||
GTK_SIGNAL_FUNC(file_cancel_clicked),
|
||||
&ret);
|
||||
// start new loop. ret is set in the above callbacks.
|
||||
gtk_main();
|
||||
}
|
||||
else {
|
||||
ret = PR_FALSE;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
*retval = returnOK;
|
||||
else
|
||||
*retval = returnCancel;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set the list of filters
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP nsFilePicker::SetFilterList(PRInt32 aNumberOfFilters,
|
||||
const PRUnichar **aTitles,
|
||||
const PRUnichar **filters)
|
||||
{
|
||||
#if 0
|
||||
GtkWidget *menu_item;
|
||||
|
||||
mNumberOfFilters = aNumberOfFilters;
|
||||
mTitles = aTitles;
|
||||
mFilters = aFilters;
|
||||
|
||||
mFilterMenu = gtk_menu_new();
|
||||
|
||||
for(unsigned int i=0; i < aNumberOfFilters; i++)
|
||||
{
|
||||
// we need *.{htm, html, xul, etc}
|
||||
char *foo = aTitles[i].ToNewCString();
|
||||
char *filters = aFilters[i].ToNewCString();
|
||||
printf("%20s %s\n", foo, filters);
|
||||
|
||||
menu_item = gtk_menu_item_new_with_label(nsAutoCString(aTitles[i]));
|
||||
|
||||
gtk_object_set_data(GTK_OBJECT(menu_item), "filters", filters);
|
||||
|
||||
gtk_signal_connect(GTK_OBJECT(menu_item),
|
||||
"activate",
|
||||
GTK_SIGNAL_FUNC(filter_item_activated),
|
||||
this);
|
||||
|
||||
gtk_menu_append(GTK_MENU(mFilterMenu), menu_item);
|
||||
gtk_widget_show(menu_item);
|
||||
|
||||
nsCRT::free(foo);
|
||||
}
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFilePicker::GetFile(nsIFileSpec **aFile)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(*aFile);
|
||||
if (mWidget) {
|
||||
gchar *fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION(mWidget));
|
||||
|
||||
nsCOMPtr<nsIFileSpec> fileSpec(do_CreateInstance("component://netscape/filespec"));
|
||||
|
||||
NS_ENSURE_TRUE(fileSpec, NS_ERROR_FAILURE);
|
||||
|
||||
fileSpec->SetNativePath(fn);
|
||||
|
||||
*aFile = fileSpec;
|
||||
NS_ADDREF(*aFile);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFilePicker::GetSelectedFilter(PRInt32 *aType)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aType);
|
||||
*aType = mSelectedType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get the file + path
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFilePicker::SetDefaultString(const PRUnichar *aString)
|
||||
{
|
||||
if (mWidget) {
|
||||
gtk_file_selection_set_filename(GTK_FILE_SELECTION(mWidget),
|
||||
(const gchar*)nsAutoCString(aString));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFilePicker::GetDefaultString(PRUnichar **aString)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set the display directory
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFilePicker::SetDisplayDirectory(nsIFileSpec *aDirectory)
|
||||
{
|
||||
mDisplayDirectory = aDirectory;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get the display directory
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFilePicker::GetDisplayDirectory(nsIFileSpec **aDirectory)
|
||||
{
|
||||
*aDirectory = mDisplayDirectory;
|
||||
NS_IF_ADDREF(*aDirectory);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFilePicker::Create(nsIDOMWindow *aParent,
|
||||
const PRUnichar *aTitle,
|
||||
PRInt16 aMode)
|
||||
{
|
||||
return nsBaseFilePicker::Create(aParent, aTitle, aMode);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFilePicker::CreateNative(nsIWidget *aParent,
|
||||
const PRUnichar *aTitle,
|
||||
PRInt16 aMode)
|
||||
{
|
||||
mWidget = gtk_file_selection_new((const gchar *)nsAutoCString(aTitle));
|
||||
gtk_signal_connect(GTK_OBJECT(mWidget),
|
||||
"destroy",
|
||||
GTK_SIGNAL_FUNC(DestroySignal),
|
||||
this);
|
||||
|
||||
gtk_button_box_set_layout(GTK_BUTTON_BOX(GTK_FILE_SELECTION(mWidget)->button_area), GTK_BUTTONBOX_SPREAD);
|
||||
|
||||
mOptionMenu = gtk_option_menu_new();
|
||||
|
||||
gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(mWidget)->main_vbox), mOptionMenu, PR_FALSE, PR_FALSE, 0);
|
||||
gtk_widget_show(mOptionMenu);
|
||||
|
||||
// Hide the file column for the folder case.
|
||||
if (aMode == nsIFilePicker::modeGetFolder) {
|
||||
gtk_widget_hide((GTK_FILE_SELECTION(mWidget)->file_list)->parent);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
gint
|
||||
nsFilePicker::DestroySignal(GtkWidget * aGtkWidget,
|
||||
nsFilePicker* aWidget)
|
||||
{
|
||||
aWidget->OnDestroySignal(aGtkWidget);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nsFilePicker::OnDestroySignal(GtkWidget* aGtkWidget)
|
||||
{
|
||||
if (aGtkWidget == mWidget) {
|
||||
mWidget = nsnull;
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 the Mozilla browser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stuart Parmenter <pavlov@netscape.com>
|
||||
*/
|
||||
|
||||
#ifndef nsFilePicker_h__
|
||||
#define nsFilePicker_h__
|
||||
|
||||
#include "nsBaseFilePicker.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/**
|
||||
* Native GTK FileSelector wrapper
|
||||
*/
|
||||
|
||||
class nsFilePicker : public nsBaseFilePicker
|
||||
{
|
||||
public:
|
||||
nsFilePicker();
|
||||
virtual ~nsFilePicker();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIFILEPICKER
|
||||
|
||||
protected:
|
||||
/* method from nsBaseFilePicker */
|
||||
NS_IMETHOD CreateNative(nsIWidget *aParent,
|
||||
const PRUnichar *aTitle,
|
||||
PRInt16 aMode);
|
||||
|
||||
static gint DestroySignal(GtkWidget * aGtkWidget,
|
||||
nsFilePicker* aWidget);
|
||||
|
||||
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
|
||||
|
||||
GtkWidget *mWidget;
|
||||
GtkWidget *mOptionMenu;
|
||||
GtkWidget *mFilterMenu;
|
||||
|
||||
|
||||
PRUint32 mNumberOfFilters;
|
||||
const nsString* mTitles;
|
||||
const nsString* mFilters;
|
||||
nsString mDefault;
|
||||
nsIFileSpec *mDisplayDirectory;
|
||||
PRInt16 mSelectedType;
|
||||
};
|
||||
|
||||
#endif // nsFilePicker_h__
|
||||
@@ -1,322 +0,0 @@
|
||||
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include "nsFileWidget.h"
|
||||
#include "nsIToolkit.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsFileWidget, nsIFileWidget)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsFileWidget constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsFileWidget::nsFileWidget() : nsIFileWidget()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mWidget = nsnull;
|
||||
mDisplayDirectory = nsnull;
|
||||
mFilterMenu = nsnull;
|
||||
mOptionMenu = nsnull;
|
||||
mNumberOfFilters = 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsFileWidget destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsFileWidget::~nsFileWidget()
|
||||
{
|
||||
if (mFilterMenu)
|
||||
{
|
||||
GtkWidget *menu_item;
|
||||
GList *list = g_list_first(GTK_MENU_SHELL(mFilterMenu)->children);
|
||||
|
||||
for (;list; list = list->next)
|
||||
{
|
||||
menu_item = GTK_WIDGET(list->data);
|
||||
gchar *data = (gchar*)gtk_object_get_data(GTK_OBJECT(menu_item), "filters");
|
||||
|
||||
if (data)
|
||||
nsCRT::free(data);
|
||||
}
|
||||
}
|
||||
|
||||
gtk_widget_destroy(mWidget);
|
||||
}
|
||||
|
||||
|
||||
static void file_ok_clicked(GtkWidget *w, PRBool *ret)
|
||||
{
|
||||
g_print("user hit ok\n");
|
||||
*ret = PR_TRUE;
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
static void file_cancel_clicked(GtkWidget *w, PRBool *ret)
|
||||
{
|
||||
g_print("user hit cancel\n");
|
||||
*ret = PR_FALSE;
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
static void filter_item_activated(GtkWidget *w, gpointer data)
|
||||
{
|
||||
// nsFileWidget *f = (nsFileWidget*)data;
|
||||
gchar *foo = (gchar*)gtk_object_get_data(GTK_OBJECT(w), "filters");
|
||||
g_print("filter_item_activated(): %s\n", foo);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Show - Display the file dialog
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool nsFileWidget::Show()
|
||||
{
|
||||
PRBool ret;
|
||||
if (mWidget) {
|
||||
// make things shorter
|
||||
GtkFileSelection *fs = GTK_FILE_SELECTION(mWidget);
|
||||
|
||||
if (mNumberOfFilters != 0)
|
||||
{
|
||||
gtk_option_menu_set_menu(GTK_OPTION_MENU(mOptionMenu), mFilterMenu);
|
||||
}
|
||||
else
|
||||
gtk_widget_hide(mOptionMenu);
|
||||
|
||||
#if 0
|
||||
if (mDisplayDirectory)
|
||||
gtk_file_selection_complete(fs, "/");
|
||||
#endif
|
||||
|
||||
// gtk_window_set_modal(GTK_WINDOW(mWidget), PR_TRUE);
|
||||
gtk_widget_show(mWidget);
|
||||
|
||||
// handle close, destroy, etc on the dialog
|
||||
gtk_signal_connect(GTK_OBJECT(fs->ok_button), "clicked",
|
||||
GTK_SIGNAL_FUNC(file_ok_clicked),
|
||||
&ret);
|
||||
gtk_signal_connect(GTK_OBJECT(fs->cancel_button), "clicked",
|
||||
GTK_SIGNAL_FUNC(file_cancel_clicked),
|
||||
&ret);
|
||||
// start new loop. ret is set in the above callbacks.
|
||||
gtk_main();
|
||||
}
|
||||
else {
|
||||
ret = PR_FALSE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set the list of filters
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP nsFileWidget::SetFilterList(PRUint32 aNumberOfFilters,
|
||||
const nsString aTitles[],
|
||||
const nsString aFilters[])
|
||||
{
|
||||
GtkWidget *menu_item;
|
||||
|
||||
mNumberOfFilters = aNumberOfFilters;
|
||||
mTitles = aTitles;
|
||||
mFilters = aFilters;
|
||||
|
||||
mFilterMenu = gtk_menu_new();
|
||||
|
||||
for(unsigned int i=0; i < aNumberOfFilters; i++)
|
||||
{
|
||||
// we need *.{htm, html, xul, etc}
|
||||
char *foo = aTitles[i].ToNewCString();
|
||||
char *filters = aFilters[i].ToNewCString();
|
||||
printf("%20s %s\n", foo, filters);
|
||||
|
||||
menu_item = gtk_menu_item_new_with_label(nsAutoCString(aTitles[i]));
|
||||
|
||||
gtk_object_set_data(GTK_OBJECT(menu_item), "filters", filters);
|
||||
|
||||
gtk_signal_connect(GTK_OBJECT(menu_item),
|
||||
"activate",
|
||||
GTK_SIGNAL_FUNC(filter_item_activated),
|
||||
this);
|
||||
|
||||
gtk_menu_append(GTK_MENU(mFilterMenu), menu_item);
|
||||
gtk_widget_show(menu_item);
|
||||
|
||||
nsCRT::free(foo);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFileWidget::GetFile(nsFileSpec& aFile)
|
||||
{
|
||||
if (mWidget) {
|
||||
gchar *fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION(mWidget));
|
||||
aFile = fn; // Put the filename into the nsFileSpec instance.
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFileWidget::GetSelectedType(PRInt16& theType)
|
||||
{
|
||||
theType = mSelectedType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get the file + path
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFileWidget::SetDefaultString(const nsString& aString)
|
||||
{
|
||||
if (mWidget) {
|
||||
gtk_file_selection_set_filename(GTK_FILE_SELECTION(mWidget),
|
||||
(const gchar*)nsAutoCString(aString));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set the display directory
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFileWidget::SetDisplayDirectory(const nsFileSpec& aDirectory)
|
||||
{
|
||||
mDisplayDirectory = aDirectory;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get the display directory
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFileWidget::GetDisplayDirectory(nsFileSpec& aDirectory)
|
||||
{
|
||||
aDirectory = mDisplayDirectory;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFileWidget::Create(nsIWidget *aParent,
|
||||
const nsString& aTitle,
|
||||
nsFileDlgMode aMode,
|
||||
nsIDeviceContext *aContext,
|
||||
nsIAppShell *aAppShell,
|
||||
nsIToolkit *aToolkit,
|
||||
void *aInitData)
|
||||
{
|
||||
mMode = aMode;
|
||||
mTitle.SetLength(0);
|
||||
mTitle.Append(aTitle);
|
||||
|
||||
mWidget = gtk_file_selection_new((const gchar *)nsAutoCString(aTitle));
|
||||
gtk_signal_connect(GTK_OBJECT(mWidget),
|
||||
"destroy",
|
||||
GTK_SIGNAL_FUNC(DestroySignal),
|
||||
this);
|
||||
|
||||
gtk_button_box_set_layout(GTK_BUTTON_BOX(GTK_FILE_SELECTION(mWidget)->button_area), GTK_BUTTONBOX_SPREAD);
|
||||
|
||||
mOptionMenu = gtk_option_menu_new();
|
||||
|
||||
gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(mWidget)->main_vbox), mOptionMenu, PR_FALSE, PR_FALSE, 0);
|
||||
gtk_widget_show(mOptionMenu);
|
||||
|
||||
|
||||
// Hide the file column for the folder case.
|
||||
if (aMode == eMode_getfolder) {
|
||||
gtk_widget_hide((GTK_FILE_SELECTION(mWidget)->file_list)->parent);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
gint
|
||||
nsFileWidget::DestroySignal(GtkWidget * aGtkWidget,
|
||||
nsFileWidget* aWidget)
|
||||
{
|
||||
aWidget->OnDestroySignal(aGtkWidget);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nsFileWidget::OnDestroySignal(GtkWidget* aGtkWidget)
|
||||
{
|
||||
if (aGtkWidget == mWidget) {
|
||||
mWidget = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
nsFileDlgResults nsFileWidget::GetFile(nsIWidget *aParent,
|
||||
const nsString &promptString,
|
||||
nsFileSpec &theFileSpec)
|
||||
{
|
||||
Create(aParent, promptString, eMode_load, nsnull, nsnull);
|
||||
if (Show() == PR_TRUE)
|
||||
{
|
||||
GetFile(theFileSpec);
|
||||
return nsFileDlgResults_OK;
|
||||
}
|
||||
|
||||
return nsFileDlgResults_Cancel;
|
||||
}
|
||||
|
||||
nsFileDlgResults nsFileWidget::GetFolder(nsIWidget *aParent,
|
||||
const nsString &promptString,
|
||||
nsFileSpec &theFileSpec)
|
||||
{
|
||||
Create(aParent, promptString, eMode_getfolder, nsnull, nsnull);
|
||||
if (Show() == PR_TRUE)
|
||||
{
|
||||
GetFile(theFileSpec);
|
||||
return nsFileDlgResults_OK;
|
||||
}
|
||||
|
||||
return nsFileDlgResults_Cancel;
|
||||
}
|
||||
|
||||
nsFileDlgResults nsFileWidget::PutFile(nsIWidget *aParent,
|
||||
const nsString &promptString,
|
||||
nsFileSpec &theFileSpec)
|
||||
{
|
||||
Create(aParent, promptString, eMode_save, nsnull, nsnull);
|
||||
if (Show() == PR_TRUE)
|
||||
{
|
||||
GetFile(theFileSpec);
|
||||
return nsFileDlgResults_OK;
|
||||
}
|
||||
return nsFileDlgResults_Cancel;
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef nsFileWidget_h__
|
||||
#define nsFileWidget_h__
|
||||
|
||||
#include "nsIWidget.h"
|
||||
#include "nsIFileWidget.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
class nsIToolkit;
|
||||
|
||||
/**
|
||||
* Native GTK FileSelector wrapper
|
||||
*/
|
||||
|
||||
class nsFileWidget : public nsIFileWidget
|
||||
{
|
||||
public:
|
||||
nsFileWidget();
|
||||
virtual ~nsFileWidget();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIWidget interface
|
||||
|
||||
NS_IMETHOD Create(nsIWidget *aParent,
|
||||
const nsString& aTitle,
|
||||
nsFileDlgMode aMode,
|
||||
nsIDeviceContext *aContext = nsnull,
|
||||
nsIAppShell *aAppShell = nsnull,
|
||||
nsIToolkit *aToolkit = nsnull,
|
||||
void *aInitData = nsnull);
|
||||
|
||||
// nsIFileWidget part
|
||||
virtual PRBool Show();
|
||||
NS_IMETHOD GetFile(nsFileSpec& aFile);
|
||||
NS_IMETHOD SetDefaultString(const nsString& aFile);
|
||||
NS_IMETHOD SetFilterList(PRUint32 aNumberOfFilters,
|
||||
const nsString aTitles[],
|
||||
const nsString aFilters[]);
|
||||
|
||||
NS_IMETHOD GetDisplayDirectory(nsFileSpec& aDirectory);
|
||||
NS_IMETHOD SetDisplayDirectory(const nsFileSpec& aDirectory);
|
||||
|
||||
virtual nsFileDlgResults GetFile(nsIWidget *aParent,
|
||||
const nsString &promptString,
|
||||
nsFileSpec &theFileSpec);
|
||||
|
||||
virtual nsFileDlgResults GetFolder(nsIWidget *aParent,
|
||||
const nsString &promptString,
|
||||
nsFileSpec &theFileSpec);
|
||||
|
||||
virtual nsFileDlgResults PutFile(nsIWidget *aParent,
|
||||
const nsString &promptString,
|
||||
nsFileSpec &theFileSpec);
|
||||
|
||||
|
||||
NS_IMETHOD GetSelectedType(PRInt16& theType);
|
||||
|
||||
protected:
|
||||
static gint DestroySignal(GtkWidget * aGtkWidget,
|
||||
nsFileWidget* aWidget);
|
||||
|
||||
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
|
||||
|
||||
GtkWidget *mWidget;
|
||||
nsString mTitle;
|
||||
GtkWidget *mOptionMenu;
|
||||
GtkWidget *mFilterMenu;
|
||||
|
||||
|
||||
nsFileDlgMode mMode;
|
||||
PRUint32 mNumberOfFilters;
|
||||
const nsString* mTitles;
|
||||
const nsString* mFilters;
|
||||
nsString mDefault;
|
||||
nsFileSpec mDisplayDirectory;
|
||||
PRInt16 mSelectedType;
|
||||
};
|
||||
|
||||
#endif // nsFileWidget_h__
|
||||
@@ -1,395 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include "nsFontRetrieverService.h"
|
||||
#include "nsIWidget.h"
|
||||
#include <ctype.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include "X11/Xlib.h"
|
||||
#include "X11/Xutil.h"
|
||||
|
||||
#include "nsFont.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsFontSizeIterator.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsFontRetrieverService, nsIFontRetrieverService, nsIFontNameIterator)
|
||||
|
||||
//----------------------------------------------------------
|
||||
nsFontRetrieverService::nsFontRetrieverService()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
mFontList = nsnull;
|
||||
mSizeIter = nsnull;
|
||||
mNameIterInx = 0;
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
nsFontRetrieverService::~nsFontRetrieverService()
|
||||
{
|
||||
if (nsnull != mFontList) {
|
||||
for (PRInt32 i=0;i<mFontList->Count();i++) {
|
||||
FontInfo * font = (FontInfo *)mFontList->ElementAt(i);
|
||||
if (font->mSizes) {
|
||||
delete font->mSizes;
|
||||
}
|
||||
delete font;
|
||||
}
|
||||
delete mFontList;
|
||||
}
|
||||
NS_IF_RELEASE(mSizeIter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------
|
||||
//-- nsIFontRetrieverService
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontRetrieverService::CreateFontNameIterator( nsIFontNameIterator** aIterator )
|
||||
{
|
||||
if (nsnull == aIterator) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (nsnull == mFontList) {
|
||||
LoadFontList();
|
||||
}
|
||||
*aIterator = this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontRetrieverService::CreateFontSizeIterator( const nsString & aFontName,
|
||||
nsIFontSizeIterator** aIterator )
|
||||
{
|
||||
// save value in case someone externally is using it
|
||||
PRInt32 saveIterInx = mNameIterInx;
|
||||
|
||||
PRBool found = PR_FALSE;
|
||||
Reset();
|
||||
do {
|
||||
nsAutoString name;
|
||||
Get(&name);
|
||||
if (name.Equals(aFontName)) {
|
||||
found = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
} while (Advance() == NS_OK);
|
||||
|
||||
if (found) {
|
||||
if (nsnull == mSizeIter) {
|
||||
mSizeIter = new nsFontSizeIterator();
|
||||
}
|
||||
NS_ASSERTION( nsnull != mSizeIter, "nsFontSizeIterator instance pointer is null");
|
||||
|
||||
*aIterator = (nsIFontSizeIterator *)mSizeIter;
|
||||
NS_ADDREF(mSizeIter);
|
||||
|
||||
FontInfo * fontInfo = (FontInfo *)mFontList->ElementAt(mNameIterInx);
|
||||
mSizeIter->SetFontInfo(fontInfo);
|
||||
mNameIterInx = saveIterInx;
|
||||
return NS_OK;
|
||||
}
|
||||
mNameIterInx = saveIterInx;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//-- nsIFontNameIterator
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontRetrieverService::Reset()
|
||||
{
|
||||
mNameIterInx = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontRetrieverService::Get( nsString* aFontName )
|
||||
{
|
||||
if (mNameIterInx < mFontList->Count()) {
|
||||
FontInfo * fontInfo = (FontInfo *)mFontList->ElementAt(mNameIterInx);
|
||||
*aFontName = fontInfo->mName;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontRetrieverService::Advance()
|
||||
{
|
||||
if (mNameIterInx < mFontList->Count()-1) {
|
||||
mNameIterInx++;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//------------------------------
|
||||
static FontInfo * GetFontInfo(nsVoidArray * aFontList, char * aName)
|
||||
{
|
||||
nsAutoString name(aName);
|
||||
PRInt32 i;
|
||||
PRInt32 cnt = aFontList->Count();
|
||||
for (i=0;i<cnt;i++) {
|
||||
FontInfo * fontInfo = (FontInfo *)aFontList->ElementAt(i);
|
||||
if (fontInfo->mName.Equals(name)) {
|
||||
return fontInfo;
|
||||
}
|
||||
}
|
||||
|
||||
FontInfo * fontInfo = new FontInfo();
|
||||
fontInfo->mName = aName;
|
||||
//printf("Adding [%s]\n", aName);fflush(stdout);
|
||||
fontInfo->mIsScalable = PR_FALSE; // X fonts aren't scalable right??
|
||||
fontInfo->mSizes = nsnull;
|
||||
aFontList->AppendElement(fontInfo);
|
||||
return fontInfo;
|
||||
}
|
||||
|
||||
//------------------------------
|
||||
static void AddSizeToFontInfo(FontInfo * aFontInfo, PRInt32 aSize)
|
||||
{
|
||||
nsVoidArray * sizes;
|
||||
if (nsnull == aFontInfo->mSizes) {
|
||||
sizes = new nsVoidArray();
|
||||
aFontInfo->mSizes = sizes;
|
||||
} else {
|
||||
sizes = aFontInfo->mSizes;
|
||||
}
|
||||
PRInt32 i;
|
||||
PRInt32 cnt = sizes->Count();
|
||||
for (i=0;i<cnt;i++) {
|
||||
PRInt32 size = (int)sizes->ElementAt(i);
|
||||
if (size == aSize) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
sizes->AppendElement((void *)aSize);
|
||||
}
|
||||
|
||||
//---------------------------------------------------
|
||||
// XXX - Hack - Parts of this will need to be reworked
|
||||
//
|
||||
// This method does brute force parcing for 4 different formats:
|
||||
//
|
||||
// 1) The format -*-*-*-*-*-* etc.
|
||||
// -misc-fixed-medium-r-normal--13-120-75-75-c-80-iso8859-8
|
||||
//
|
||||
// 2) Name-size format
|
||||
// lucidasans-10
|
||||
//
|
||||
// 3) Name-style-size
|
||||
// lucidasans-bold-10
|
||||
//
|
||||
// 4) Name only (implicit size)
|
||||
// 6x13
|
||||
//
|
||||
//--------------------------------------------------
|
||||
NS_IMETHODIMP nsFontRetrieverService::LoadFontList()
|
||||
{
|
||||
char * pattern = "*";
|
||||
int nnames = 1024;
|
||||
|
||||
int available = nnames+1;
|
||||
int i;
|
||||
char **fonts;
|
||||
XFontStruct *info;
|
||||
|
||||
if (nsnull == mFontList) {
|
||||
mFontList = new nsVoidArray();
|
||||
if (nsnull == mFontList) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get list of fonts matching pattern */
|
||||
for (;;) {
|
||||
// the following line is VERY slow to return
|
||||
fonts = XListFontsWithInfo(GDK_DISPLAY(), pattern, nnames,
|
||||
&available, &info);
|
||||
if (fonts == NULL || available < nnames)
|
||||
break;
|
||||
|
||||
XFreeFontInfo(fonts, info, available);
|
||||
nnames = available * 2;
|
||||
}
|
||||
|
||||
if (fonts == NULL) {
|
||||
fprintf(stderr, "pattern \"%s\" unmatched\n", pattern);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
#if 0 // debug
|
||||
// print out all the retrieved fonts
|
||||
printf("-----------------------------\n");
|
||||
for (i=0; i<available; i++) {
|
||||
printf("[%s]i\n", fonts[i]);
|
||||
}
|
||||
printf("-----------------------------\n");
|
||||
#endif
|
||||
|
||||
// this code assumes all like fonts are grouped together
|
||||
// currentName is the current name of the font we are gathering
|
||||
// sizes for, when the name changes we create a new FontInfo object
|
||||
// but it also takes into account fonts of similar names when it
|
||||
// goes to add then and disregards duplicates
|
||||
char buffer[1024];
|
||||
char currentName[1024];
|
||||
FontInfo * font = nsnull;
|
||||
|
||||
currentName[0] = 0;
|
||||
for (i=0; i<available; i++) {
|
||||
|
||||
// This is kind of lame, but it will have to do for now
|
||||
strcpy(buffer, fonts[i]);
|
||||
|
||||
// Start by checking to see if the name begins with a dash
|
||||
char * ptr = buffer;
|
||||
if (buffer[0] == '-') { //Format #1
|
||||
|
||||
PRInt32 cnt = 0;
|
||||
// skip first two '-'
|
||||
do {
|
||||
if (*ptr == '-') cnt++;
|
||||
ptr++;
|
||||
} while (cnt < 2);
|
||||
|
||||
// find the dash at the end of the name
|
||||
char * end = strchr(ptr, '-');
|
||||
if (end) {
|
||||
*end = 0;
|
||||
|
||||
// Check to see if we need to create a new FontInfo obj
|
||||
// and set the currentName var to this guys font name
|
||||
if (strcmp(currentName, ptr) || NULL == font) {
|
||||
font = GetFontInfo(mFontList, ptr);
|
||||
strcpy(currentName, ptr);
|
||||
}
|
||||
if (nsnull == font->mSizes) {
|
||||
font->mSizes = new nsVoidArray();
|
||||
}
|
||||
ptr = end+1; // skip past the dash that was set to zero
|
||||
|
||||
cnt = 0;
|
||||
// now skip ahead 4 dashes
|
||||
do {
|
||||
if (*ptr == '-') cnt++;
|
||||
ptr++;
|
||||
} while (cnt < 4);
|
||||
|
||||
// find the dash after the size
|
||||
end = strchr(ptr, '-');
|
||||
|
||||
if (end) {
|
||||
*end = 0;
|
||||
PRInt32 size;
|
||||
sscanf(ptr, "%d", &size);
|
||||
AddSizeToFontInfo(font, size);
|
||||
}
|
||||
}
|
||||
} else { // formats 2,3,4
|
||||
|
||||
// no leading dash means the start of the
|
||||
// buffer is the start of the name
|
||||
// this checks for a dash at the end of the font name
|
||||
// which means there is a size at the end
|
||||
char * end = strchr(buffer, '-');
|
||||
if (end) { // Format 2,3
|
||||
*end = 0;
|
||||
// Check to see if we need to create a new FontInfo obj
|
||||
// and set the currentName var to this guys font name
|
||||
if (strcmp(currentName, buffer) || NULL == font) {
|
||||
font = GetFontInfo(mFontList, buffer);
|
||||
strcpy(currentName, buffer);
|
||||
}
|
||||
end++; // advance past the dash
|
||||
// check to see if we have a number
|
||||
ptr = end;
|
||||
if (isalpha(*ptr)) { // Format 3
|
||||
// skip until next dash
|
||||
end = strchr(ptr, '-');
|
||||
if (end) {
|
||||
*end = 0;
|
||||
ptr = end+1;
|
||||
}
|
||||
}
|
||||
PRInt32 size;
|
||||
// yes, it has a dash at the end so it must have the size
|
||||
// check to see if the size is terminated by a dash
|
||||
// it shouldn't be
|
||||
char * end2 = strchr(ptr, '-');
|
||||
if (end2) *end2 = 0; // put terminator at the dash
|
||||
sscanf(end, "%d", &size);
|
||||
AddSizeToFontInfo(font, size);
|
||||
|
||||
} else { // Format #4
|
||||
// The font has an implicit size,
|
||||
// so there is nothing to parse for size
|
||||
// so we can't really do much here
|
||||
// Check to see if we need to create a new FontInfo obj
|
||||
// and set the currentName var to this guys font name
|
||||
if (strcmp(currentName, buffer) || NULL == font) {
|
||||
font = GetFontInfo(mFontList, buffer);
|
||||
strcpy(currentName, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
XFreeFontInfo(fonts, info, available);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontRetrieverService::IsFontScalable(const nsString & aFontName,
|
||||
PRBool* aResult )
|
||||
{
|
||||
// save value in case someone externally is using it
|
||||
PRInt32 saveIterInx = mNameIterInx;
|
||||
|
||||
PRBool found = PR_FALSE;
|
||||
Reset();
|
||||
do {
|
||||
nsAutoString name;
|
||||
Get(&name);
|
||||
if (name.Equals(aFontName)) {
|
||||
found = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
} while (Advance() == NS_OK);
|
||||
|
||||
if (found) {
|
||||
FontInfo * fontInfo = (FontInfo *)mFontList->ElementAt(mNameIterInx);
|
||||
*aResult = fontInfo->mIsScalable;
|
||||
mNameIterInx = saveIterInx;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mNameIterInx = saveIterInx;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef __nsFontRetrieverService
|
||||
#define __nsFontRetrieverService
|
||||
|
||||
#include "nsIFontRetrieverService.h"
|
||||
#include "nsIFontNameIterator.h"
|
||||
|
||||
class nsVoidArray;
|
||||
class nsFontSizeIterator;
|
||||
|
||||
class nsFontRetrieverService: public nsIFontRetrieverService,
|
||||
public nsIFontNameIterator
|
||||
{
|
||||
public:
|
||||
nsFontRetrieverService();
|
||||
virtual ~nsFontRetrieverService();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIFontRetrieverService
|
||||
NS_IMETHOD CreateFontNameIterator( nsIFontNameIterator** aIterator );
|
||||
|
||||
NS_IMETHOD CreateFontSizeIterator( const nsString & aFontName, nsIFontSizeIterator** aIterator );
|
||||
NS_IMETHOD IsFontScalable( const nsString & aFontName, PRBool* aResult );
|
||||
|
||||
// nsIFontNameIterator
|
||||
|
||||
NS_IMETHOD Reset();
|
||||
NS_IMETHOD Get( nsString* aFontName );
|
||||
NS_IMETHOD Advance();
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
NS_IMETHOD LoadFontList();
|
||||
|
||||
nsVoidArray * mFontList;
|
||||
|
||||
PRInt32 mNameIterInx;
|
||||
|
||||
nsFontSizeIterator * mSizeIter;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,88 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include "nsFontSizeIterator.h"
|
||||
|
||||
#include "nsFont.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
|
||||
NS_IMPL_ADDREF(nsFontSizeIterator)
|
||||
NS_IMPL_RELEASE(nsFontSizeIterator)
|
||||
NS_IMPL_QUERY_INTERFACE(nsFontSizeIterator, nsIFontSizeIterator::GetIID())
|
||||
|
||||
//----------------------------------------------------------
|
||||
nsFontSizeIterator::nsFontSizeIterator()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mFontInfo = nsnull;
|
||||
mSizeIterInx = 0;
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
nsFontSizeIterator::~nsFontSizeIterator()
|
||||
{
|
||||
}
|
||||
|
||||
///----------------------------------------------------------
|
||||
//-- nsIFontNameIterator
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontSizeIterator::Reset()
|
||||
{
|
||||
mSizeIterInx = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontSizeIterator::Get( double* aFontSize )
|
||||
{
|
||||
if (nsnull != mFontInfo->mSizes &&
|
||||
mFontInfo->mSizes->Count() > 0 &&
|
||||
mSizeIterInx < mFontInfo->mSizes->Count()) {
|
||||
PRUint32 size = (PRUint32)mFontInfo->mSizes->ElementAt(mSizeIterInx);
|
||||
*aFontSize = (double)size;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontSizeIterator::Advance()
|
||||
{
|
||||
if (nsnull != mFontInfo->mSizes &&
|
||||
mFontInfo->mSizes->Count() > 0 &&
|
||||
mSizeIterInx < mFontInfo->mSizes->Count()-2) {
|
||||
mSizeIterInx++;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontSizeIterator::SetFontInfo( FontInfo * aFontInfo )
|
||||
{
|
||||
mFontInfo = aFontInfo;
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef __nsFontSizeIterator
|
||||
#define __nsFontSizeIterator
|
||||
|
||||
#include "nsIFontSizeIterator.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsVoidArray;
|
||||
|
||||
typedef struct {
|
||||
nsString mName;
|
||||
PRBool mIsScalable;
|
||||
nsVoidArray * mSizes;
|
||||
} FontInfo;
|
||||
|
||||
|
||||
class nsFontSizeIterator: public nsIFontSizeIterator {
|
||||
public:
|
||||
nsFontSizeIterator();
|
||||
virtual ~nsFontSizeIterator();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIFontSizeIterator
|
||||
NS_IMETHOD Reset();
|
||||
NS_IMETHOD Get( double* aFontSize );
|
||||
NS_IMETHOD Advance();
|
||||
|
||||
// Native impl
|
||||
NS_IMETHOD SetFontInfo( FontInfo * aFontInfo );
|
||||
|
||||
protected:
|
||||
|
||||
FontInfo * mFontInfo;
|
||||
PRInt32 mSizeIterInx; // current index of iter
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,967 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include "nsWidget.h"
|
||||
#include "nsWindow.h"
|
||||
|
||||
#include "nsScrollbar.h"
|
||||
#include "nsIFileWidget.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsIMenu.h"
|
||||
#include "nsIMenuItem.h"
|
||||
#include "nsIMenuListener.h"
|
||||
|
||||
#include "nsTextWidget.h"
|
||||
|
||||
#include "nsICharsetConverterManager.h"
|
||||
#include "nsIPlatformCharset.h"
|
||||
#include "nsIServiceManager.h"
|
||||
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
|
||||
|
||||
#include "stdio.h"
|
||||
#include "ctype.h"
|
||||
|
||||
#include "gtk/gtk.h"
|
||||
#include "nsGtkEventHandler.h"
|
||||
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#ifdef DEBUG_pavlov
|
||||
//#define DEBUG_EVENTS 1
|
||||
#endif
|
||||
|
||||
struct EventInfo {
|
||||
nsWidget *widget; // the widget
|
||||
nsRect *rect; // the rect
|
||||
};
|
||||
|
||||
//==============================================================
|
||||
void InitAllocationEvent(GtkAllocation *aAlloc,
|
||||
gpointer p,
|
||||
nsSizeEvent &anEvent,
|
||||
PRUint32 aEventType)
|
||||
{
|
||||
anEvent.message = aEventType;
|
||||
anEvent.widget = (nsWidget *) p;
|
||||
|
||||
anEvent.eventStructType = NS_SIZE_EVENT;
|
||||
|
||||
if (aAlloc != nsnull) {
|
||||
// HACK
|
||||
// nsRect *foo = new nsRect(aAlloc->x, aAlloc->y, aAlloc->width, aAlloc->height);
|
||||
nsRect *foo = new nsRect(0, 0, aAlloc->width, aAlloc->height);
|
||||
anEvent.windowSize = foo;
|
||||
// anEvent.point.x = aAlloc->x;
|
||||
// anEvent.point.y = aAlloc->y;
|
||||
// HACK
|
||||
anEvent.point.x = 0;
|
||||
anEvent.point.y = 0;
|
||||
anEvent.mWinWidth = aAlloc->width;
|
||||
anEvent.mWinHeight = aAlloc->height;
|
||||
}
|
||||
|
||||
anEvent.time = PR_IntervalNow();
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
void InitConfigureEvent(GdkEventConfigure *aConf,
|
||||
gpointer p,
|
||||
nsSizeEvent &anEvent,
|
||||
PRUint32 aEventType)
|
||||
{
|
||||
anEvent.message = aEventType;
|
||||
anEvent.widget = (nsWidget *) p;
|
||||
|
||||
anEvent.eventStructType = NS_SIZE_EVENT;
|
||||
|
||||
if (aConf != nsnull) {
|
||||
/* do we accually need to alloc a new rect, or can we just set the
|
||||
current one */
|
||||
nsRect *foo = new nsRect(aConf->x, aConf->y, aConf->width, aConf->height);
|
||||
anEvent.windowSize = foo;
|
||||
anEvent.point.x = aConf->x;
|
||||
anEvent.point.y = aConf->y;
|
||||
anEvent.mWinWidth = aConf->width;
|
||||
anEvent.mWinHeight = aConf->height;
|
||||
}
|
||||
// this usually returns 0
|
||||
anEvent.time = 0;
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
void InitExposeEvent(GdkEventExpose *aGEE,
|
||||
gpointer p,
|
||||
nsPaintEvent &anEvent,
|
||||
PRUint32 aEventType)
|
||||
{
|
||||
anEvent.message = aEventType;
|
||||
anEvent.widget = (nsWidget *) p;
|
||||
|
||||
anEvent.eventStructType = NS_PAINT_EVENT;
|
||||
|
||||
if (aGEE != nsnull)
|
||||
{
|
||||
#ifdef DEBUG_EVENTS
|
||||
g_print("expose event: x = %i , y = %i , w = %i , h = %i\n",
|
||||
aGEE->area.x, aGEE->area.y,
|
||||
aGEE->area.width, aGEE->area.height);
|
||||
#endif
|
||||
anEvent.point.x = aGEE->area.x;
|
||||
anEvent.point.y = aGEE->area.y;
|
||||
|
||||
nsRect *rect = new nsRect(aGEE->area.x, aGEE->area.y,
|
||||
aGEE->area.width, aGEE->area.height);
|
||||
anEvent.rect = rect;
|
||||
anEvent.time = gdk_event_get_time((GdkEvent*)aGEE);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================
|
||||
void UninitExposeEvent(GdkEventExpose *aGEE,
|
||||
gpointer p,
|
||||
nsPaintEvent &anEvent,
|
||||
PRUint32 aEventType)
|
||||
{
|
||||
if (aGEE != nsnull) {
|
||||
delete anEvent.rect;
|
||||
}
|
||||
}
|
||||
|
||||
struct nsKeyConverter {
|
||||
int vkCode; // Platform independent key code
|
||||
int keysym; // GDK keysym key code
|
||||
};
|
||||
|
||||
//
|
||||
// Netscape keycodes are defined in widget/public/nsGUIEvent.h
|
||||
// GTK keycodes are defined in <gdk/gdkkeysyms.h>
|
||||
//
|
||||
struct nsKeyConverter nsKeycodes[] = {
|
||||
{ NS_VK_CANCEL, GDK_Cancel },
|
||||
{ NS_VK_BACK, GDK_BackSpace },
|
||||
{ NS_VK_TAB, GDK_Tab },
|
||||
{ NS_VK_TAB, GDK_ISO_Left_Tab },
|
||||
{ NS_VK_CLEAR, GDK_Clear },
|
||||
{ NS_VK_RETURN, GDK_Return },
|
||||
{ NS_VK_SHIFT, GDK_Shift_L },
|
||||
{ NS_VK_SHIFT, GDK_Shift_R },
|
||||
{ NS_VK_CONTROL, GDK_Control_L },
|
||||
{ NS_VK_CONTROL, GDK_Control_R },
|
||||
{ NS_VK_ALT, GDK_Alt_L },
|
||||
{ NS_VK_ALT, GDK_Alt_R },
|
||||
{ NS_VK_PAUSE, GDK_Pause },
|
||||
{ NS_VK_CAPS_LOCK, GDK_Caps_Lock },
|
||||
{ NS_VK_ESCAPE, GDK_Escape },
|
||||
{ NS_VK_SPACE, GDK_space },
|
||||
{ NS_VK_PAGE_UP, GDK_Page_Up },
|
||||
{ NS_VK_PAGE_DOWN, GDK_Page_Down },
|
||||
{ NS_VK_END, GDK_End },
|
||||
{ NS_VK_HOME, GDK_Home },
|
||||
{ NS_VK_LEFT, GDK_Left },
|
||||
{ NS_VK_UP, GDK_Up },
|
||||
{ NS_VK_RIGHT, GDK_Right },
|
||||
{ NS_VK_DOWN, GDK_Down },
|
||||
{ NS_VK_PRINTSCREEN, GDK_Print },
|
||||
{ NS_VK_INSERT, GDK_Insert },
|
||||
{ NS_VK_DELETE, GDK_Delete },
|
||||
|
||||
{ NS_VK_MULTIPLY, GDK_KP_Multiply },
|
||||
{ NS_VK_ADD, GDK_KP_Add },
|
||||
{ NS_VK_SEPARATOR, GDK_KP_Separator },
|
||||
{ NS_VK_SUBTRACT, GDK_KP_Subtract },
|
||||
{ NS_VK_DECIMAL, GDK_KP_Decimal },
|
||||
{ NS_VK_DIVIDE, GDK_KP_Divide },
|
||||
{ NS_VK_RETURN, GDK_KP_Enter },
|
||||
|
||||
// NS doesn't have dash or equals distinct from the numeric keypad ones,
|
||||
// so we'll use those for now. See bug 17008:
|
||||
{ NS_VK_SUBTRACT, GDK_minus },
|
||||
{ NS_VK_EQUALS, GDK_equal },
|
||||
// and we don't have a single-quote symbol either:
|
||||
{ NS_VK_QUOTE, GDK_apostrophe },
|
||||
|
||||
{ NS_VK_COMMA, GDK_comma },
|
||||
{ NS_VK_PERIOD, GDK_period },
|
||||
{ NS_VK_SLASH, GDK_slash },
|
||||
{ NS_VK_BACK_SLASH, GDK_backslash },
|
||||
{ NS_VK_BACK_QUOTE, GDK_grave },
|
||||
{ NS_VK_OPEN_BRACKET, GDK_bracketleft },
|
||||
{ NS_VK_CLOSE_BRACKET, GDK_bracketright },
|
||||
{ NS_VK_QUOTE, GDK_quotedbl },
|
||||
|
||||
// Some shifted keys, see bug 15463.
|
||||
// These should be subject to different keyboard mappings;
|
||||
// how do we do that in gtk?
|
||||
{ NS_VK_SEMICOLON, GDK_colon },
|
||||
{ NS_VK_BACK_QUOTE, GDK_asciitilde },
|
||||
{ NS_VK_COMMA, GDK_less },
|
||||
{ NS_VK_PERIOD, GDK_greater },
|
||||
{ NS_VK_SLASH, GDK_question },
|
||||
{ NS_VK_1, GDK_exclam },
|
||||
{ NS_VK_2, GDK_at },
|
||||
{ NS_VK_3, GDK_numbersign },
|
||||
{ NS_VK_4, GDK_dollar },
|
||||
{ NS_VK_5, GDK_percent },
|
||||
{ NS_VK_6, GDK_asciicircum },
|
||||
{ NS_VK_7, GDK_ampersand },
|
||||
{ NS_VK_8, GDK_asterisk },
|
||||
{ NS_VK_9, GDK_parenleft },
|
||||
{ NS_VK_0, GDK_parenright },
|
||||
{ NS_VK_SUBTRACT, GDK_underscore },
|
||||
{ NS_VK_EQUALS, GDK_plus }
|
||||
};
|
||||
|
||||
void nsGtkWidget_InitNSKeyEvent(int aEventType, nsKeyEvent& aKeyEvent,
|
||||
GtkWidget *w, gpointer p, GdkEventKey * event);
|
||||
|
||||
//==============================================================
|
||||
|
||||
// Input keysym is in gtk format; output is in NS_VK format
|
||||
int nsPlatformToDOMKeyCode(GdkEventKey *aGEK)
|
||||
{
|
||||
int i;
|
||||
int length = sizeof(nsKeycodes) / sizeof(struct nsKeyConverter);
|
||||
|
||||
int keysym = aGEK->keyval;
|
||||
|
||||
// First, try to handle alphanumeric input, not listed in nsKeycodes:
|
||||
// most likely, more letters will be getting typed in than things in
|
||||
// the key list, so we will look through these first.
|
||||
|
||||
// since X has different key symbols for upper and lowercase letters and
|
||||
// mozilla does not, convert gdk's to mozilla's
|
||||
if (keysym >= GDK_a && keysym <= GDK_z)
|
||||
return keysym - GDK_a + NS_VK_A;
|
||||
if (keysym >= GDK_A && keysym <= GDK_Z)
|
||||
return keysym - GDK_A + NS_VK_A;
|
||||
|
||||
// numbers
|
||||
if (keysym >= GDK_0 && keysym <= GDK_9)
|
||||
return keysym - GDK_0 + NS_VK_0;
|
||||
|
||||
// keypad numbers
|
||||
if (keysym >= GDK_KP_0 && keysym <= GDK_KP_9)
|
||||
return keysym - GDK_KP_0 + NS_VK_NUMPAD0;
|
||||
|
||||
// misc other things
|
||||
for (i = 0; i < length; i++) {
|
||||
if (nsKeycodes[i].keysym == keysym)
|
||||
return(nsKeycodes[i].vkCode);
|
||||
}
|
||||
|
||||
// function keys
|
||||
if (keysym >= GDK_F1 && keysym <= GDK_F24)
|
||||
return keysym - GDK_F1 + NS_VK_F1;
|
||||
|
||||
#if defined(DEBUG_akkana) || defined(DEBUG_ftang)
|
||||
printf("No match in nsPlatformToDOMKeyCode: keysym is 0x%x, string is %s\n", keysym, aGEK->string);
|
||||
#endif
|
||||
|
||||
return((int)0);
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
|
||||
PRUint32 nsConvertCharCodeToUnicode(GdkEventKey* aGEK)
|
||||
{
|
||||
// For control chars, GDK sets string to be the actual ascii value.
|
||||
// Map that to what nsKeyEvent wants, which currently --
|
||||
// TEMPORARILY (the spec has changed and will be switched over
|
||||
// when the tree opens for M11) --
|
||||
// is the ascii for the actual event (e.g. 1 for control-a).
|
||||
// This is only true for control chars; for alt chars, send the
|
||||
// ascii for the key, i.e. a for alt-a.
|
||||
if (aGEK->state & GDK_CONTROL_MASK)
|
||||
{
|
||||
if (aGEK->state & GDK_SHIFT_MASK)
|
||||
return aGEK->string[0] + 'A' - 1;
|
||||
else
|
||||
return aGEK->string[0] + 'a' - 1;
|
||||
}
|
||||
|
||||
// For now (obviously this will need to change for IME),
|
||||
// only set a char code if the result is printable:
|
||||
if (!isprint(aGEK->string[0]))
|
||||
return 0;
|
||||
|
||||
// ALT keys in gdk give the upper case character in string,
|
||||
// but we want the lower case char in char code
|
||||
// unless shift was also pressed.
|
||||
if (((aGEK->state & GDK_MOD1_MASK))
|
||||
&& !(aGEK->state & GDK_SHIFT_MASK)
|
||||
&& isupper(aGEK->string[0]))
|
||||
return tolower(aGEK->string[0]);
|
||||
|
||||
//
|
||||
// placeholder for something a little more interesting and correct
|
||||
//
|
||||
return aGEK->string[0];
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
void InitKeyEvent(GdkEventKey *aGEK,
|
||||
gpointer p,
|
||||
nsKeyEvent &anEvent,
|
||||
PRUint32 aEventType)
|
||||
{
|
||||
anEvent.message = aEventType;
|
||||
anEvent.widget = (nsWidget *) p;
|
||||
|
||||
anEvent.eventStructType = NS_KEY_EVENT;
|
||||
|
||||
if (aGEK != nsnull) {
|
||||
anEvent.keyCode = nsPlatformToDOMKeyCode(aGEK);
|
||||
anEvent.charCode = 0;
|
||||
anEvent.time = aGEK->time;
|
||||
anEvent.isShift = (aGEK->state & GDK_SHIFT_MASK) ? PR_TRUE : PR_FALSE;
|
||||
anEvent.isControl = (aGEK->state & GDK_CONTROL_MASK) ? PR_TRUE : PR_FALSE;
|
||||
anEvent.isAlt = (aGEK->state & GDK_MOD1_MASK) ? PR_TRUE : PR_FALSE;
|
||||
// XXX
|
||||
anEvent.isMeta = PR_FALSE; //(aGEK->state & GDK_MOD2_MASK) ? PR_TRUE : PR_FALSE;
|
||||
anEvent.point.x = 0;
|
||||
anEvent.point.y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void InitKeyPressEvent(GdkEventKey *aGEK,
|
||||
gpointer p,
|
||||
nsKeyEvent &anEvent)
|
||||
{
|
||||
//
|
||||
// init the basic event fields
|
||||
//
|
||||
anEvent.eventStructType = NS_KEY_EVENT;
|
||||
anEvent.message = NS_KEY_PRESS;
|
||||
anEvent.widget = (nsWidget*)p;
|
||||
|
||||
if (aGEK!=nsnull)
|
||||
{
|
||||
anEvent.isShift = (aGEK->state & GDK_SHIFT_MASK) ? PR_TRUE : PR_FALSE;
|
||||
anEvent.isControl = (aGEK->state & GDK_CONTROL_MASK) ? PR_TRUE : PR_FALSE;
|
||||
anEvent.isAlt = (aGEK->state & GDK_MOD1_MASK) ? PR_TRUE : PR_FALSE;
|
||||
// XXX
|
||||
anEvent.isMeta = PR_FALSE; //(aGEK->state & GDK_MOD2_MASK) ? PR_TRUE : PR_FALSE;
|
||||
|
||||
if(aGEK->length)
|
||||
anEvent.charCode = nsConvertCharCodeToUnicode(aGEK);
|
||||
else
|
||||
anEvent.charCode = 0;
|
||||
|
||||
if (anEvent.charCode) {
|
||||
anEvent.keyCode = 0;
|
||||
anEvent.isShift = PR_FALSE;
|
||||
} else
|
||||
anEvent.keyCode = nsPlatformToDOMKeyCode(aGEK);
|
||||
|
||||
#if defined(DEBUG_akkana) || defined(DEBUG_pavlov) || defined (DEBUG_ftang)
|
||||
printf("Key Press event: keyCode = 0x%x, char code = '%c'",
|
||||
anEvent.keyCode, anEvent.charCode);
|
||||
if (anEvent.isShift)
|
||||
printf(" [shift]");
|
||||
if (anEvent.isControl)
|
||||
printf(" [ctrl]");
|
||||
if (anEvent.isAlt)
|
||||
printf(" [alt]");
|
||||
if (anEvent.isMeta)
|
||||
printf(" [meta]");
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
anEvent.time = aGEK->time;
|
||||
anEvent.point.x = 0;
|
||||
anEvent.point.y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================
|
||||
void UninitKeyEvent(GdkEventKey *aGEK,
|
||||
gpointer p,
|
||||
nsKeyEvent &anEvent,
|
||||
PRUint32 aEventType)
|
||||
{
|
||||
}
|
||||
|
||||
/*==============================================================
|
||||
==============================================================
|
||||
=============================================================
|
||||
==============================================================*/
|
||||
|
||||
void handle_size_allocate(GtkWidget *w, GtkAllocation *alloc, gpointer p)
|
||||
{
|
||||
nsWindow *widget = (nsWindow *)p;
|
||||
nsSizeEvent event;
|
||||
|
||||
InitAllocationEvent(alloc, p, event, NS_SIZE);
|
||||
NS_ADDREF(widget);
|
||||
widget->OnResize(event);
|
||||
NS_RELEASE(widget);
|
||||
|
||||
delete event.windowSize;
|
||||
}
|
||||
|
||||
gint handle_expose_event(GtkWidget *w, GdkEventExpose *event, gpointer p)
|
||||
{
|
||||
if (event->type == GDK_NO_EXPOSE)
|
||||
return PR_FALSE;
|
||||
|
||||
nsPaintEvent pevent;
|
||||
InitExposeEvent(event, p, pevent, NS_PAINT);
|
||||
|
||||
nsWindow *win = (nsWindow *)p;
|
||||
win->AddRef();
|
||||
win->OnExpose(pevent);
|
||||
win->Release();
|
||||
|
||||
UninitExposeEvent(event, p, pevent, NS_PAINT);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
void menu_item_activate_handler(GtkWidget *w, gpointer p)
|
||||
{
|
||||
// g_print("menu_item_activate_handler\n");
|
||||
|
||||
nsIMenuListener *menuListener = nsnull;
|
||||
nsIMenuItem *menuItem = (nsIMenuItem *)p;
|
||||
if (menuItem != nsnull) {
|
||||
nsMenuEvent mevent;
|
||||
mevent.message = NS_MENU_SELECTED;
|
||||
mevent.eventStructType = NS_MENU_EVENT;
|
||||
mevent.point.x = 0;
|
||||
mevent.point.y = 0;
|
||||
// mevent.widget = menuItem;
|
||||
mevent.widget = nsnull;
|
||||
menuItem->GetCommand(mevent.mCommand);
|
||||
|
||||
mevent.mMenuItem = menuItem;
|
||||
mevent.time = PR_IntervalNow();
|
||||
|
||||
// FIXME - THIS SHOULD WORK. FIX EVENTS FOR XP CODE!!!!! (pav)
|
||||
// nsEventStatus status;
|
||||
// mevent.widget->DispatchEvent((nsGUIEvent *)&mevent, status);
|
||||
|
||||
menuItem->QueryInterface(nsIMenuListener::GetIID(), (void**)&menuListener);
|
||||
if(menuListener) {
|
||||
menuListener->MenuItemSelected(mevent);
|
||||
NS_IF_RELEASE(menuListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
void menu_map_handler(GtkWidget *w, gpointer p)
|
||||
{
|
||||
nsIMenuListener *menuListener = nsnull;
|
||||
nsIMenu *menu = (nsIMenu *)p;
|
||||
if (menu != nsnull) {
|
||||
nsMenuEvent mevent;
|
||||
mevent.message = NS_MENU_SELECTED;
|
||||
mevent.eventStructType = NS_MENU_EVENT;
|
||||
mevent.point.x = 0;
|
||||
mevent.point.y = 0;
|
||||
mevent.widget = nsnull;
|
||||
|
||||
mevent.time = PR_IntervalNow();
|
||||
|
||||
menu->QueryInterface(nsIMenuListener::GetIID(), (void**)&menuListener);
|
||||
|
||||
if(menuListener) {
|
||||
menuListener->MenuConstruct(
|
||||
mevent,
|
||||
nsnull, //parent window
|
||||
nsnull, //menuNode
|
||||
nsnull ); // webshell
|
||||
NS_IF_RELEASE(menuListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
void menu_unmap_handler(GtkWidget *w, gpointer p)
|
||||
{
|
||||
nsIMenuListener *menuListener = nsnull;
|
||||
nsIMenu *menu = (nsIMenu *)p;
|
||||
if (menu != nsnull) {
|
||||
nsMenuEvent mevent;
|
||||
mevent.message = NS_MENU_SELECTED;
|
||||
mevent.eventStructType = NS_MENU_EVENT;
|
||||
mevent.point.x = 0;
|
||||
mevent.point.y = 0;
|
||||
mevent.widget = nsnull;
|
||||
|
||||
mevent.time = PR_IntervalNow();
|
||||
|
||||
menu->QueryInterface(nsIMenuListener::GetIID(), (void**)&menuListener);
|
||||
if(menuListener) {
|
||||
menuListener->MenuDestruct(mevent);
|
||||
NS_IF_RELEASE(menuListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==============================================================
|
||||
void handle_scrollbar_value_changed(GtkAdjustment *adj, gpointer p)
|
||||
{
|
||||
nsScrollbar *widget = (nsScrollbar*) p;
|
||||
nsScrollbarEvent sevent;
|
||||
|
||||
sevent.message = NS_SCROLLBAR_POS;
|
||||
sevent.widget = (nsWidget *) p;
|
||||
sevent.eventStructType = NS_SCROLLBAR_EVENT;
|
||||
|
||||
GdkWindow *win = (GdkWindow *)widget->GetNativeData(NS_NATIVE_WINDOW);
|
||||
gdk_window_get_pointer(win, &sevent.point.x, &sevent.point.y, nsnull);
|
||||
|
||||
widget->AddRef();
|
||||
widget->OnScroll(sevent, adj->value);
|
||||
widget->Release();
|
||||
|
||||
/* FIXME we need to set point.* from the event stuff. */
|
||||
#if 0
|
||||
nsWindow * widgetWindow = (nsWindow *) p ;
|
||||
XmScrollBarCallbackStruct * cbs = (XmScrollBarCallbackStruct*) call_data;
|
||||
sevent.widget = (nsWindow *) p;
|
||||
if (cbs->event != nsnull) {
|
||||
sevent.point.x = cbs->event->xbutton.x;
|
||||
sevent.point.y = cbs->event->xbutton.y;
|
||||
} else {
|
||||
sevent.point.x = 0;
|
||||
sevent.point.y = 0;
|
||||
}
|
||||
sevent.time = 0; //XXX Implement this
|
||||
|
||||
switch (cbs->reason) {
|
||||
|
||||
case XmCR_INCREMENT:
|
||||
sevent.message = NS_SCROLLBAR_LINE_NEXT;
|
||||
break;
|
||||
|
||||
case XmCR_DECREMENT:
|
||||
sevent.message = NS_SCROLLBAR_LINE_PREV;
|
||||
break;
|
||||
|
||||
case XmCR_PAGE_INCREMENT:
|
||||
sevent.message = NS_SCROLLBAR_PAGE_NEXT;
|
||||
break;
|
||||
|
||||
case XmCR_PAGE_DECREMENT:
|
||||
sevent.message = NS_SCROLLBAR_PAGE_PREV;
|
||||
break;
|
||||
|
||||
case XmCR_DRAG:
|
||||
sevent.message = NS_SCROLLBAR_POS;
|
||||
break;
|
||||
|
||||
case XmCR_VALUE_CHANGED:
|
||||
sevent.message = NS_SCROLLBAR_POS;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static gint composition_start(GdkEventKey *aEvent, nsWindow *aWin,
|
||||
nsEventStatus *aStatus) {
|
||||
nsCompositionEvent compEvent;
|
||||
|
||||
compEvent.widget = (nsWidget*)aWin;
|
||||
compEvent.point.x = 0;
|
||||
compEvent.point.y = 0;
|
||||
compEvent.time = aEvent->time;
|
||||
compEvent.message = NS_COMPOSITION_START;
|
||||
compEvent.eventStructType = NS_COMPOSITION_START;
|
||||
compEvent.compositionMessage = NS_COMPOSITION_START;
|
||||
aWin->DispatchEvent(&compEvent, *aStatus);
|
||||
|
||||
// set SpotLocation
|
||||
aWin->SetXICSpotLocation(compEvent.theReply.mCursorPosition);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static gint composition_draw(GdkEventKey *aEvent, nsWindow *aWin,
|
||||
nsIUnicodeDecoder *aDecoder,
|
||||
nsEventStatus *aStatus) {
|
||||
if (!aWin->mIMECompositionUniString) {
|
||||
aWin->mIMECompositionUniStringSize = 128;
|
||||
aWin->mIMECompositionUniString =
|
||||
new PRUnichar[aWin->mIMECompositionUniStringSize];
|
||||
}
|
||||
PRUnichar *uniChar;
|
||||
PRInt32 uniCharSize;
|
||||
PRInt32 srcLen = aEvent->length;
|
||||
for (;;) {
|
||||
uniChar = aWin->mIMECompositionUniString;
|
||||
uniCharSize = aWin->mIMECompositionUniStringSize - 1;
|
||||
aDecoder->Convert((char*)aEvent->string, &srcLen, uniChar, &uniCharSize);
|
||||
if (srcLen == aEvent->length &&
|
||||
uniCharSize < aWin->mIMECompositionUniStringSize - 1) {
|
||||
break;
|
||||
}
|
||||
aWin->mIMECompositionUniStringSize += 32;
|
||||
aWin->mIMECompositionUniString =
|
||||
new PRUnichar[aWin->mIMECompositionUniStringSize];
|
||||
}
|
||||
aWin->mIMECompositionUniString[uniCharSize] = 0;
|
||||
|
||||
nsTextEvent textEvent;
|
||||
textEvent.message = NS_TEXT_EVENT;
|
||||
textEvent.widget = (nsWidget*)aWin;
|
||||
textEvent.time = aEvent->time;
|
||||
textEvent.point.x = 0;
|
||||
textEvent.point.y = 0;
|
||||
textEvent.theText = aWin->mIMECompositionUniString;
|
||||
textEvent.rangeCount = 0;
|
||||
textEvent.rangeArray = nsnull;
|
||||
textEvent.isShift = (aEvent->state & GDK_SHIFT_MASK) ? PR_TRUE : PR_FALSE;
|
||||
textEvent.isControl = (aEvent->state & GDK_CONTROL_MASK) ? PR_TRUE : PR_FALSE;
|
||||
textEvent.isAlt = (aEvent->state & GDK_MOD1_MASK) ? PR_TRUE : PR_FALSE;
|
||||
// XXX
|
||||
textEvent.isMeta = PR_FALSE; //(aEvent->state & GDK_MOD2_MASK) ? PR_TRUE : PR_FALSE;
|
||||
textEvent.eventStructType = NS_TEXT_EVENT;
|
||||
aWin->DispatchEvent(&textEvent, *aStatus);
|
||||
|
||||
aWin->SetXICSpotLocation(textEvent.theReply.mCursorPosition);
|
||||
return True;
|
||||
}
|
||||
|
||||
static gint composition_end(GdkEventKey *aEvent, nsWindow *aWin,
|
||||
nsEventStatus *aStatus) {
|
||||
nsCompositionEvent compEvent;
|
||||
|
||||
compEvent.widget = (nsWidget*)aWin;
|
||||
compEvent.point.x = 0;
|
||||
compEvent.point.y = 0;
|
||||
compEvent.time = aEvent->time;
|
||||
compEvent.message = NS_COMPOSITION_END;
|
||||
compEvent.eventStructType = NS_COMPOSITION_END;
|
||||
compEvent.compositionMessage = NS_COMPOSITION_END;
|
||||
aWin->DispatchEvent(&compEvent, *aStatus);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static nsIUnicodeDecoder*
|
||||
open_unicode_decoder(void) {
|
||||
nsresult result = NS_ERROR_FAILURE;
|
||||
nsIUnicodeDecoder *decoder = nsnull;
|
||||
NS_WITH_SERVICE(nsIPlatformCharset, platform, NS_PLATFORMCHARSET_PROGID,
|
||||
&result);
|
||||
if (platform && NS_SUCCEEDED(result)) {
|
||||
nsAutoString charset("");
|
||||
result = platform->GetCharset(kPlatformCharsetSel_Menu, charset);
|
||||
if (NS_FAILED(result) || (charset.Length() == 0)) {
|
||||
charset = "ISO-8859-1"; // default
|
||||
}
|
||||
nsICharsetConverterManager* manager = nsnull;
|
||||
nsresult res = nsServiceManager::
|
||||
GetService(kCharsetConverterManagerCID,
|
||||
nsCOMTypeInfo<nsICharsetConverterManager>::GetIID(),
|
||||
(nsISupports**)&manager);
|
||||
if (manager && NS_SUCCEEDED(res)) {
|
||||
manager->GetUnicodeDecoder(&charset, &decoder);
|
||||
nsServiceManager::ReleaseService(kCharsetConverterManagerCID, manager);
|
||||
}
|
||||
}
|
||||
return decoder;
|
||||
}
|
||||
|
||||
// GTK's text widget already does XIM, so we don't want to do this again
|
||||
gint handle_key_press_event_for_text(GtkObject *w, GdkEventKey* event,
|
||||
gpointer p)
|
||||
{
|
||||
nsKeyEvent kevent;
|
||||
nsTextWidget* win = (nsTextWidget*)p;
|
||||
|
||||
// work around for annoying things.
|
||||
if (event->keyval == GDK_Tab)
|
||||
if (event->state & GDK_CONTROL_MASK)
|
||||
if (event->state & GDK_MOD1_MASK)
|
||||
return PR_FALSE;
|
||||
|
||||
// Don't pass shift, control and alt as key press events
|
||||
if (event->keyval == GDK_Shift_L
|
||||
|| event->keyval == GDK_Shift_R
|
||||
|| event->keyval == GDK_Control_L
|
||||
|| event->keyval == GDK_Control_R)
|
||||
return PR_TRUE;
|
||||
|
||||
win->AddRef();
|
||||
InitKeyEvent(event, p, kevent, NS_KEY_DOWN);
|
||||
win->OnKey(kevent);
|
||||
|
||||
//
|
||||
// Second, dispatch the Key event as a key press event w/ a Unicode
|
||||
// character code. Note we have to check for modifier keys, since
|
||||
// gtk returns a character value for them
|
||||
//
|
||||
InitKeyPressEvent(event,p, kevent);
|
||||
win->OnKey(kevent);
|
||||
|
||||
win->Release();
|
||||
if (w)
|
||||
{
|
||||
gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_press_event");
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// GTK's text widget already does XIM, so we don't want to do this again
|
||||
gint handle_key_release_event_for_text(GtkObject *w, GdkEventKey* event,
|
||||
gpointer p)
|
||||
{
|
||||
nsKeyEvent kevent;
|
||||
nsTextWidget* win = (nsTextWidget*)p;
|
||||
|
||||
// Don't pass shift, control and alt as key release events
|
||||
if (event->keyval == GDK_Shift_L
|
||||
|| event->keyval == GDK_Shift_R
|
||||
|| event->keyval == GDK_Control_L
|
||||
|| event->keyval == GDK_Control_R)
|
||||
return PR_TRUE;
|
||||
|
||||
InitKeyEvent(event, p, kevent, NS_KEY_UP);
|
||||
win->AddRef();
|
||||
win->OnKey(kevent);
|
||||
win->Release();
|
||||
|
||||
if (w)
|
||||
{
|
||||
gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_release_event");
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================
|
||||
gint handle_key_press_event(GtkObject *w, GdkEventKey* event, gpointer p)
|
||||
{
|
||||
nsKeyEvent kevent;
|
||||
nsWindow* win = (nsWindow*)p;
|
||||
|
||||
// work around for annoying things.
|
||||
if (event->keyval == GDK_Tab)
|
||||
if (event->state & GDK_CONTROL_MASK)
|
||||
if (event->state & GDK_MOD1_MASK)
|
||||
return PR_FALSE;
|
||||
|
||||
// Don't pass shift, control and alt as key press events
|
||||
if (event->keyval == GDK_Shift_L
|
||||
|| event->keyval == GDK_Shift_R
|
||||
|| event->keyval == GDK_Control_L
|
||||
|| event->keyval == GDK_Control_R)
|
||||
return PR_TRUE;
|
||||
|
||||
win->AddRef();
|
||||
//
|
||||
// First, dispatch the Key event as a virtual key down event
|
||||
//
|
||||
InitKeyEvent(event, p, kevent, NS_KEY_DOWN);
|
||||
win->OnKey(kevent);
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Second, dispatch the Key event as a key press event w/ a Unicode
|
||||
// character code. Note we have to check for modifier keys, since
|
||||
// gtk returns a character value for them
|
||||
//
|
||||
if (event->length) {
|
||||
static nsIUnicodeDecoder *decoder = nsnull;
|
||||
if (!decoder) {
|
||||
decoder = open_unicode_decoder();
|
||||
}
|
||||
if (decoder && (!kevent.keyCode)) {
|
||||
nsEventStatus status;
|
||||
composition_start(event, win, &status);
|
||||
composition_draw(event, win, decoder, &status);
|
||||
composition_end(event, win, &status);
|
||||
} else {
|
||||
InitKeyPressEvent(event,p, kevent);
|
||||
win->OnKey(kevent);
|
||||
nsEventStatus status;
|
||||
composition_start(event, win, &status);
|
||||
composition_end(event, win, &status);
|
||||
}
|
||||
} else { // for Home/End/Up/Down/Left/Right/PageUp/PageDown key
|
||||
InitKeyPressEvent(event,p, kevent);
|
||||
win->OnKey(kevent);
|
||||
}
|
||||
|
||||
win->Release();
|
||||
if (w)
|
||||
{
|
||||
gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_press_event");
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
gint handle_key_release_event(GtkObject *w, GdkEventKey* event, gpointer p)
|
||||
{
|
||||
// Don't pass shift, control and alt as key release events
|
||||
if (event->keyval == GDK_Shift_L
|
||||
|| event->keyval == GDK_Shift_R
|
||||
|| event->keyval == GDK_Control_L
|
||||
|| event->keyval == GDK_Control_R)
|
||||
return PR_TRUE;
|
||||
|
||||
nsKeyEvent kevent;
|
||||
InitKeyEvent(event, p, kevent, NS_KEY_UP);
|
||||
|
||||
nsWindow * win = (nsWindow *) p;
|
||||
win->AddRef();
|
||||
win->OnKey(kevent);
|
||||
win->Release();
|
||||
|
||||
if (w)
|
||||
{
|
||||
gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_release_event");
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
void
|
||||
handle_gdk_event (GdkEvent *event, gpointer data)
|
||||
{
|
||||
GtkObject *object = nsnull;
|
||||
|
||||
if (event->any.window)
|
||||
gdk_window_get_user_data (event->any.window, (void **)&object);
|
||||
|
||||
if (object != nsnull &&
|
||||
GDK_IS_SUPERWIN (object))
|
||||
{
|
||||
// It was an event on one of our superwindows
|
||||
|
||||
nsWindow *window = (nsWindow *)gtk_object_get_data (object, "nsWindow");
|
||||
|
||||
if (gtk_grab_get_current () != nsnull)
|
||||
{
|
||||
// A GTK+ grab is in effect. Rewrite the event to point to
|
||||
// our toplevel, and pass it through.
|
||||
// XXX: We should actually translate the coordinates
|
||||
|
||||
gdk_window_unref (event->any.window);
|
||||
event->any.window = GTK_WIDGET (window->GetMozArea())->window;
|
||||
gdk_window_ref (event->any.window);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle it ourselves.
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case GDK_KEY_PRESS:
|
||||
handle_key_press_event (NULL, &event->key, window);
|
||||
break;
|
||||
case GDK_KEY_RELEASE:
|
||||
handle_key_release_event (NULL, &event->key, window);
|
||||
break;
|
||||
default:
|
||||
window->HandleEvent (event);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_main_do_event (event);
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
void
|
||||
handle_xlib_shell_event(GdkSuperWin *superwin, XEvent *event, gpointer p)
|
||||
{
|
||||
nsWindow *window = (nsWindow *)p;
|
||||
switch(event->xany.type) {
|
||||
case ConfigureNotify:
|
||||
window->HandleXlibConfigureNotifyEvent(event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
void
|
||||
handle_xlib_bin_event(GdkSuperWin *superwin, XEvent *event, gpointer p)
|
||||
{
|
||||
nsWindow *window = (nsWindow *)p;
|
||||
|
||||
switch(event->xany.type) {
|
||||
case Expose:
|
||||
window->HandleXlibExposeEvent(event);
|
||||
break;
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
window->HandleXlibButtonEvent((XButtonEvent *)event);
|
||||
break;
|
||||
case MotionNotify:
|
||||
window->HandleXlibMotionNotifyEvent((XMotionEvent *) event);
|
||||
break;
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
window->HandleXlibCrossingEvent((XCrossingEvent *) event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
gint nsGtkWidget_FSBCancel_Callback(GtkWidget *w, gpointer p)
|
||||
{
|
||||
#if 0
|
||||
nsWindow *widgetWindow = (nsWindow*)gtk_object_get_user_data(GTK_OBJECT(w));
|
||||
nsFileWidget * widgetWindow = (nsFileWidget *) p ;
|
||||
if (p != nsnull) {
|
||||
widgetWindow->OnCancel();
|
||||
}
|
||||
#endif
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
gint nsGtkWidget_FSBOk_Callback(GtkWidget *w, gpointer p)
|
||||
{
|
||||
#if 0
|
||||
nsWindow *widgetWindow = (nsWindow*)gtk_object_get_user_data(GTK_OBJECT(w));
|
||||
nsFileWidget * widgetWindow = (nsFileWidget *) p;
|
||||
if (p != nsnull) {
|
||||
widgetWindow->OnOk();
|
||||
}
|
||||
#endif
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef __nsGtkEventHandler_h
|
||||
#define __nsGtkEventHandler_h
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include "gdksuperwin.h"
|
||||
|
||||
class nsIWidget;
|
||||
class nsIMenuItem;
|
||||
class nsIMenu;
|
||||
|
||||
gint handle_configure_event(GtkWidget *w, GdkEventConfigure *conf, gpointer p);
|
||||
void handle_size_allocate(GtkWidget *w, GtkAllocation *alloc, gpointer p);
|
||||
gint handle_expose_event(GtkWidget *w, GdkEventExpose *event, gpointer p);
|
||||
|
||||
|
||||
gint handle_key_release_event_for_text(GtkObject *w, GdkEventKey* event, gpointer p);
|
||||
gint handle_key_press_event_for_text(GtkObject *w, GdkEventKey* event, gpointer p);
|
||||
|
||||
gint handle_key_release_event(GtkObject *w, GdkEventKey* event, gpointer p);
|
||||
gint handle_key_press_event(GtkObject *w, GdkEventKey* event, gpointer p);
|
||||
|
||||
void handle_scrollbar_value_changed(GtkAdjustment *adjustment, gpointer p);
|
||||
|
||||
void menu_item_activate_handler(GtkWidget *w, gpointer p);
|
||||
|
||||
void menu_map_handler(GtkWidget *w, gpointer p);
|
||||
void menu_unmap_handler(GtkWidget *w, gpointer p);
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
gint nsGtkWidget_FSBCancel_Callback(GtkWidget *w, gpointer p);
|
||||
gint nsGtkWidget_FSBOk_Callback(GtkWidget *w, gpointer p);
|
||||
|
||||
//----------------------------------------------------
|
||||
gint CheckButton_Toggle_Callback(GtkWidget *w, gpointer p);
|
||||
|
||||
gint nsGtkWidget_RadioButton_ArmCallback(GtkWidget *w, gpointer p);
|
||||
gint nsGtkWidget_RadioButton_DisArmCallback(GtkWidget *w, gpointer p);
|
||||
|
||||
gint nsGtkWidget_Text_Callback(GtkWidget *w, GdkEventKey* event, gpointer p);
|
||||
gint nsGtkWidget_Expose_Callback(GtkWidget *w, gpointer p);
|
||||
|
||||
gint nsGtkWidget_Refresh_Callback(gpointer call_data);
|
||||
|
||||
void handle_xlib_shell_event(GdkSuperWin *superwin, XEvent *event, gpointer p);
|
||||
void handle_xlib_bin_event(GdkSuperWin *superwin, XEvent *event, gpointer p);
|
||||
void handle_gdk_event (GdkEvent *event, gpointer data);
|
||||
|
||||
#endif // __nsGtkEventHandler.h
|
||||
@@ -1,213 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nsGtkUtils.h"
|
||||
|
||||
#include <gdk/gdkx.h>
|
||||
#include <gdk/gdkprivate.h>
|
||||
|
||||
#if defined(__osf__) && !defined(_XOPEN_SOURCE_EXTENDED)
|
||||
/*
|
||||
** DEC's compiler requires _XOPEN_SOURCE_EXTENDED to be defined in
|
||||
** order for it to see the prototype for usleep in unistd.h, but if
|
||||
** we define that the build breaks long before getting here. So
|
||||
** put the prototype here explicitly.
|
||||
*/
|
||||
int usleep(useconds_t);
|
||||
#endif
|
||||
#if defined(__QNX__)
|
||||
#define usleep(s) sleep(s)
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
#if 0
|
||||
/* staitc */ gint
|
||||
nsGtkUtils::gdk_query_pointer(GdkWindow * window,
|
||||
gint * x_out,
|
||||
gint * y_out)
|
||||
{
|
||||
g_return_val_if_fail(NULL != window, FALSE);
|
||||
g_return_val_if_fail(NULL != x_out, FALSE);
|
||||
g_return_val_if_fail(NULL != y_out, FALSE);
|
||||
|
||||
Window root;
|
||||
Window child;
|
||||
int rootx, rooty;
|
||||
int winx = 0;
|
||||
int winy = 0;
|
||||
unsigned int xmask = 0;
|
||||
gint result = FALSE;
|
||||
|
||||
*x_out = -1;
|
||||
*y_out = -1;
|
||||
|
||||
result = XQueryPointer(GDK_WINDOW_XDISPLAY(window),
|
||||
GDK_WINDOW_XWINDOW(window),
|
||||
&root,
|
||||
&child,
|
||||
&rootx,
|
||||
&rooty,
|
||||
&winx,
|
||||
&winy,
|
||||
&xmask);
|
||||
|
||||
if (result)
|
||||
{
|
||||
*x_out = rootx;
|
||||
*y_out = rooty;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
//////////////////////////////////////////////////////////////////
|
||||
/* static */ void
|
||||
nsGtkUtils::gtk_widget_set_color(GtkWidget * widget,
|
||||
GtkRcFlags flags,
|
||||
GtkStateType state,
|
||||
GdkColor * color)
|
||||
{
|
||||
GtkRcStyle * rc_style;
|
||||
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (color != NULL);
|
||||
g_return_if_fail (flags == 0);
|
||||
|
||||
rc_style = (GtkRcStyle *) gtk_object_get_data (GTK_OBJECT (widget),
|
||||
"modify-style");
|
||||
|
||||
if (!rc_style)
|
||||
{
|
||||
rc_style = gtk_rc_style_new ();
|
||||
|
||||
gtk_widget_modify_style (widget, rc_style);
|
||||
|
||||
gtk_object_set_data (GTK_OBJECT (widget), "modify-style", rc_style);
|
||||
}
|
||||
|
||||
if (flags & GTK_RC_FG)
|
||||
{
|
||||
rc_style->color_flags[state] = GtkRcFlags(rc_style->color_flags[state] | GTK_RC_FG);
|
||||
rc_style->fg[state] = *color;
|
||||
}
|
||||
|
||||
if (flags & GTK_RC_BG)
|
||||
{
|
||||
rc_style->color_flags[state] = GtkRcFlags(rc_style->color_flags[state] | GTK_RC_BG);
|
||||
rc_style->bg[state] = *color;
|
||||
}
|
||||
|
||||
if (flags & GTK_RC_TEXT)
|
||||
{
|
||||
rc_style->color_flags[state] = GtkRcFlags(rc_style->color_flags[state] | GTK_RC_TEXT);
|
||||
rc_style->text[state] = *color;
|
||||
}
|
||||
|
||||
if (flags & GTK_RC_BASE)
|
||||
{
|
||||
rc_style->color_flags[state] = GtkRcFlags(rc_style->color_flags[state] | GTK_RC_BASE);
|
||||
rc_style->base[state] = *color;
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////
|
||||
/* static */ GdkModifierType
|
||||
nsGtkUtils::gdk_keyboard_get_modifiers()
|
||||
{
|
||||
GdkModifierType m = (GdkModifierType) 0;
|
||||
|
||||
gdk_window_get_pointer(NULL,NULL,NULL,&m);
|
||||
|
||||
return m;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////
|
||||
/* static */ void
|
||||
nsGtkUtils::gdk_window_flash(GdkWindow * aGdkWindow,
|
||||
unsigned int aTimes,
|
||||
unsigned long aInterval,
|
||||
GdkRectangle * aArea)
|
||||
{
|
||||
gint x;
|
||||
gint y;
|
||||
gint width;
|
||||
gint height;
|
||||
guint i;
|
||||
GdkGC * gc = 0;
|
||||
GdkColor white;
|
||||
|
||||
gdk_window_get_geometry(aGdkWindow,
|
||||
NULL,
|
||||
NULL,
|
||||
&width,
|
||||
&height,
|
||||
NULL);
|
||||
|
||||
gdk_window_get_origin (aGdkWindow,
|
||||
&x,
|
||||
&y);
|
||||
|
||||
gc = gdk_gc_new(GDK_ROOT_PARENT());
|
||||
|
||||
white.pixel = WhitePixel(gdk_display,DefaultScreen(gdk_display));
|
||||
|
||||
gdk_gc_set_foreground(gc,&white);
|
||||
gdk_gc_set_function(gc,GDK_XOR);
|
||||
gdk_gc_set_subwindow(gc,GDK_INCLUDE_INFERIORS);
|
||||
|
||||
/*
|
||||
* If an area is given, use that. Notice how out of whack coordinates
|
||||
* and dimentsions are not checked!!!
|
||||
*/
|
||||
if (aArea)
|
||||
{
|
||||
x += aArea->x;
|
||||
y += aArea->y;
|
||||
|
||||
width = aArea->width;
|
||||
height = aArea->height;
|
||||
}
|
||||
|
||||
/*
|
||||
* Need to do this twice so that the XOR effect can replace
|
||||
* the original window contents.
|
||||
*/
|
||||
for (i = 0; i < aTimes * 2; i++)
|
||||
{
|
||||
gdk_draw_rectangle(GDK_ROOT_PARENT(),
|
||||
gc,
|
||||
TRUE,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height);
|
||||
|
||||
gdk_flush();
|
||||
|
||||
usleep(aInterval);
|
||||
}
|
||||
|
||||
gdk_gc_destroy(gc);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////
|
||||
@@ -1,85 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef __nsGtkUtils_h
|
||||
#define __nsGtkUtils_h
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
struct nsGtkUtils
|
||||
{
|
||||
//
|
||||
// Wrapper for XQueryPointer
|
||||
//
|
||||
#if 0
|
||||
static gint gdk_query_pointer(GdkWindow * window,
|
||||
gint * x_out,
|
||||
gint * y_out);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Change a widget's background
|
||||
//
|
||||
// flags isa bit mask of the following bits:
|
||||
//
|
||||
// GTK_RC_FG
|
||||
// GTK_RC_BG
|
||||
// GTK_RC_TEXT
|
||||
// GTK_RC_BASE
|
||||
//
|
||||
// state is an enum:
|
||||
//
|
||||
// GTK_STATE_NORMAL,
|
||||
// GTK_STATE_ACTIVE,
|
||||
// GTK_STATE_PRELIGHT,
|
||||
// GTK_STATE_SELECTED,
|
||||
// GTK_STATE_INSENSITIVE
|
||||
//
|
||||
static void gtk_widget_set_color(GtkWidget * widget,
|
||||
GtkRcFlags flags,
|
||||
GtkStateType state,
|
||||
GdkColor * color);
|
||||
|
||||
/**
|
||||
* Return the current keyboard modifier state.
|
||||
*
|
||||
* @return the current keyboard modifier state.
|
||||
*
|
||||
*/
|
||||
static GdkModifierType gdk_keyboard_get_modifiers();
|
||||
|
||||
/**
|
||||
* Flash an area within a GDK window (or the whole window)
|
||||
*
|
||||
* @param aGdkWindow The GDK window to flash.
|
||||
* @param aTimes Number of times to flash the area.
|
||||
* @param aInterval Interval between flashes in milliseconds.
|
||||
* @param aArea The area to flash. The whole window if NULL.
|
||||
*
|
||||
*/
|
||||
static void gdk_window_flash(GdkWindow * aGdkWindow,
|
||||
unsigned int aTimes,
|
||||
unsigned long aInterval,
|
||||
GdkRectangle * aArea);
|
||||
};
|
||||
|
||||
#endif // __nsGtkEventHandler.h
|
||||
@@ -1,141 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "nsLabel.h"
|
||||
#include "nsString.h"
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsLabel, nsWidget)
|
||||
NS_IMPL_RELEASE_INHERITED(nsLabel, nsWidget)
|
||||
NS_IMPL_QUERY_INTERFACE2(nsLabel, nsILabel, nsIWidget)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsLabel constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsLabel::nsLabel() : nsWidget(), nsILabel()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mAlignment = eAlign_Left;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsLabel destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsLabel::~nsLabel()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the nativeLabel widget
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsLabel::CreateNative(GtkObject *parentWindow)
|
||||
{
|
||||
unsigned char alignment = GetNativeAlignment();
|
||||
|
||||
mWidget = gtk_label_new("");
|
||||
gtk_widget_set_name(mWidget, "nsLabel");
|
||||
gtk_misc_set_alignment(GTK_MISC(mWidget), 0.0, alignment);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsLabel::PreCreateWidget(nsWidgetInitData *aInitData)
|
||||
{
|
||||
if (nsnull != aInitData) {
|
||||
nsLabelInitData* data = (nsLabelInitData *) aInitData;
|
||||
mAlignment = data->mAlignment;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set alignment
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsLabel::SetAlignment(nsLabelAlignment aAlignment)
|
||||
{
|
||||
GtkJustification align;
|
||||
|
||||
mAlignment = aAlignment;
|
||||
|
||||
align = GetNativeAlignment();
|
||||
gtk_misc_set_alignment(GTK_MISC(mWidget), 0.0, align);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
GtkJustification nsLabel::GetNativeAlignment()
|
||||
{
|
||||
switch (mAlignment) {
|
||||
case eAlign_Right : return GTK_JUSTIFY_RIGHT;
|
||||
case eAlign_Left : return GTK_JUSTIFY_LEFT;
|
||||
case eAlign_Center: return GTK_JUSTIFY_CENTER;
|
||||
default :
|
||||
return GTK_JUSTIFY_LEFT;
|
||||
}
|
||||
return GTK_JUSTIFY_LEFT;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set this button label
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsLabel::SetLabel(const nsString& aText)
|
||||
{
|
||||
NS_ALLOC_STR_BUF(label, aText, 256);
|
||||
gtk_label_set(GTK_LABEL(mWidget), label);
|
||||
NS_FREE_STR_BUF(label);
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get this button label
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsLabel::GetLabel(nsString& aBuffer)
|
||||
{
|
||||
char * text;
|
||||
gtk_label_get(GTK_LABEL(mWidget), &text);
|
||||
aBuffer.SetLength(0);
|
||||
aBuffer.Append(text);
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef nsLabel_h__
|
||||
#define nsLabel_h__
|
||||
|
||||
#include "nsWidget.h"
|
||||
#include "nsILabel.h"
|
||||
|
||||
/**
|
||||
* Native GTK+ Label wrapper
|
||||
*/
|
||||
class nsLabel : public nsWidget,
|
||||
public nsILabel
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
nsLabel();
|
||||
virtual ~nsLabel();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsILabel part
|
||||
NS_IMETHOD SetLabel(const nsString &aText);
|
||||
NS_IMETHOD GetLabel(nsString &aBuffer);
|
||||
NS_IMETHOD SetAlignment(nsLabelAlignment aAlignment);
|
||||
|
||||
NS_IMETHOD PreCreateWidget(nsWidgetInitData *aInitData);
|
||||
|
||||
virtual PRBool OnMove(PRInt32 aX, PRInt32 aY) { return PR_FALSE; }
|
||||
virtual PRBool OnResize(nsRect &aRect) { return PR_FALSE; }
|
||||
|
||||
|
||||
protected:
|
||||
NS_METHOD CreateNative(GtkObject *parentWindow);
|
||||
GtkJustification GetNativeAlignment();
|
||||
|
||||
nsLabelAlignment mAlignment;
|
||||
|
||||
};
|
||||
|
||||
#endif // nsLabel_h__
|
||||
@@ -1,394 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "nsListBox.h"
|
||||
#include "nsString.h"
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsListBox, nsWidget)
|
||||
NS_IMPL_RELEASE_INHERITED(nsListBox, nsWidget)
|
||||
NS_IMPL_QUERY_INTERFACE3(nsListBox, nsIListBox, nsIListWidget, nsIWidget)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsListBox constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsListBox::nsListBox() : nsWidget(), nsIListWidget(), nsIListBox()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mMultiSelect = PR_FALSE;
|
||||
mCList = nsnull;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsListBox:: destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsListBox::~nsListBox()
|
||||
{
|
||||
}
|
||||
|
||||
void nsListBox::InitCallbacks(char * aName)
|
||||
{
|
||||
InstallButtonPressSignal(mCList);
|
||||
InstallButtonReleaseSignal(mCList);
|
||||
|
||||
InstallEnterNotifySignal(mCList);
|
||||
InstallLeaveNotifySignal(mCList);
|
||||
|
||||
// These are needed so that the events will go to us and not our parent.
|
||||
AddToEventMask(mCList,
|
||||
GDK_BUTTON_PRESS_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_ENTER_NOTIFY_MASK |
|
||||
GDK_EXPOSURE_MASK |
|
||||
GDK_FOCUS_CHANGE_MASK |
|
||||
GDK_KEY_PRESS_MASK |
|
||||
GDK_KEY_RELEASE_MASK |
|
||||
GDK_LEAVE_NOTIFY_MASK |
|
||||
GDK_POINTER_MOTION_MASK);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// initializer
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP nsListBox::SetMultipleSelection(PRBool aMultipleSelections)
|
||||
{
|
||||
mMultiSelect = aMultipleSelections;
|
||||
if (mCList) {
|
||||
if (mMultiSelect)
|
||||
gtk_clist_set_selection_mode(GTK_CLIST(mCList), GTK_SELECTION_MULTIPLE);
|
||||
else
|
||||
gtk_clist_set_selection_mode(GTK_CLIST(mCList), GTK_SELECTION_BROWSE);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// AddItemAt
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP nsListBox::AddItemAt(nsString &aItem, PRInt32 aPosition)
|
||||
{
|
||||
if (mCList) {
|
||||
gchar *text[2];
|
||||
const nsAutoCString tempStr(aItem);
|
||||
text[0] = (gchar*)(const char *)tempStr;
|
||||
text[1] = (gchar*)NULL;
|
||||
gtk_clist_insert(GTK_CLIST(mCList), (int)aPosition, text);
|
||||
|
||||
// XXX Im not sure using the string address is the right thing to
|
||||
// store in the row data.
|
||||
gtk_clist_set_row_data(GTK_CLIST(mCList), aPosition, (gpointer)&aItem);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Finds an item at a postion
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRInt32 nsListBox::FindItem(nsString &aItem, PRInt32 aStartPos)
|
||||
{
|
||||
int i = -1;
|
||||
if (mCList) {
|
||||
i = gtk_clist_find_row_from_data(GTK_CLIST(mCList), (gpointer)&aItem);
|
||||
if (i < aStartPos) {
|
||||
i = -1;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// CountItems - Get Item Count
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRInt32 nsListBox::GetItemCount()
|
||||
{
|
||||
if (mCList) {
|
||||
return GTK_CLIST(mCList)->rows;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Removes an Item at a specified location
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool nsListBox::RemoveItemAt(PRInt32 aPosition)
|
||||
{
|
||||
if (mCList) {
|
||||
gtk_clist_remove(GTK_CLIST(mCList), aPosition);
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool nsListBox::GetItemAt(nsString& anItem, PRInt32 aPosition)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
anItem.Truncate();
|
||||
if (mCList) {
|
||||
char *text = nsnull;
|
||||
gtk_clist_get_text(GTK_CLIST(mCList),aPosition,0,&text);
|
||||
if (text) {
|
||||
anItem.Append(text);
|
||||
result = PR_TRUE;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Gets the selected of selected item
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsListBox::GetSelectedItem(nsString& aItem)
|
||||
{
|
||||
aItem.Truncate();
|
||||
if (mCList) {
|
||||
PRInt32 i=0, idx=-1;
|
||||
GtkCList *clist = GTK_CLIST(mCList);
|
||||
GList *list = clist->row_list;
|
||||
|
||||
for (i=0; i < clist->rows && idx == -1; i++, list = list->next) {
|
||||
if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED) {
|
||||
char *text = nsnull;
|
||||
gtk_clist_get_text(GTK_CLIST(mCList),i,0,&text);
|
||||
if (text) {
|
||||
aItem.Append(text);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Gets the list of selected otems
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRInt32 nsListBox::GetSelectedIndex()
|
||||
{
|
||||
PRInt32 i=0, idx=-1;
|
||||
if (mCList) {
|
||||
if (!mMultiSelect) {
|
||||
GtkCList *clist = GTK_CLIST(mCList);
|
||||
GList *list = clist->row_list;
|
||||
|
||||
for (i=0; i < clist->rows && idx == -1; i++, list = list->next) {
|
||||
if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED) {
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
NS_ASSERTION(PR_FALSE, "Multi selection list box does not support GetSelectedIndex()");
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// SelectItem
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsListBox::SelectItem(PRInt32 aPosition)
|
||||
{
|
||||
if (mCList) {
|
||||
gtk_clist_select_row(GTK_CLIST(mCList), aPosition, 0);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// GetSelectedCount
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRInt32 nsListBox::GetSelectedCount()
|
||||
{
|
||||
if (mCList) {
|
||||
if (!GTK_CLIST(mCList)->selection)
|
||||
return 0;
|
||||
else
|
||||
return (PRInt32)g_list_length(GTK_CLIST(mCList)->selection);
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// GetSelectedIndices
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsListBox::GetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize)
|
||||
{
|
||||
if (mCList) {
|
||||
PRInt32 i=0, num = 0;
|
||||
GtkCList *clist = GTK_CLIST(mCList);
|
||||
GList *list = clist->row_list;
|
||||
|
||||
for (i=0; i < clist->rows && num < aSize; i++, list = list->next) {
|
||||
if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED) {
|
||||
aIndices[num] = i;
|
||||
num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
PRInt32 i = 0;
|
||||
for (i = 0; i < aSize; i++) aIndices[i] = 0;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// SetSelectedIndices
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsListBox::SetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize)
|
||||
{
|
||||
if (mCList) {
|
||||
gtk_clist_unselect_all(GTK_CLIST(mCList));
|
||||
int i;
|
||||
for (i=0;i<aSize;i++) {
|
||||
SelectItem(aIndices[i]);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Deselect
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsListBox::Deselect()
|
||||
{
|
||||
if (mCList) {
|
||||
gtk_clist_unselect_all(GTK_CLIST(mCList));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set initial parameters
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsListBox::PreCreateWidget(nsWidgetInitData *aInitData)
|
||||
{
|
||||
if (nsnull != aInitData) {
|
||||
nsListBoxInitData* data = (nsListBoxInitData *) aInitData;
|
||||
mMultiSelect = data->mMultiSelect;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the native widget
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsListBox::CreateNative(GtkObject *parentWindow)
|
||||
{
|
||||
// to handle scrolling
|
||||
mWidget = gtk_scrolled_window_new (nsnull, nsnull);
|
||||
gtk_widget_set_name(mWidget, "nsListBox");
|
||||
gtk_container_set_border_width(GTK_CONTAINER(mWidget), 0);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (mWidget),
|
||||
GTK_POLICY_NEVER,
|
||||
GTK_POLICY_AUTOMATIC);
|
||||
|
||||
mCList = ::gtk_clist_new(1);
|
||||
gtk_clist_column_titles_hide(GTK_CLIST(mCList));
|
||||
// Default (it may be changed)
|
||||
gtk_clist_set_selection_mode(GTK_CLIST(mCList), GTK_SELECTION_BROWSE);
|
||||
SetMultipleSelection(mMultiSelect);
|
||||
gtk_widget_show(mCList);
|
||||
gtk_signal_connect(GTK_OBJECT(mCList),
|
||||
"destroy",
|
||||
GTK_SIGNAL_FUNC(DestroySignal),
|
||||
this);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (mWidget), mCList);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsListBox::OnDestroySignal(GtkWidget* aGtkWidget)
|
||||
{
|
||||
if (aGtkWidget == mCList) {
|
||||
mCList = nsnull;
|
||||
}
|
||||
else {
|
||||
nsWidget::OnDestroySignal(aGtkWidget);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// set font for listbox
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
/*virtual*/
|
||||
void nsListBox::SetFontNative(GdkFont *aFont)
|
||||
{
|
||||
GtkStyle *style = gtk_style_copy(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0))->style);
|
||||
// gtk_style_copy ups the ref count of the font
|
||||
gdk_font_unref (style->font);
|
||||
|
||||
style->font = aFont;
|
||||
gdk_font_ref(style->font);
|
||||
|
||||
gtk_widget_set_style(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0)), style);
|
||||
|
||||
gtk_style_unref(style);
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef nsListBox_h__
|
||||
#define nsListBox_h__
|
||||
|
||||
#include "nsWidget.h"
|
||||
#include "nsIListBox.h"
|
||||
|
||||
/**
|
||||
* Native GTK+ Listbox wrapper
|
||||
*/
|
||||
class nsListBox : public nsWidget,
|
||||
public nsIListWidget,
|
||||
public nsIListBox
|
||||
{
|
||||
|
||||
public:
|
||||
nsListBox();
|
||||
virtual ~nsListBox();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIListBox interface
|
||||
NS_IMETHOD PreCreateWidget(nsWidgetInitData *aInitData);
|
||||
NS_IMETHOD SetMultipleSelection(PRBool aMultipleSelections);
|
||||
NS_IMETHOD AddItemAt(nsString &aItem, PRInt32 aPosition);
|
||||
PRInt32 FindItem(nsString &aItem, PRInt32 aStartPos);
|
||||
PRInt32 GetItemCount();
|
||||
PRBool RemoveItemAt(PRInt32 aPosition);
|
||||
PRBool GetItemAt(nsString& anItem, PRInt32 aPosition);
|
||||
NS_IMETHOD GetSelectedItem(nsString& aItem);
|
||||
PRInt32 GetSelectedIndex();
|
||||
PRInt32 GetSelectedCount();
|
||||
NS_IMETHOD GetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize);
|
||||
NS_IMETHOD SetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize);
|
||||
NS_IMETHOD SelectItem(PRInt32 aPosition);
|
||||
NS_IMETHOD Deselect() ;
|
||||
|
||||
virtual void SetFontNative(GdkFont *aFont);
|
||||
|
||||
protected:
|
||||
NS_IMETHOD CreateNative(GtkObject *parentWindow);
|
||||
virtual void InitCallbacks(char * aName = nsnull);
|
||||
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
|
||||
|
||||
GtkWidget *mCList;
|
||||
PRBool mMultiSelect;
|
||||
};
|
||||
|
||||
#endif // nsListBox_h__
|
||||
@@ -1,316 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include "nsLookAndFeel.h"
|
||||
#include <gtk/gtkinvisible.h>
|
||||
|
||||
#define GDK_COLOR_TO_NS_RGB(c) \
|
||||
((nscolor) NS_RGB(c.red, c.green, c.blue))
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsLookAndFeel, nsILookAndFeel)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Query interface implementation
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsLookAndFeel::nsLookAndFeel()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mWidget = gtk_invisible_new();
|
||||
gtk_widget_ensure_style(mWidget);
|
||||
mStyle = gtk_widget_get_style(mWidget);
|
||||
}
|
||||
|
||||
nsLookAndFeel::~nsLookAndFeel()
|
||||
{
|
||||
gtk_widget_destroy(mWidget);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLookAndFeel::GetColor(const nsColorID aID, nscolor &aColor)
|
||||
{
|
||||
nsresult res = NS_OK;
|
||||
aColor = 0; // default color black
|
||||
|
||||
switch (aID) {
|
||||
case eColor_WindowBackground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_WindowForeground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_WidgetBackground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_WidgetForeground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_WidgetSelectBackground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_SELECTED]);
|
||||
break;
|
||||
case eColor_WidgetSelectForeground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_SELECTED]);
|
||||
break;
|
||||
case eColor_Widget3DHighlight:
|
||||
aColor = NS_RGB(0xa0,0xa0,0xa0);
|
||||
break;
|
||||
case eColor_Widget3DShadow:
|
||||
aColor = NS_RGB(0x40,0x40,0x40);
|
||||
break;
|
||||
case eColor_TextBackground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_TextForeground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_TextSelectBackground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_SELECTED]);
|
||||
break;
|
||||
case eColor_TextSelectForeground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->text[GTK_STATE_SELECTED]);
|
||||
break;
|
||||
|
||||
// css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
|
||||
case eColor_activeborder:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_activecaption:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_appworkspace:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_background:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
|
||||
case eColor_captiontext:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_graytext:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_INSENSITIVE]);
|
||||
break;
|
||||
case eColor_highlight:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_SELECTED]);
|
||||
break;
|
||||
case eColor_highlighttext:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_SELECTED]);
|
||||
break;
|
||||
case eColor_inactiveborder:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_inactivecaption:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_INSENSITIVE]);
|
||||
break;
|
||||
case eColor_inactivecaptiontext:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_INSENSITIVE]);
|
||||
break;
|
||||
case eColor_infobackground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_infotext:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_menu:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_menutext:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_scrollbar:
|
||||
break;
|
||||
|
||||
case eColor_threedface:
|
||||
case eColor_buttonface:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
|
||||
case eColor_buttonhighlight: // ?
|
||||
case eColor_threedhighlight:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_ACTIVE]);
|
||||
break;
|
||||
|
||||
case eColor_buttontext:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
|
||||
case eColor_buttonshadow:
|
||||
case eColor_threeddarkshadow:
|
||||
case eColor_threedshadow: // i think these should be the same
|
||||
aColor = NS_DarkenColor(NS_DarkenColor(NS_DarkenColor(NS_DarkenColor(NS_DarkenColor(GDK_COLOR_TO_NS_RGB(mStyle->light[GTK_STATE_NORMAL]))))));
|
||||
// aColor = GDK_COLOR_TO_NS_RGB(mStyle->dark[GTK_STATE_NORMAL]); // dark style gives me bright green?!
|
||||
break;
|
||||
|
||||
case eColor_threedlightshadow:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->light[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
|
||||
case eColor_window:
|
||||
case eColor_windowframe:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
|
||||
case eColor_windowtext:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* default color is BLACK */
|
||||
aColor = 0;
|
||||
res = NS_ERROR_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
// printf("%i, %i, %i\n", NS_GET_R(aColor), NS_GET_B(aColor), NS_GET_G(aColor));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
|
||||
{
|
||||
nsresult res = NS_OK;
|
||||
switch (aID) {
|
||||
case eMetric_WindowTitleHeight:
|
||||
aMetric = 0;
|
||||
break;
|
||||
case eMetric_WindowBorderWidth:
|
||||
// aMetric = mStyle->klass->xthickness;
|
||||
break;
|
||||
case eMetric_WindowBorderHeight:
|
||||
// aMetric = mStyle->klass->ythickness;
|
||||
break;
|
||||
case eMetric_Widget3DBorder:
|
||||
// aMetric = 4;
|
||||
break;
|
||||
case eMetric_TextFieldHeight:
|
||||
{
|
||||
GtkRequisition req;
|
||||
GtkWidget *text = gtk_entry_new();
|
||||
// needed to avoid memory leak
|
||||
gtk_widget_ref(text);
|
||||
gtk_object_sink(GTK_OBJECT(text));
|
||||
gtk_widget_size_request(text,&req);
|
||||
aMetric = req.height;
|
||||
gtk_widget_destroy(text);
|
||||
gtk_widget_unref(text);
|
||||
}
|
||||
break;
|
||||
case eMetric_TextFieldBorder:
|
||||
aMetric = 2;
|
||||
break;
|
||||
case eMetric_TextVerticalInsidePadding:
|
||||
aMetric = 0;
|
||||
break;
|
||||
case eMetric_TextShouldUseVerticalInsidePadding:
|
||||
aMetric = 0;
|
||||
break;
|
||||
case eMetric_TextHorizontalInsideMinimumPadding:
|
||||
aMetric = 15;
|
||||
break;
|
||||
case eMetric_TextShouldUseHorizontalInsideMinimumPadding:
|
||||
aMetric = 1;
|
||||
break;
|
||||
case eMetric_ButtonHorizontalInsidePaddingNavQuirks:
|
||||
aMetric = 10;
|
||||
break;
|
||||
case eMetric_ButtonHorizontalInsidePaddingOffsetNavQuirks:
|
||||
aMetric = 8;
|
||||
break;
|
||||
case eMetric_CheckboxSize:
|
||||
aMetric = 15;
|
||||
break;
|
||||
case eMetric_RadioboxSize:
|
||||
aMetric = 15;
|
||||
break;
|
||||
case eMetric_ListShouldUseHorizontalInsideMinimumPadding:
|
||||
aMetric = 15;
|
||||
break;
|
||||
case eMetric_ListHorizontalInsideMinimumPadding:
|
||||
aMetric = 15;
|
||||
break;
|
||||
case eMetric_ListShouldUseVerticalInsidePadding:
|
||||
aMetric = 1;
|
||||
break;
|
||||
case eMetric_ListVerticalInsidePadding:
|
||||
aMetric = 1;
|
||||
break;
|
||||
case eMetric_CaretBlinkTime:
|
||||
aMetric = 500;
|
||||
break;
|
||||
case eMetric_CaretWidthTwips:
|
||||
aMetric = 20;
|
||||
break;
|
||||
default:
|
||||
aMetric = 0;
|
||||
res = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricFloatID aID, float & aMetric)
|
||||
{
|
||||
nsresult res = NS_OK;
|
||||
switch (aID) {
|
||||
case eMetricFloat_TextFieldVerticalInsidePadding:
|
||||
aMetric = 0.25f;
|
||||
break;
|
||||
case eMetricFloat_TextFieldHorizontalInsidePadding:
|
||||
aMetric = 0.95f; // large number on purpose so minimum padding is used
|
||||
break;
|
||||
case eMetricFloat_TextAreaVerticalInsidePadding:
|
||||
aMetric = 0.40f;
|
||||
break;
|
||||
case eMetricFloat_TextAreaHorizontalInsidePadding:
|
||||
aMetric = 0.40f; // large number on purpose so minimum padding is used
|
||||
break;
|
||||
case eMetricFloat_ListVerticalInsidePadding:
|
||||
aMetric = 0.10f;
|
||||
break;
|
||||
case eMetricFloat_ListHorizontalInsidePadding:
|
||||
aMetric = 0.40f;
|
||||
break;
|
||||
case eMetricFloat_ButtonVerticalInsidePadding:
|
||||
aMetric = 0.25f;
|
||||
break;
|
||||
case eMetricFloat_ButtonHorizontalInsidePadding:
|
||||
aMetric = 0.25f;
|
||||
break;
|
||||
default:
|
||||
aMetric = -1.0;
|
||||
res = NS_ERROR_FAILURE;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
NS_IMETHODIMP nsLookAndFeel::GetNavSize(const nsMetricNavWidgetID aWidgetID,
|
||||
const nsMetricNavFontID aFontID,
|
||||
const PRInt32 aFontSize,
|
||||
nsSize &aSize)
|
||||
{
|
||||
aSize.width = 0;
|
||||
aSize.height = 0;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
#endif
|
||||
@@ -1,55 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef __nsLookAndFeel
|
||||
#define __nsLookAndFeel
|
||||
#include "nsILookAndFeel.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
class nsLookAndFeel: public nsILookAndFeel {
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
public:
|
||||
nsLookAndFeel();
|
||||
virtual ~nsLookAndFeel();
|
||||
|
||||
NS_IMETHOD GetColor(const nsColorID aID, nscolor &aColor);
|
||||
NS_IMETHOD GetMetric(const nsMetricID aID, PRInt32 & aMetric);
|
||||
NS_IMETHOD GetMetric(const nsMetricFloatID aID, float & aMetric);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
// This method returns the actual (or nearest estimate)
|
||||
// of the Navigator size for a given form control for a given font
|
||||
// and font size. This is used in NavQuirks mode to see how closely
|
||||
// we match its size
|
||||
NS_IMETHOD GetNavSize(const nsMetricNavWidgetID aWidgetID,
|
||||
const nsMetricNavFontID aFontID,
|
||||
const PRInt32 aFontSize,
|
||||
nsSize &aSize);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
GtkStyle *mStyle;
|
||||
GtkWidget *mWidget;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,792 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "nsMenu.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIMenuBar.h"
|
||||
#include "nsIMenuItem.h"
|
||||
#include "nsIMenuListener.h"
|
||||
#include "nsString.h"
|
||||
#include "nsGtkEventHandler.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
|
||||
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
|
||||
static NS_DEFINE_CID(kMenuItemCID, NS_MENUITEM_CID);
|
||||
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
|
||||
nsresult nsMenu::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
*aInstancePtr = NULL;
|
||||
|
||||
if (aIID.Equals(nsIMenu::GetIID())) {
|
||||
*aInstancePtr = (void*)(nsIMenu*) this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kISupportsIID)) {
|
||||
*aInstancePtr = (void*)(nsISupports*)(nsIMenu*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(nsIMenuListener::GetIID())) {
|
||||
*aInstancePtr = (void*)(nsIMenuListener*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(nsMenu)
|
||||
NS_IMPL_RELEASE(nsMenu)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsMenu constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsMenu::nsMenu() : nsIMenu()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mNumMenuItems = 0;
|
||||
mMenu = nsnull;
|
||||
mMenuParent = nsnull;
|
||||
mMenuBarParent = nsnull;
|
||||
mListener = nsnull;
|
||||
mConstructCalled = PR_FALSE;
|
||||
|
||||
mDOMNode = nsnull;
|
||||
mWebShell = nsnull;
|
||||
mDOMElement = nsnull;
|
||||
mAccessKey = "_";
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsMenu destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsMenu::~nsMenu()
|
||||
{
|
||||
//g_print("nsMenu::~nsMenu() called\n");
|
||||
NS_IF_RELEASE(mListener);
|
||||
// Free our menu items
|
||||
RemoveAll();
|
||||
gtk_widget_destroy(mMenu);
|
||||
mMenu = nsnull;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the proper widget
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::Create(nsISupports *aParent, const nsString &aLabel)
|
||||
{
|
||||
if(aParent)
|
||||
{
|
||||
nsIMenuBar * menubar = nsnull;
|
||||
aParent->QueryInterface(nsIMenuBar::GetIID(), (void**) &menubar);
|
||||
if(menubar)
|
||||
{
|
||||
mMenuBarParent = menubar;
|
||||
NS_RELEASE(menubar);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsIMenu * menu = nsnull;
|
||||
aParent->QueryInterface(nsIMenu::GetIID(), (void**) &menu);
|
||||
if(menu)
|
||||
{
|
||||
mMenuParent = menu;
|
||||
NS_RELEASE(menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mLabel = aLabel;
|
||||
mMenu = gtk_menu_new();
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (mMenu), "map",
|
||||
GTK_SIGNAL_FUNC(menu_map_handler),
|
||||
this);
|
||||
gtk_signal_connect (GTK_OBJECT (mMenu), "unmap",
|
||||
GTK_SIGNAL_FUNC(menu_unmap_handler),
|
||||
this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::GetParent(nsISupports*& aParent)
|
||||
{
|
||||
aParent = nsnull;
|
||||
if (nsnull != mMenuParent) {
|
||||
return mMenuParent->QueryInterface(kISupportsIID,
|
||||
(void**)&aParent);
|
||||
} else if (nsnull != mMenuBarParent) {
|
||||
return mMenuBarParent->QueryInterface(kISupportsIID,
|
||||
(void**)&aParent);
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::GetLabel(nsString &aText)
|
||||
{
|
||||
aText = mLabel;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::SetLabel(const nsString &aText)
|
||||
{
|
||||
/* we Do GetLabel() when we are adding the menu...
|
||||
* but we might want to redo this.
|
||||
*/
|
||||
mLabel = aText;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::GetAccessKey(nsString &aText)
|
||||
{
|
||||
aText = mAccessKey;
|
||||
char *foo = mAccessKey.ToNewCString();
|
||||
|
||||
#ifdef DEBUG_pavlov
|
||||
g_print("GetAccessKey returns \"%s\"\n", foo);
|
||||
#endif
|
||||
|
||||
nsCRT::free(foo);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::SetAccessKey(const nsString &aText)
|
||||
{
|
||||
mAccessKey = aText;
|
||||
char *foo = mAccessKey.ToNewCString();
|
||||
|
||||
#ifdef DEBUG_pavlov
|
||||
g_print("SetAccessKey setting to \"%s\"\n", foo);
|
||||
#endif
|
||||
|
||||
nsCRT::free(foo);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/**
|
||||
* Set enabled state
|
||||
*
|
||||
*/
|
||||
NS_METHOD nsMenu::SetEnabled(PRBool aIsEnabled)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/**
|
||||
* Get enabled state
|
||||
*
|
||||
*/
|
||||
NS_METHOD nsMenu::GetEnabled(PRBool* aIsEnabled)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/**
|
||||
* Query if this is the help menu
|
||||
*
|
||||
*/
|
||||
NS_METHOD nsMenu::IsHelpMenu(PRBool* aIsHelpMenu)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::AddItem(nsISupports * aItem)
|
||||
{
|
||||
if(aItem)
|
||||
{
|
||||
nsIMenuItem * menuitem = nsnull;
|
||||
aItem->QueryInterface(nsIMenuItem::GetIID(),
|
||||
(void**)&menuitem);
|
||||
if(menuitem)
|
||||
{
|
||||
AddMenuItem(menuitem); // nsMenu now owns this
|
||||
NS_RELEASE(menuitem);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsIMenu * menu = nsnull;
|
||||
aItem->QueryInterface(nsIMenu::GetIID(),
|
||||
(void**)&menu);
|
||||
if(menu)
|
||||
{
|
||||
AddMenu(menu); // nsMenu now owns this
|
||||
NS_RELEASE(menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// local method used by nsMenu::AddItem
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::AddMenuItem(nsIMenuItem * aMenuItem)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
void *voidData;
|
||||
|
||||
aMenuItem->GetNativeData(voidData);
|
||||
widget = GTK_WIDGET(voidData);
|
||||
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
|
||||
|
||||
// XXX add aMenuItem to internal data structor list
|
||||
// Need to be adding an nsISupports *, not nsIMenuItem *
|
||||
nsISupports * supports = nsnull;
|
||||
aMenuItem->QueryInterface(kISupportsIID,
|
||||
(void**)&supports);
|
||||
{
|
||||
mMenuItemVoidArray.AppendElement(supports);
|
||||
mNumMenuItems++;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// local method used by nsMenu::AddItem
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::AddMenu(nsIMenu * aMenu)
|
||||
{
|
||||
nsString Label;
|
||||
GtkWidget *newmenu=nsnull;
|
||||
void *voidData=NULL;
|
||||
|
||||
aMenu->GetLabel(Label);
|
||||
|
||||
// Create nsMenuItem
|
||||
nsIMenuItem * pnsMenuItem = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(kMenuItemCID,
|
||||
nsnull,
|
||||
nsIMenuItem::GetIID(),
|
||||
(void**)&pnsMenuItem);
|
||||
if (NS_OK == rv) {
|
||||
nsISupports * supports = nsnull;
|
||||
QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pnsMenuItem->Create(supports, Label, PR_FALSE); //PR_TRUE);
|
||||
NS_RELEASE(supports);
|
||||
|
||||
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
AddItem(supports); // Parent should now own menu item
|
||||
NS_RELEASE(supports);
|
||||
|
||||
void * menuitem = nsnull;
|
||||
pnsMenuItem->GetNativeData(menuitem);
|
||||
|
||||
voidData = NULL;
|
||||
aMenu->GetNativeData(&voidData);
|
||||
newmenu = GTK_WIDGET(voidData);
|
||||
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), newmenu);
|
||||
|
||||
NS_RELEASE(pnsMenuItem);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::AddSeparator()
|
||||
{
|
||||
// Create nsMenuItem
|
||||
nsIMenuItem * pnsMenuItem = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(
|
||||
kMenuItemCID, nsnull, nsIMenuItem::GetIID(), (void**)&pnsMenuItem);
|
||||
if (NS_OK == rv) {
|
||||
nsString tmp = "menuseparator";
|
||||
nsISupports * supports = nsnull;
|
||||
QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pnsMenuItem->Create(supports, tmp, PR_TRUE);
|
||||
NS_RELEASE(supports);
|
||||
|
||||
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
AddItem(supports); // Parent should now own menu item
|
||||
NS_RELEASE(supports);
|
||||
|
||||
NS_RELEASE(pnsMenuItem);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::GetItemCount(PRUint32 &aCount)
|
||||
{
|
||||
// this should be right.. does it need to be +1 ?
|
||||
aCount = g_list_length(GTK_MENU_SHELL(mMenu)->children);
|
||||
//g_print("nsMenu::GetItemCount = %i\n", aCount);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::GetItemAt(const PRUint32 aPos,
|
||||
nsISupports *&aMenuItem)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::InsertItemAt(const PRUint32 aPos,
|
||||
nsISupports *aMenuItem)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::RemoveItem(const PRUint32 aPos)
|
||||
{
|
||||
#if 0
|
||||
// this may work here better than Removeall(), but i'm not sure how to test this one
|
||||
nsISupports *item = mMenuItemVoidArray[aPos];
|
||||
delete item;
|
||||
mMenuItemVoidArray.RemoveElementAt(aPos);
|
||||
#endif
|
||||
/*
|
||||
gtk_menu_shell_remove (GTK_MENU_SHELL (mMenu), item);
|
||||
|
||||
nsCRT::free(labelStr);
|
||||
|
||||
voidData = NULL;
|
||||
|
||||
aMenu->GetNativeData(&voidData);
|
||||
newmenu = GTK_WIDGET(voidData);
|
||||
|
||||
gtk_menu_item_remove_submenu (GTK_MENU_ITEM (item));
|
||||
*/
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::RemoveAll()
|
||||
{
|
||||
//g_print("nsMenu::RemoveAll()\n");
|
||||
#if 0
|
||||
// this doesn't work quite right, but this is about all that should really be needed
|
||||
int i=0;
|
||||
nsIMenu *menu = nsnull;
|
||||
nsIMenuItem *menuitem = nsnull;
|
||||
nsISupports *item = nsnull;
|
||||
|
||||
for (i=mMenuItemVoidArray.Count(); i>0; i--)
|
||||
{
|
||||
item = (nsISupports*)mMenuItemVoidArray[i-1];
|
||||
|
||||
if(nsnull != item)
|
||||
{
|
||||
if (NS_OK == item->QueryInterface(nsIMenuItem::GetIID(), (void**)&menuitem)) {
|
||||
// we do this twice because we have to do it once for QueryInterface,
|
||||
// then we want to get rid of it.
|
||||
// g_print("remove nsMenuItem\n");
|
||||
NS_RELEASE(menuitem);
|
||||
NS_RELEASE(item);
|
||||
menuitem = nsnull;
|
||||
} else if (NS_OK == item->QueryInterface(nsIMenu::GetIID(), (void**)&menu)) {
|
||||
// g_print("remove nsMenu\n");
|
||||
NS_RELEASE(menu);
|
||||
NS_RELEASE(item);
|
||||
menu = nsnull;
|
||||
}
|
||||
// mMenuItemVoidArray.RemoveElementAt(i-1);
|
||||
}
|
||||
}
|
||||
mMenuItemVoidArray.Clear();
|
||||
#else
|
||||
for (int i = mMenuItemVoidArray.Count(); i > 0; i--) {
|
||||
if(nsnull != mMenuItemVoidArray[i-1]) {
|
||||
nsIMenuItem * menuitem = nsnull;
|
||||
((nsISupports*)mMenuItemVoidArray[i-1])->QueryInterface(nsIMenuItem::GetIID(),
|
||||
(void**)&menuitem);
|
||||
if(menuitem) {
|
||||
void *gtkmenuitem = nsnull;
|
||||
menuitem->GetNativeData(gtkmenuitem);
|
||||
if (gtkmenuitem) {
|
||||
// gtk_widget_ref(GTK_WIDGET(gtkmenuitem));
|
||||
//gtk_widget_destroy(GTK_WIDGET(gtkmenuitem));
|
||||
gtk_container_remove (GTK_CONTAINER (mMenu), GTK_WIDGET(gtkmenuitem));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
nsIMenu * menu= nsnull;
|
||||
((nsISupports*)mMenuItemVoidArray[i-1])->QueryInterface(nsIMenu::GetIID(),
|
||||
(void**)&menu);
|
||||
if(menu)
|
||||
{
|
||||
void * gtkmenu = nsnull;
|
||||
menu->GetNativeData(>kmenu);
|
||||
|
||||
if(gtkmenu){
|
||||
//g_print("gtkmenu removed");
|
||||
|
||||
//gtk_menu_item_remove_submenu (GTK_MENU_ITEM (item));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//g_print("end RemoveAll\n");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::GetNativeData(void ** aData)
|
||||
{
|
||||
*aData = (void *)mMenu;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::SetNativeData(void * aData)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
GtkWidget *nsMenu::GetNativeParent()
|
||||
{
|
||||
void * voidData;
|
||||
if (nsnull != mMenuParent) {
|
||||
mMenuParent->GetNativeData(&voidData);
|
||||
} else if (nsnull != mMenuBarParent) {
|
||||
mMenuBarParent->GetNativeData(voidData);
|
||||
} else {
|
||||
return nsnull;
|
||||
}
|
||||
return GTK_WIDGET(voidData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::AddMenuListener(nsIMenuListener * aMenuListener)
|
||||
{
|
||||
mListener = aMenuListener;
|
||||
NS_ADDREF(mListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::RemoveMenuListener(nsIMenuListener * aMenuListener)
|
||||
{
|
||||
if (aMenuListener == mListener) {
|
||||
NS_IF_RELEASE(mListener);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// nsIMenuListener interface
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenu::MenuItemSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
if (nsnull != mListener) {
|
||||
mListener->MenuSelected(aMenuEvent);
|
||||
}
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
nsEventStatus nsMenu::MenuSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
if (nsnull != mListener) {
|
||||
mListener->MenuSelected(aMenuEvent);
|
||||
}
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenu::MenuDeselected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
if (nsnull != mListener) {
|
||||
mListener->MenuDeselected(aMenuEvent);
|
||||
}
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenu::MenuConstruct(const nsMenuEvent & aMenuEvent,
|
||||
nsIWidget * aParentWindow,
|
||||
void * menuNode,
|
||||
void * aWebShell)
|
||||
{
|
||||
//g_print("nsMenu::MenuConstruct called \n");
|
||||
if(menuNode){
|
||||
SetDOMNode((nsIDOMNode*)menuNode);
|
||||
}
|
||||
|
||||
if(!aWebShell){
|
||||
aWebShell = mWebShell;
|
||||
}
|
||||
|
||||
// First open the menu.
|
||||
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
|
||||
if (domElement)
|
||||
domElement->SetAttribute("open", "true");
|
||||
|
||||
/// Now get the kids. Retrieve our menupopup child.
|
||||
nsCOMPtr<nsIDOMNode> menuPopupNode;
|
||||
mDOMNode->GetFirstChild(getter_AddRefs(menuPopupNode));
|
||||
while (menuPopupNode) {
|
||||
nsCOMPtr<nsIDOMElement> menuPopupElement(do_QueryInterface(menuPopupNode));
|
||||
if (menuPopupElement) {
|
||||
nsString menuPopupNodeType;
|
||||
menuPopupElement->GetNodeName(menuPopupNodeType);
|
||||
if (menuPopupNodeType.Equals("menupopup"))
|
||||
break;
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> oldMenuPopupNode(menuPopupNode);
|
||||
oldMenuPopupNode->GetNextSibling(getter_AddRefs(menuPopupNode));
|
||||
}
|
||||
|
||||
if (!menuPopupNode)
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> menuitemNode;
|
||||
menuPopupNode->GetFirstChild(getter_AddRefs(menuitemNode));
|
||||
|
||||
unsigned short menuIndex = 0;
|
||||
|
||||
while (menuitemNode) {
|
||||
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
|
||||
if (menuitemElement) {
|
||||
nsString menuitemNodeType;
|
||||
nsString menuitemName;
|
||||
menuitemElement->GetNodeName(menuitemNodeType);
|
||||
if (menuitemNodeType.Equals("menuitem")) {
|
||||
// LoadMenuItem
|
||||
LoadMenuItem(this,
|
||||
menuitemElement,
|
||||
menuitemNode,
|
||||
menuIndex,
|
||||
(nsIWebShell*)aWebShell);
|
||||
} else if (menuitemNodeType.Equals("menuseparator")) {
|
||||
AddSeparator();
|
||||
} else if (menuitemNodeType.Equals("menu")) {
|
||||
// Load a submenu
|
||||
LoadSubMenu(this, menuitemElement, menuitemNode);
|
||||
}
|
||||
}
|
||||
|
||||
++menuIndex;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
|
||||
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
|
||||
} // end menu item innner loop
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenu::MenuDestruct(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
// Close the node.
|
||||
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
|
||||
if (domElement)
|
||||
domElement->RemoveAttribute("open");
|
||||
|
||||
//g_print("nsMenu::MenuDestruct called \n");
|
||||
mConstructCalled = PR_FALSE;
|
||||
RemoveAll();
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/**
|
||||
* Set DOMNode
|
||||
*
|
||||
*/
|
||||
NS_METHOD nsMenu::SetDOMNode(nsIDOMNode * aMenuNode)
|
||||
{
|
||||
mDOMNode = aMenuNode;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/**
|
||||
* Set DOMElement
|
||||
*
|
||||
*/
|
||||
NS_METHOD nsMenu::SetDOMElement(nsIDOMElement * aMenuElement)
|
||||
{
|
||||
mDOMElement = aMenuElement;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/**
|
||||
* Set WebShell
|
||||
*
|
||||
*/
|
||||
NS_METHOD nsMenu::SetWebShell(nsIWebShell * aWebShell)
|
||||
{
|
||||
mWebShell = aWebShell;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
void nsMenu::LoadMenuItem(nsIMenu * pParentMenu,
|
||||
nsIDOMElement * menuitemElement,
|
||||
nsIDOMNode * menuitemNode,
|
||||
unsigned short menuitemIndex,
|
||||
nsIWebShell * aWebShell)
|
||||
{
|
||||
static const char* NS_STRING_TRUE = "true";
|
||||
nsString disabled;
|
||||
nsString menuitemName;
|
||||
nsString menuitemCmd;
|
||||
|
||||
menuitemElement->GetAttribute(nsAutoString("disabled"), disabled);
|
||||
menuitemElement->GetAttribute(nsAutoString("value"), menuitemName);
|
||||
menuitemElement->GetAttribute(nsAutoString("cmd"), menuitemCmd);
|
||||
|
||||
// Create nsMenuItem
|
||||
nsIMenuItem * pnsMenuItem = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(kMenuItemCID,
|
||||
nsnull,
|
||||
nsIMenuItem::GetIID(),
|
||||
(void**)&pnsMenuItem);
|
||||
if (NS_OK == rv) {
|
||||
pnsMenuItem->Create(pParentMenu, menuitemName, PR_FALSE);
|
||||
|
||||
nsISupports * supports = nsnull;
|
||||
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pParentMenu->AddItem(supports); // Parent should now own menu item
|
||||
NS_RELEASE(supports);
|
||||
|
||||
if(disabled == NS_STRING_TRUE ) {
|
||||
pnsMenuItem->SetEnabled(PR_FALSE);
|
||||
}
|
||||
|
||||
// Create MenuDelegate - this is the intermediator inbetween
|
||||
// the DOM node and the nsIMenuItem
|
||||
// The nsWebShellWindow wacthes for Document changes and then notifies the
|
||||
// the appropriate nsMenuDelegate object
|
||||
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(menuitemNode));
|
||||
if (!domElement) {
|
||||
//return NS_ERROR_FAILURE;
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString cmdAtom("oncommand");
|
||||
nsString cmdName;
|
||||
|
||||
domElement->GetAttribute(cmdAtom, cmdName);
|
||||
|
||||
pnsMenuItem->SetCommand(cmdName);
|
||||
// DO NOT use passed in webshell because of messed up windows dynamic loading
|
||||
// code.
|
||||
pnsMenuItem->SetWebShell(mWebShell);
|
||||
pnsMenuItem->SetDOMElement(domElement);
|
||||
|
||||
NS_RELEASE(pnsMenuItem);
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
void nsMenu::LoadSubMenu(nsIMenu * pParentMenu,
|
||||
nsIDOMElement * menuElement,
|
||||
nsIDOMNode * menuNode)
|
||||
{
|
||||
nsString menuName;
|
||||
menuElement->GetAttribute(nsAutoString("value"), menuName);
|
||||
//printf("Creating Menu [%s] \n", menuName.ToNewCString()); // this leaks
|
||||
|
||||
// Create nsMenu
|
||||
nsIMenu * pnsMenu = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(kMenuCID,
|
||||
nsnull,
|
||||
nsIMenu::GetIID(),
|
||||
(void**)&pnsMenu);
|
||||
if (NS_OK == rv) {
|
||||
// Call Create
|
||||
nsISupports * supports = nsnull;
|
||||
pParentMenu->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pnsMenu->Create(supports, menuName);
|
||||
NS_RELEASE(supports); // Balance QI
|
||||
|
||||
// Set nsMenu Name
|
||||
pnsMenu->SetLabel(menuName);
|
||||
|
||||
supports = nsnull;
|
||||
pnsMenu->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pParentMenu->AddItem(supports); // parent takes ownership
|
||||
NS_RELEASE(supports);
|
||||
|
||||
pnsMenu->SetWebShell(mWebShell);
|
||||
pnsMenu->SetDOMNode(menuNode);
|
||||
|
||||
/*
|
||||
// Begin menuitem inner loop
|
||||
unsigned short menuIndex = 0;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> menuitemNode;
|
||||
menuNode->GetFirstChild(getter_AddRefs(menuitemNode));
|
||||
while (menuitemNode) {
|
||||
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
|
||||
if (menuitemElement) {
|
||||
nsString menuitemNodeType;
|
||||
menuitemElement->GetNodeName(menuitemNodeType);
|
||||
|
||||
#ifdef DEBUG_saari
|
||||
printf("Type [%s] %d\n", menuitemNodeType.ToNewCString(), menuitemNodeType.Equals("menuseparator"));
|
||||
#endif
|
||||
|
||||
if (menuitemNodeType.Equals("menuitem")) {
|
||||
// Load a menuitem
|
||||
LoadMenuItem(pnsMenu, menuitemElement, menuitemNode, menuIndex, mWebShell);
|
||||
} else if (menuitemNodeType.Equals("menuseparator")) {
|
||||
pnsMenu->AddSeparator();
|
||||
} else if (menuitemNodeType.Equals("menu")) {
|
||||
// Add a submenu
|
||||
LoadSubMenu(pnsMenu, menuitemElement, menuitemNode);
|
||||
}
|
||||
}
|
||||
++menuIndex;
|
||||
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
|
||||
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
|
||||
} // end menu item innner loop
|
||||
*/
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef nsMenu_h__
|
||||
#define nsMenu_h__
|
||||
|
||||
#include "nsIMenu.h"
|
||||
#include "nsIMenuListener.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
class nsIDOMElement;
|
||||
class nsIDOMNode;
|
||||
class nsIMenuBar;
|
||||
class nsIWebShell;
|
||||
|
||||
/**
|
||||
* Native GTK+ Menu wrapper
|
||||
*/
|
||||
|
||||
class nsMenu : public nsIMenu, public nsIMenuListener
|
||||
{
|
||||
|
||||
public:
|
||||
nsMenu();
|
||||
virtual ~nsMenu();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIMenuListener methods
|
||||
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuConstruct(
|
||||
const nsMenuEvent & aMenuEvent,
|
||||
nsIWidget * aParentWindow,
|
||||
void * menuNode,
|
||||
void * aWebShell);
|
||||
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
|
||||
|
||||
NS_IMETHOD Create(nsISupports * aParent, const nsString &aLabel);
|
||||
|
||||
// nsIMenu Methods
|
||||
NS_IMETHOD GetParent(nsISupports *&aParent);
|
||||
NS_IMETHOD GetLabel(nsString &aText);
|
||||
NS_IMETHOD SetLabel(const nsString &aText);
|
||||
NS_IMETHOD GetAccessKey(nsString &aText);
|
||||
NS_IMETHOD SetAccessKey(const nsString &aText);
|
||||
NS_IMETHOD AddItem(nsISupports * aItem);
|
||||
NS_IMETHOD AddMenuItem(nsIMenuItem * aMenuItem);
|
||||
NS_IMETHOD AddMenu(nsIMenu * aMenu);
|
||||
NS_IMETHOD AddSeparator();
|
||||
NS_IMETHOD GetItemCount(PRUint32 &aCount);
|
||||
NS_IMETHOD GetItemAt(const PRUint32 aPos, nsISupports *& aMenuItem);
|
||||
NS_IMETHOD InsertItemAt(const PRUint32 aPos, nsISupports * aMenuItem);
|
||||
NS_IMETHOD RemoveItem(const PRUint32 aPos);
|
||||
NS_IMETHOD RemoveAll();
|
||||
NS_IMETHOD GetNativeData(void** aData);
|
||||
NS_IMETHOD SetNativeData(void* aData);
|
||||
NS_IMETHOD AddMenuListener(nsIMenuListener * aMenuListener);
|
||||
NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener);
|
||||
NS_IMETHOD SetEnabled(PRBool aIsEnabled);
|
||||
NS_IMETHOD GetEnabled(PRBool* aIsEnabled);
|
||||
NS_IMETHOD IsHelpMenu(PRBool* aIsHelp);
|
||||
|
||||
NS_IMETHOD SetDOMNode(nsIDOMNode * aMenuNode);
|
||||
NS_IMETHOD SetDOMElement(nsIDOMElement * aMenuElement);
|
||||
NS_IMETHOD SetWebShell(nsIWebShell * aWebShell);
|
||||
|
||||
protected:
|
||||
void LoadMenuItem(
|
||||
nsIMenu * pParentMenu,
|
||||
nsIDOMElement * menuitemElement,
|
||||
nsIDOMNode * menuitemNode,
|
||||
unsigned short menuitemIndex,
|
||||
nsIWebShell * aWebShell);
|
||||
|
||||
void LoadSubMenu(
|
||||
nsIMenu * pParentMenu,
|
||||
nsIDOMElement * menuElement,
|
||||
nsIDOMNode * menuNode);
|
||||
|
||||
GtkWidget *GetNativeParent();
|
||||
|
||||
nsString mLabel;
|
||||
nsString mAccessKey;
|
||||
PRUint32 mNumMenuItems;
|
||||
GtkWidget *mMenu;
|
||||
|
||||
nsVoidArray mMenuItemVoidArray;
|
||||
|
||||
nsIMenu *mMenuParent;
|
||||
nsIMenuBar *mMenuBarParent;
|
||||
nsIMenuListener * mListener;
|
||||
|
||||
PRBool mConstructCalled;
|
||||
nsIDOMNode * mDOMNode;
|
||||
nsIWebShell * mWebShell;
|
||||
nsIDOMElement * mDOMElement;
|
||||
};
|
||||
|
||||
#endif // nsMenu_h__
|
||||
@@ -1,354 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "nsMenuBar.h"
|
||||
#include "nsMenuItem.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIMenu.h"
|
||||
#include "nsIWebShell.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
#include "nsGtkEventHandler.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
|
||||
static NS_DEFINE_CID(kMenuBarCID, NS_MENUBAR_CID);
|
||||
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
|
||||
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
|
||||
nsresult nsMenuBar::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
*aInstancePtr = NULL;
|
||||
|
||||
if (aIID.Equals(nsIMenuBar::GetIID())) {
|
||||
*aInstancePtr = (void*) ((nsIMenuBar*) this);
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aIID.Equals(kISupportsIID)) {
|
||||
*aInstancePtr = (void*) ((nsISupports*)(nsIMenuBar*) this);
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aIID.Equals(nsIMenuListener::GetIID())) {
|
||||
*aInstancePtr = (void*) ((nsIMenuListener*)this);
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(nsMenuBar)
|
||||
NS_IMPL_RELEASE(nsMenuBar)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsMenuBar constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsMenuBar::nsMenuBar() : nsIMenuBar(), nsIMenuListener()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mNumMenus = 0;
|
||||
mMenuBar = nsnull;
|
||||
mParent = nsnull;
|
||||
mIsMenuBarAdded = PR_FALSE;
|
||||
mWebShell = nsnull;
|
||||
mDOMNode = nsnull;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsMenuBar destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsMenuBar::~nsMenuBar()
|
||||
{
|
||||
// Release the menus
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the proper widget
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::Create(nsIWidget *aParent)
|
||||
{
|
||||
SetParent(aParent);
|
||||
mMenuBar = gtk_menu_bar_new();
|
||||
|
||||
gtk_widget_show(mMenuBar);
|
||||
mParent->SetMenuBar(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::GetParent(nsIWidget *&aParent)
|
||||
{
|
||||
aParent = mParent;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::SetParent(nsIWidget *aParent)
|
||||
{
|
||||
mParent = aParent;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::AddMenu(nsIMenu * aMenu)
|
||||
{
|
||||
nsString Label;
|
||||
GtkWidget *widget, *nmenu;
|
||||
void *voidData;
|
||||
|
||||
nsISupports * supports = nsnull;
|
||||
aMenu->QueryInterface(kISupportsIID, (void**)&supports);
|
||||
if (supports) {
|
||||
mMenusVoidArray.AppendElement(aMenu);
|
||||
mNumMenus++;
|
||||
}
|
||||
|
||||
aMenu->GetLabel(Label);
|
||||
|
||||
// get access key
|
||||
nsString accessKey = " ";
|
||||
aMenu->GetAccessKey(accessKey);
|
||||
if(accessKey != " ")
|
||||
{
|
||||
// munge acess key into name
|
||||
PRInt32 offset = Label.Find(accessKey);
|
||||
if(offset != -1)
|
||||
Label.Insert("_", offset);
|
||||
}
|
||||
|
||||
char *foo = Label.ToNewCString();
|
||||
g_print("%s\n", foo);
|
||||
nsCRT::free(foo);
|
||||
|
||||
widget = nsMenuItem::CreateLocalized(Label);
|
||||
gtk_widget_show(widget);
|
||||
gtk_menu_bar_append (GTK_MENU_BAR (mMenuBar), widget);
|
||||
|
||||
aMenu->GetNativeData(&voidData);
|
||||
nmenu = GTK_WIDGET(voidData);
|
||||
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), nmenu);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::GetMenuCount(PRUint32 &aCount)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::GetMenuAt(const PRUint32 aCount, nsIMenu *& aMenu)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::InsertMenuAt(const PRUint32 aCount, nsIMenu *& aMenu)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::RemoveMenu(const PRUint32 aCount)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::RemoveAll()
|
||||
{
|
||||
for (int i = mMenusVoidArray.Count(); i > 0; i--) {
|
||||
if(nsnull != mMenusVoidArray[i-1]) {
|
||||
nsIMenu * menu = nsnull;
|
||||
((nsISupports*)mMenusVoidArray[i-1])->QueryInterface(nsIMenu::GetIID(), (void**)&menu);
|
||||
if(menu) {
|
||||
//void * gtkmenu= nsnull;
|
||||
//menu->GetNativeData(>kmenu);
|
||||
//if(gtkmenu){
|
||||
// gtk_container_remove (GTK_CONTAINER (mMenuBar), GTK_WIDGET(gtkmenu) );
|
||||
//}
|
||||
NS_RELEASE(menu);
|
||||
|
||||
g_print("menu release \n");
|
||||
int num =((nsISupports*)mMenusVoidArray[i-1])->Release();
|
||||
while(num) {
|
||||
g_print("menu release again!\n");
|
||||
num = ((nsISupports*)mMenusVoidArray[i-1])->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::GetNativeData(void *& aData)
|
||||
{
|
||||
aData = (void *)mMenuBar;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::SetNativeData(void * aData)
|
||||
{
|
||||
// Temporary hack for MacOS. Will go away when nsMenuBar handles it's own
|
||||
// construction
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::Paint()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsMenuListener interface
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenuBar::MenuItemSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
nsEventStatus nsMenuBar::MenuSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
nsEventStatus nsMenuBar::MenuDeselected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
nsEventStatus nsMenuBar::MenuConstruct(
|
||||
const nsMenuEvent & aMenuEvent,
|
||||
nsIWidget * aParentWindow,
|
||||
void * menubarNode,
|
||||
void * aWebShell)
|
||||
{
|
||||
mWebShell = (nsIWebShell*) aWebShell;
|
||||
mDOMNode = (nsIDOMNode*)menubarNode;
|
||||
|
||||
nsIMenuBar * pnsMenuBar = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(kMenuBarCID,
|
||||
nsnull,
|
||||
nsIMenuBar::GetIID(),
|
||||
(void**)&pnsMenuBar);
|
||||
if (NS_OK == rv) {
|
||||
if (nsnull != pnsMenuBar) {
|
||||
pnsMenuBar->Create(aParentWindow);
|
||||
|
||||
// set pnsMenuBar as a nsMenuListener on aParentWindow
|
||||
nsCOMPtr<nsIMenuListener> menuListener;
|
||||
pnsMenuBar->QueryInterface(nsIMenuListener::GetIID(), getter_AddRefs(menuListener));
|
||||
aParentWindow->AddMenuListener(menuListener);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> menuNode;
|
||||
((nsIDOMNode*)menubarNode)->GetFirstChild(getter_AddRefs(menuNode));
|
||||
while (menuNode) {
|
||||
nsCOMPtr<nsIDOMElement> menuElement(do_QueryInterface(menuNode));
|
||||
if (menuElement) {
|
||||
nsString menuNodeType;
|
||||
nsString menuName;
|
||||
nsString menuAccessKey = " ";
|
||||
menuElement->GetNodeName(menuNodeType);
|
||||
if (menuNodeType.Equals("menu")) {
|
||||
menuElement->GetAttribute(nsAutoString("value"), menuName);
|
||||
menuElement->GetAttribute(nsAutoString("accesskey"), menuAccessKey);
|
||||
// Don't create the menu yet, just add in the top level names
|
||||
|
||||
// Create nsMenu
|
||||
nsIMenu * pnsMenu = nsnull;
|
||||
rv = nsComponentManager::CreateInstance(kMenuCID, nsnull, nsIMenu::GetIID(), (void**)&pnsMenu);
|
||||
if (NS_OK == rv) {
|
||||
// Call Create
|
||||
nsISupports * supports = nsnull;
|
||||
pnsMenuBar->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pnsMenu->Create(supports, menuName);
|
||||
NS_RELEASE(supports);
|
||||
|
||||
pnsMenu->SetLabel(menuName);
|
||||
pnsMenu->SetAccessKey(menuAccessKey);
|
||||
pnsMenu->SetDOMNode(menuNode);
|
||||
pnsMenu->SetDOMElement(menuElement);
|
||||
pnsMenu->SetWebShell(mWebShell);
|
||||
|
||||
// Make nsMenu a child of nsMenuBar
|
||||
// nsMenuBar takes ownership of the nsMenu
|
||||
pnsMenuBar->AddMenu(pnsMenu);
|
||||
|
||||
// Release the menu now that the menubar owns it
|
||||
NS_RELEASE(pnsMenu);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> oldmenuNode(menuNode);
|
||||
oldmenuNode->GetNextSibling(getter_AddRefs(menuNode));
|
||||
} // end while (nsnull != menuNode)
|
||||
|
||||
// Give the aParentWindow this nsMenuBar to hold onto.
|
||||
// The parent window should take ownership at this point
|
||||
aParentWindow->SetMenuBar(pnsMenuBar);
|
||||
|
||||
// HACK: force a paint for now
|
||||
pnsMenuBar->Paint();
|
||||
|
||||
NS_RELEASE(pnsMenuBar);
|
||||
} // end if ( nsnull != pnsMenuBar )
|
||||
}
|
||||
|
||||
return nsEventStatus_eIgnore;
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
nsEventStatus nsMenuBar::MenuDestruct(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef nsMenuBar_h__
|
||||
#define nsMenuBar_h__
|
||||
|
||||
#include "nsIMenuBar.h"
|
||||
#include "nsIMenuListener.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
class nsIDOMNode;
|
||||
class nsIWebShell;
|
||||
class nsIWidget;
|
||||
|
||||
/**
|
||||
* Native GTK+ MenuBar wrapper
|
||||
*/
|
||||
|
||||
class nsMenuBar : public nsIMenuBar, public nsIMenuListener
|
||||
{
|
||||
|
||||
public:
|
||||
nsMenuBar();
|
||||
virtual ~nsMenuBar();
|
||||
|
||||
// nsIMenuListener interface
|
||||
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuConstruct(
|
||||
const nsMenuEvent & aMenuEvent,
|
||||
nsIWidget * aParentWindow,
|
||||
void * menuNode,
|
||||
void * aWebShell);
|
||||
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
|
||||
NS_IMETHOD Create(nsIWidget * aParent);
|
||||
|
||||
// nsIMenuBar Methods
|
||||
NS_IMETHOD GetParent(nsIWidget *&aParent);
|
||||
NS_IMETHOD SetParent(nsIWidget * aParent);
|
||||
NS_IMETHOD AddMenu(nsIMenu * aMenu);
|
||||
NS_IMETHOD GetMenuCount(PRUint32 &aCount);
|
||||
NS_IMETHOD GetMenuAt(const PRUint32 aCount, nsIMenu *& aMenu);
|
||||
NS_IMETHOD InsertMenuAt(const PRUint32 aCount, nsIMenu *& aMenu);
|
||||
NS_IMETHOD RemoveMenu(const PRUint32 aCount);
|
||||
NS_IMETHOD RemoveAll();
|
||||
NS_IMETHOD GetNativeData(void*& aData);
|
||||
NS_IMETHOD Paint();
|
||||
NS_IMETHOD SetNativeData(void* aData);
|
||||
protected:
|
||||
GtkWidget * mMenuBar;
|
||||
nsIWidget * mParent;
|
||||
PRBool mIsMenuBarAdded;
|
||||
|
||||
nsIWebShell * mWebShell;
|
||||
nsIDOMNode * mDOMNode;
|
||||
|
||||
nsVoidArray mMenusVoidArray;
|
||||
PRUint32 mNumMenus;
|
||||
};
|
||||
|
||||
#endif // nsMenuBar_h__
|
||||
@@ -1,539 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "nsMenuItem.h"
|
||||
#include "nsIMenu.h"
|
||||
#include "nsIMenuBar.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
#include "nsGtkEventHandler.h"
|
||||
|
||||
#include "nsIPopUpMenu.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDocumentViewer.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsIWebShell.h"
|
||||
#include "nsICharsetConverterManager.h"
|
||||
#include "nsIPlatformCharset.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
|
||||
nsresult nsMenuItem::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
*aInstancePtr = NULL;
|
||||
|
||||
if (aIID.Equals(nsIMenuItem::GetIID())) {
|
||||
*aInstancePtr = (void*)(nsIMenuItem*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kISupportsIID)) {
|
||||
*aInstancePtr = (void*)(nsISupports*)(nsIMenuItem*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(nsIMenuListener::GetIID())) {
|
||||
*aInstancePtr = (void*)(nsIMenuListener*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(nsMenuItem)
|
||||
NS_IMPL_RELEASE(nsMenuItem)
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsMenuItem constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsMenuItem::nsMenuItem() : nsIMenuItem()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mMenuItem = nsnull;
|
||||
mMenuParent = nsnull;
|
||||
mPopUpParent = nsnull;
|
||||
mTarget = nsnull;
|
||||
mXULCommandListener = nsnull;
|
||||
mIsSeparator = PR_FALSE;
|
||||
mWebShell = nsnull;
|
||||
mDOMElement = nsnull;
|
||||
mIsSubMenu = PR_FALSE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsMenuItem destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsMenuItem::~nsMenuItem()
|
||||
{
|
||||
//g_print("nsMenuItem::~nsMenuItem called\n");
|
||||
//NS_IF_RELEASE(mTarget);
|
||||
gtk_widget_destroy(mMenuItem);
|
||||
mMenuItem = nsnull;
|
||||
//g_print("end nsMenuItem::~nsMenuItem\n");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
GtkWidget *nsMenuItem::GetNativeParent()
|
||||
{
|
||||
void * voidData;
|
||||
if (nsnull != mMenuParent) {
|
||||
mMenuParent->GetNativeData(&voidData);
|
||||
} else if (nsnull != mPopUpParent) {
|
||||
mPopUpParent->GetNativeData(voidData);
|
||||
} else {
|
||||
return nsnull;
|
||||
}
|
||||
return GTK_WIDGET(voidData);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsIWidget * nsMenuItem::GetMenuBarParent(nsISupports * aParent)
|
||||
{
|
||||
nsIWidget * widget = nsnull; // MenuBar's Parent
|
||||
nsIMenu * menu = nsnull;
|
||||
nsIMenuBar * menuBar = nsnull;
|
||||
nsIPopUpMenu * popup = nsnull;
|
||||
nsISupports * parent = aParent;
|
||||
|
||||
while(1) {
|
||||
if (NS_OK == parent->QueryInterface(nsIMenu::GetIID(),(void**)&menu)) {
|
||||
NS_RELEASE(parent);
|
||||
if (NS_OK != menu->GetParent(parent)) {
|
||||
NS_RELEASE(menu);
|
||||
return nsnull;
|
||||
}
|
||||
NS_RELEASE(menu);
|
||||
|
||||
} else if (NS_OK == parent->QueryInterface(nsIPopUpMenu::GetIID(),(void**)&popup)) {
|
||||
if (NS_OK != popup->GetParent(widget)) {
|
||||
widget = nsnull;
|
||||
}
|
||||
NS_RELEASE(popup);
|
||||
NS_RELEASE(parent);
|
||||
return widget;
|
||||
|
||||
} else if (NS_OK == parent->QueryInterface(nsIMenuBar::GetIID(),(void**)&menuBar)) {
|
||||
if (NS_OK != menuBar->GetParent(widget)) {
|
||||
widget = nsnull;
|
||||
}
|
||||
NS_RELEASE(menuBar);
|
||||
NS_RELEASE(parent);
|
||||
return widget;
|
||||
} else {
|
||||
NS_RELEASE(parent);
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
nsMenuItem::CreateLocalized(const nsString& aLabel)
|
||||
{
|
||||
nsresult result;
|
||||
static nsIUnicodeEncoder* converter = nsnull;
|
||||
static int isLatin1 = 0;
|
||||
static int initialized = 0;
|
||||
if (!initialized) {
|
||||
initialized = 1;
|
||||
result = NS_ERROR_FAILURE;
|
||||
NS_WITH_SERVICE(nsIPlatformCharset, platform, NS_PLATFORMCHARSET_PROGID,
|
||||
&result);
|
||||
if (platform && NS_SUCCEEDED(result)) {
|
||||
nsAutoString charset("");
|
||||
result = platform->GetCharset(kPlatformCharsetSel_Menu, charset);
|
||||
if (NS_SUCCEEDED(result) && (charset.Length() > 0)) {
|
||||
if (!charset.Compare("iso-8859-1", PR_TRUE)) {
|
||||
isLatin1 = 1;
|
||||
}
|
||||
NS_WITH_SERVICE(nsICharsetConverterManager, manager,
|
||||
NS_CHARSETCONVERTERMANAGER_PROGID, &result);
|
||||
if (manager && NS_SUCCEEDED(result)) {
|
||||
result = manager->GetUnicodeEncoder(&charset, &converter);
|
||||
if (NS_FAILED(result) && converter) {
|
||||
NS_RELEASE(converter);
|
||||
converter = nsnull;
|
||||
}
|
||||
else if (converter) {
|
||||
result = converter->SetOutputErrorBehavior(
|
||||
nsIUnicodeEncoder::kOnError_Replace, nsnull, '?');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget* menuItem = nsnull;
|
||||
|
||||
if (converter) {
|
||||
char labelStr[128];
|
||||
labelStr[0] = 0;
|
||||
PRInt32 srcLen = aLabel.Length() + 1;
|
||||
PRInt32 destLen = sizeof(labelStr);
|
||||
result = converter->Convert(aLabel.GetUnicode(), &srcLen, labelStr,
|
||||
&destLen);
|
||||
if (labelStr[0] && NS_SUCCEEDED(result)) {
|
||||
menuItem = gtk_menu_item_new_with_label(labelStr);
|
||||
if (menuItem && (!isLatin1)) {
|
||||
GtkWidget* label = GTK_BIN(menuItem)->child;
|
||||
gtk_widget_ensure_style(label);
|
||||
GtkStyle* style = gtk_style_copy(label->style);
|
||||
gdk_font_unref(style->font);
|
||||
style->font = gdk_fontset_load("*");
|
||||
gtk_widget_set_style(label, style);
|
||||
gtk_style_unref(style);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
char labelStr[128];
|
||||
aLabel.ToCString(labelStr, sizeof(labelStr));
|
||||
menuItem = gtk_menu_item_new_with_label(labelStr);
|
||||
}
|
||||
|
||||
return menuItem;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::Create(nsISupports *aParent,
|
||||
const nsString &aLabel,
|
||||
PRBool aIsSeparator)
|
||||
|
||||
{
|
||||
if (nsnull == aParent) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if(aParent) {
|
||||
nsIMenu * menu;
|
||||
aParent->QueryInterface(nsIMenu::GetIID(), (void**) &menu);
|
||||
mMenuParent = menu;
|
||||
NS_RELEASE(menu);
|
||||
}
|
||||
|
||||
nsIWidget *widget = nsnull; // MenuBar's Parent
|
||||
nsISupports *sups;
|
||||
if (NS_OK == aParent->QueryInterface(kISupportsIID,(void**)&sups)) {
|
||||
widget = GetMenuBarParent(sups);
|
||||
// GetMenuBarParent will call release for us
|
||||
// NS_RELEASE(sups);
|
||||
mTarget = widget;
|
||||
}
|
||||
|
||||
mIsSeparator = aIsSeparator;
|
||||
mLabel = aLabel;
|
||||
|
||||
// create the native menu item
|
||||
|
||||
if(mIsSeparator) {
|
||||
mMenuItem = gtk_menu_item_new();
|
||||
} else {
|
||||
mMenuItem = CreateLocalized(aLabel);
|
||||
}
|
||||
|
||||
gtk_widget_show(mMenuItem);
|
||||
|
||||
gtk_signal_connect(GTK_OBJECT(mMenuItem), "activate",
|
||||
GTK_SIGNAL_FUNC(menu_item_activate_handler),
|
||||
this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetLabel(nsString &aText)
|
||||
{
|
||||
aText = mLabel;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::SetLabel(nsString &aText)
|
||||
{
|
||||
mLabel = aText;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::SetEnabled(PRBool aIsEnabled)
|
||||
{
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(mMenuItem), aIsEnabled);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetEnabled(PRBool *aIsEnabled)
|
||||
{
|
||||
*aIsEnabled = GTK_WIDGET_IS_SENSITIVE(mMenuItem);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::SetChecked(PRBool aIsEnabled)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetChecked(PRBool *aIsEnabled)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::SetCheckboxType(PRBool aIsCheckbox)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetCheckboxType(PRBool *aIsCheckbox)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetCommand(PRUint32 & aCommand)
|
||||
{
|
||||
aCommand = mCommand;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetTarget(nsIWidget *& aTarget)
|
||||
{
|
||||
aTarget = mTarget;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetNativeData(void *& aData)
|
||||
{
|
||||
aData = (void *)mMenuItem;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::AddMenuListener(nsIMenuListener * aMenuListener)
|
||||
{
|
||||
|
||||
NS_IF_RELEASE(mXULCommandListener);
|
||||
NS_IF_ADDREF(aMenuListener);
|
||||
mXULCommandListener = aMenuListener;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::RemoveMenuListener(nsIMenuListener * aMenuListener)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::IsSeparator(PRBool & aIsSep)
|
||||
{
|
||||
aIsSep = mIsSeparator;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// nsIMenuListener interface
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenuItem::MenuItemSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
if(!mIsSeparator) {
|
||||
//g_print("nsMenuItem::MenuItemSelected\n");
|
||||
DoCommand();
|
||||
}else{
|
||||
//g_print("nsMenuItem::MenuItemSelected is separator\n");
|
||||
}
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenuItem::MenuSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
if(mXULCommandListener)
|
||||
return mXULCommandListener->MenuSelected(aMenuEvent);
|
||||
|
||||
//g_print("nsMenuItem::MenuSelected\n");
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenuItem::MenuDeselected(const nsMenuEvent &aMenuEvent)
|
||||
{
|
||||
//g_print("nsMenuItem::MenuDeselected\n");
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenuItem::MenuConstruct(const nsMenuEvent &aMenuEvent,
|
||||
nsIWidget *aParentWindow,
|
||||
void *menuNode,
|
||||
void *aWebShell)
|
||||
{
|
||||
//g_print("nsMenuItem::MenuConstruct\n");
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenuItem::MenuDestruct(const nsMenuEvent &aMenuEvent)
|
||||
{
|
||||
//g_print("nsMenuItem::MenuDestruct\n");
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/**
|
||||
* Sets the JavaScript Command to be invoked when a "gui" event
|
||||
* occurs on a source widget
|
||||
* @param aStrCmd the JS command to be cached for later execution
|
||||
* @return NS_OK
|
||||
*/
|
||||
NS_METHOD nsMenuItem::SetCommand(const nsString &aStrCmd)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/**
|
||||
* Executes the "cached" JavaScript Command
|
||||
* @return NS_OK if the command was executed properly, otherwise an error code
|
||||
*/
|
||||
NS_METHOD nsMenuItem::DoCommand()
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
if(!mWebShell || !mDOMElement)
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIContentViewer> contentViewer;
|
||||
NS_ENSURE_SUCCESS(mWebShell->GetContentViewer(getter_AddRefs(contentViewer)),
|
||||
NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDocumentViewer> docViewer;
|
||||
docViewer = do_QueryInterface(contentViewer);
|
||||
if (!docViewer) {
|
||||
NS_ERROR("Document viewer interface not supported by the content viewer.");
|
||||
//g_print("Document viewer interface not supported by the content viewer.");
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPresContext> presContext;
|
||||
if (NS_FAILED(rv = docViewer->GetPresContext(*getter_AddRefs(presContext)))) {
|
||||
NS_ERROR("Unable to retrieve the doc viewer's presentation context.");
|
||||
//g_print("Unable to retrieve the doc viewer's presentation context.");
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsMouseEvent event;
|
||||
event.eventStructType = NS_MOUSE_EVENT;
|
||||
event.message = NS_MENU_ACTION;
|
||||
|
||||
nsCOMPtr<nsIContent> contentNode;
|
||||
contentNode = do_QueryInterface(mDOMElement);
|
||||
if (!contentNode) {
|
||||
NS_ERROR("DOM Node doesn't support the nsIContent interface required to handle DOM events.");
|
||||
//g_print("DOM Node doesn't support the nsIContent interface required to handle DOM events.");
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = contentNode->HandleDOMEvent(*presContext, &event, nsnull, NS_EVENT_FLAG_INIT, status);
|
||||
//g_print("HandleDOMEvent called");
|
||||
return rv;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::SetDOMNode(nsIDOMNode * aDOMNode)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetDOMNode(nsIDOMNode ** aDOMNode)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::SetDOMElement(nsIDOMElement * aDOMElement)
|
||||
{
|
||||
mDOMElement = aDOMElement;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetDOMElement(nsIDOMElement ** aDOMElement)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::SetWebShell(nsIWebShell * aWebShell)
|
||||
{
|
||||
mWebShell = aWebShell;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsMenuItem::SetShortcutChar(const nsString &aText)
|
||||
{
|
||||
mKeyEquivalent = aText;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsMenuItem::GetShortcutChar(nsString &aText)
|
||||
{
|
||||
aText = mKeyEquivalent;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsMenuItem::SetModifiers(PRUint8 aModifiers)
|
||||
{
|
||||
mModifiers = aModifiers;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsMenuItem::GetModifiers(PRUint8 * aModifiers)
|
||||
{
|
||||
*aModifiers = mModifiers;
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef nsMenuItem_h__
|
||||
#define nsMenuItem_h__
|
||||
|
||||
#include "nsIMenuItem.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIMenuListener.h"
|
||||
|
||||
class nsIDOMNode;
|
||||
class nsIDOMElement;
|
||||
class nsIMenu;
|
||||
class nsIPopUpMenu;
|
||||
class nsIWebShell;
|
||||
class nsIWidget;
|
||||
|
||||
/**
|
||||
* Native GTK+ MenuItem wrapper
|
||||
*/
|
||||
|
||||
class nsMenuItem : public nsIMenuItem, public nsIMenuListener
|
||||
{
|
||||
|
||||
public:
|
||||
nsMenuItem();
|
||||
virtual ~nsMenuItem();
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIMenuItem Methods
|
||||
NS_IMETHOD Create(nsISupports *aParent,
|
||||
const nsString &aLabel,
|
||||
PRBool aIsSeparator);
|
||||
NS_IMETHOD GetLabel(nsString &aText);
|
||||
NS_IMETHOD SetLabel(nsString &aText);
|
||||
NS_IMETHOD SetEnabled(PRBool aIsEnabled);
|
||||
NS_IMETHOD GetEnabled(PRBool *aIsEnabled);
|
||||
NS_IMETHOD SetChecked(PRBool aIsEnabled);
|
||||
NS_IMETHOD GetChecked(PRBool *aIsEnabled);
|
||||
NS_IMETHOD SetCheckboxType(PRBool aIsCheckbox);
|
||||
NS_IMETHOD GetCheckboxType(PRBool *aIsCheckbox);
|
||||
NS_IMETHOD GetCommand(PRUint32 & aCommand);
|
||||
NS_IMETHOD GetTarget(nsIWidget *& aTarget);
|
||||
NS_IMETHOD GetNativeData(void*& aData);
|
||||
NS_IMETHOD AddMenuListener(nsIMenuListener * aMenuListener);
|
||||
NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener);
|
||||
NS_IMETHOD IsSeparator(PRBool & aIsSep);
|
||||
|
||||
NS_IMETHOD SetCommand(const nsString & aStrCmd);
|
||||
NS_IMETHOD DoCommand();
|
||||
NS_IMETHOD SetDOMNode(nsIDOMNode * aDOMNode);
|
||||
NS_IMETHOD GetDOMNode(nsIDOMNode ** aDOMNode);
|
||||
NS_IMETHOD SetDOMElement(nsIDOMElement * aDOMElement);
|
||||
NS_IMETHOD GetDOMElement(nsIDOMElement ** aDOMElement);
|
||||
NS_IMETHOD SetWebShell(nsIWebShell * aWebShell);
|
||||
|
||||
NS_IMETHOD SetShortcutChar(const nsString &aText);
|
||||
NS_IMETHOD GetShortcutChar(nsString &aText);
|
||||
NS_IMETHOD SetModifiers(PRUint8 aModifiers);
|
||||
NS_IMETHOD GetModifiers(PRUint8 * aModifiers);
|
||||
|
||||
// nsIMenuListener interface
|
||||
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuConstruct(const nsMenuEvent & aMenuEvent,
|
||||
nsIWidget * aParentWindow,
|
||||
void * menuNode,
|
||||
void * aWebShell);
|
||||
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
|
||||
|
||||
static GtkWidget* CreateLocalized(const nsString& aLabel);
|
||||
|
||||
protected:
|
||||
nsIWidget *GetMenuBarParent(nsISupports * aParentSupports);
|
||||
GtkWidget *GetNativeParent();
|
||||
|
||||
nsIMenuListener *mXULCommandListener;
|
||||
nsString mLabel;
|
||||
nsString mKeyEquivalent;
|
||||
PRUint8 mModifiers;
|
||||
PRUint32 mCommand;
|
||||
nsIMenu *mMenuParent;
|
||||
nsIPopUpMenu *mPopUpParent;
|
||||
nsIWidget *mTarget;
|
||||
|
||||
GtkWidget *mMenuItem; // native cascade widget
|
||||
PRBool mIsSeparator;
|
||||
PRBool mIsSubMenu;
|
||||
|
||||
nsIWebShell * mWebShell;
|
||||
nsIDOMElement * mDOMElement;
|
||||
};
|
||||
|
||||
#endif // nsMenuItem_h__
|
||||
@@ -1,214 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
#include "nsPopUpMenu.h"
|
||||
#include "nsIMenu.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsFileSpec.h" // XXX: For nsAutoCString
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsPopUpMenu, nsIPopUpMenu::GetIID())
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsPopUpMenu constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsPopUpMenu::nsPopUpMenu() : nsIPopUpMenu()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mNumMenuItems = 0;
|
||||
mParent = nsnull;
|
||||
mMenu = nsnull;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsPopUpMenu destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsPopUpMenu::~nsPopUpMenu()
|
||||
{
|
||||
NS_IF_RELEASE(mParent);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the proper widget
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::Create(nsIWidget *aParent)
|
||||
{
|
||||
|
||||
mParent = aParent;
|
||||
NS_ADDREF(mParent);
|
||||
|
||||
mMenu = gtk_menu_new();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::AddItem(const nsString &aText)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = gtk_menu_item_new_with_label ((const char*)nsAutoCString(mLabel));
|
||||
gtk_widget_show(widget);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::AddItem(nsIMenuItem * aMenuItem)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
void *voidData;
|
||||
|
||||
aMenuItem->GetNativeData(voidData);
|
||||
widget = GTK_WIDGET(voidData);
|
||||
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
|
||||
|
||||
// XXX add aMenuItem to internal data structor list
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::AddMenu(nsIMenu * aMenu)
|
||||
{
|
||||
nsString Label;
|
||||
GtkWidget *item=NULL, *parentmenu=NULL, *newmenu=NULL;
|
||||
void *voidData=NULL;
|
||||
|
||||
aMenu->GetLabel(Label);
|
||||
|
||||
GetNativeData(voidData);
|
||||
parentmenu = GTK_WIDGET(voidData);
|
||||
|
||||
item = gtk_menu_item_new_with_label ((const char*)nsAutoCString(Label));
|
||||
gtk_widget_show(item);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (parentmenu), item);
|
||||
|
||||
voidData = NULL;
|
||||
|
||||
aMenu->GetNativeData(&voidData);
|
||||
newmenu = GTK_WIDGET(voidData);
|
||||
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), newmenu);
|
||||
|
||||
// XXX add aMenu to internal data structor list
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::AddSeparator()
|
||||
{
|
||||
GtkWidget *widget;
|
||||
widget = gtk_menu_item_new ();
|
||||
gtk_widget_show(widget);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::GetItemCount(PRUint32 &aCount)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::GetItemAt(const PRUint32 aCount, nsIMenuItem *& aMenuItem)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::InsertItemAt(const PRUint32 aCount, nsIMenuItem *& aMenuItem)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::InsertItemAt(const PRUint32 aCount, const nsString & aMenuItemName)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::InsertSeparator(const PRUint32 aCount)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::RemoveItem(const PRUint32 aCount)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::RemoveAll()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void nsPopUpMenu::GetXY(GtkMenu *menu, gint *x, gint *y, gpointer user_data)
|
||||
{
|
||||
*x = ((nsPopUpMenu *)(user_data))->mX;
|
||||
*y = ((nsPopUpMenu *)(user_data))->mY;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::ShowMenu(PRInt32 aX, PRInt32 aY)
|
||||
{
|
||||
mX = aX;
|
||||
mY = aY;
|
||||
|
||||
gtk_menu_popup (GTK_MENU(mMenu),
|
||||
NULL,
|
||||
NULL,
|
||||
GetXY,
|
||||
this,
|
||||
0,
|
||||
GDK_CURRENT_TIME);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::GetNativeData(void *& aData)
|
||||
{
|
||||
aData = (void *)mMenu;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::GetParent(nsIWidget *& aParent)
|
||||
{
|
||||
aParent = mParent;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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):
|
||||
*/
|
||||
|
||||
#ifndef nsPopUpMenu_h__
|
||||
#define nsPopUpMenu_h__
|
||||
|
||||
#include "nsIPopUpMenu.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
/**
|
||||
* Native GTK+ PopUp wrapper
|
||||
*/
|
||||
|
||||
class nsPopUpMenu : public nsIPopUpMenu
|
||||
{
|
||||
|
||||
public:
|
||||
nsPopUpMenu();
|
||||
virtual ~nsPopUpMenu();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD Create(nsIWidget * aParent);
|
||||
|
||||
// nsIPopUpMenu Methods
|
||||
NS_IMETHOD AddItem(const nsString &aText);
|
||||
NS_IMETHOD AddItem(nsIMenuItem * aMenuItem);
|
||||
NS_IMETHOD AddMenu(nsIMenu * aMenu);
|
||||
NS_IMETHOD AddSeparator();
|
||||
NS_IMETHOD GetItemCount(PRUint32 &aCount);
|
||||
NS_IMETHOD GetItemAt(const PRUint32 aCount, nsIMenuItem *& aMenuItem);
|
||||
NS_IMETHOD InsertItemAt(const PRUint32 aCount, nsIMenuItem *& aMenuItem);
|
||||
NS_IMETHOD InsertItemAt(const PRUint32 aCount, const nsString & aMenuItemName);
|
||||
NS_IMETHOD InsertSeparator(const PRUint32 aCount);
|
||||
NS_IMETHOD RemoveItem(const PRUint32 aCount);
|
||||
NS_IMETHOD RemoveAll();
|
||||
static void GetXY(GtkMenu *menu, gint *x, gint *y, gpointer user_data);
|
||||
NS_IMETHOD ShowMenu(PRInt32 aX, PRInt32 aY);
|
||||
NS_IMETHOD GetNativeData(void*& aData);
|
||||
NS_IMETHOD GetParent(nsIWidget*& aParent);
|
||||
|
||||
protected:
|
||||
|
||||
nsString mLabel;
|
||||
|
||||
PRUint32 mNumMenuItems;
|
||||
nsIWidget *mParent;
|
||||
GtkWidget *mMenu;
|
||||
|
||||
gint mX;
|
||||
gint mY;
|
||||
};
|
||||
|
||||
#endif // nsPopUpMenu_h__
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user