Compare commits

..

11 Commits

Author SHA1 Message Date
warren%netscape.com
9394b13b25 More mac tweaks.
git-svn-id: svn://10.0.0.236/branches/logging_102400_branch@81877 18797224-902f-48f8-a5cc-f745e15eee43
2000-10-27 19:53:38 +00:00
warren%netscape.com
b0ffab807c Fixed mac debug breaks.
git-svn-id: svn://10.0.0.236/branches/logging_102400_branch@81876 18797224-902f-48f8-a5cc-f745e15eee43
2000-10-27 19:46:44 +00:00
warren%netscape.com
d9a2c8dc60 Changes to build on Mac.
git-svn-id: svn://10.0.0.236/branches/logging_102400_branch@81856 18797224-902f-48f8-a5cc-f745e15eee43
2000-10-27 05:11:58 +00:00
warren%netscape.com
44a53b1fd4 Changed ERROR to ASSERT and ABORT logs. Made printing end with newline.
git-svn-id: svn://10.0.0.236/branches/logging_102400_branch@81855 18797224-902f-48f8-a5cc-f745e15eee43
2000-10-27 04:56:56 +00:00
warren%netscape.com
c9926fb13a Cleanup suggestions from Chris
git-svn-id: svn://10.0.0.236/branches/logging_102400_branch@81743 18797224-902f-48f8-a5cc-f745e15eee43
2000-10-25 18:04:37 +00:00
warren%netscape.com
ca390d2c10 various changes to build on unix
git-svn-id: svn://10.0.0.236/branches/logging_102400_branch@81712 18797224-902f-48f8-a5cc-f745e15eee43
2000-10-25 02:14:21 +00:00
warren%netscape.com
83692e17fd Backing out bogus MANIFEST_IDL stuff
git-svn-id: svn://10.0.0.236/branches/logging_102400_branch@81711 18797224-902f-48f8-a5cc-f745e15eee43
2000-10-25 01:44:25 +00:00
warren%netscape.com
65a7fd023e Backing out bogus test stuff
git-svn-id: svn://10.0.0.236/branches/logging_102400_branch@81709 18797224-902f-48f8-a5cc-f745e15eee43
2000-10-25 01:41:39 +00:00
warren%netscape.com
ac89b148a4 Fixed spacing
git-svn-id: svn://10.0.0.236/branches/logging_102400_branch@81708 18797224-902f-48f8-a5cc-f745e15eee43
2000-10-25 01:16:56 +00:00
warren%netscape.com
b41ca12451 xpcom changes for nslog.h
git-svn-id: svn://10.0.0.236/branches/logging_102400_branch@81706 18797224-902f-48f8-a5cc-f745e15eee43
2000-10-25 00:47:00 +00:00
(no author)
311567599e This commit was manufactured by cvs2svn to create branch
'logging_102400_branch'.

git-svn-id: svn://10.0.0.236/branches/logging_102400_branch@81500 18797224-902f-48f8-a5cc-f745e15eee43
2000-10-20 01:14:50 +00:00
982 changed files with 296828 additions and 5027 deletions

View File

@@ -0,0 +1,621 @@
/* -*- 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) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsAVLTree.h"
enum eLean {eLeft,eNeutral,eRight};
struct NS_COM nsAVLNode {
public:
nsAVLNode(void* aValue) {
mLeft=0;
mRight=0;
mSkew=eNeutral;
mValue=aValue;
}
nsAVLNode* mLeft;
nsAVLNode* mRight;
eLean mSkew;
void* mValue;
};
/************************************************************
Now begin the tree class. Don't forget that the comparison
between nodes must occur via the comparitor function,
otherwise all you're testing is pointer addresses.
************************************************************/
/** ------------------------------------------------
*
*
* @update gess 4/22/98
* @param
* @return
*/ //----------------------------------------------
nsAVLTree::nsAVLTree(nsAVLNodeComparitor& aComparitor,
nsAVLNodeFunctor* aDeallocator) :
mComparitor(aComparitor), mDeallocator(aDeallocator) {
mRoot=0;
mCount=0;
}
static void
avlDeleteTree(nsAVLNode* aNode){
if (aNode) {
avlDeleteTree(aNode->mLeft);
avlDeleteTree(aNode->mRight);
delete aNode;
}
}
/**
*
* @update gess12/27/98
* @param
* @return
*/
nsAVLTree::~nsAVLTree(){
if (mDeallocator) {
ForEachDepthFirst(*mDeallocator);
}
avlDeleteTree(mRoot);
}
class CDoesntExist: public nsAVLNodeFunctor {
public:
CDoesntExist(const nsAVLTree& anotherTree) : mOtherTree(anotherTree) {
}
virtual void* operator()(void* anItem) {
void* result=mOtherTree.FindItem(anItem);
if(result)
return nsnull;
return anItem;
}
protected:
const nsAVLTree& mOtherTree;
};
/**
* This method compares two trees (members by identity).
* @update gess12/27/98
* @param tree to compare against
* @return true if they are identical (contain same stuff).
*/
PRBool nsAVLTree::operator==(const nsAVLTree& aCopy) const{
CDoesntExist functor(aCopy);
void* theItem=FirstThat(functor);
PRBool result=PRBool(!theItem);
return result;
}
/**
*
* @update gess12/27/98
* @param
* @return
*/
static void
avlRotateRight(nsAVLNode*& aRootNode){
nsAVLNode* ptr2;
nsAVLNode* ptr3;
ptr2=aRootNode->mRight;
if(ptr2->mSkew==eRight) {
aRootNode->mRight=ptr2->mLeft;
ptr2->mLeft=aRootNode;
aRootNode->mSkew=eNeutral;
aRootNode=ptr2;
}
else {
ptr3=ptr2->mLeft;
ptr2->mLeft=ptr3->mRight;
ptr3->mRight=ptr2;
aRootNode->mRight=ptr3->mLeft;
ptr3->mLeft=aRootNode;
if(ptr3->mSkew==eLeft)
ptr2->mSkew=eRight;
else ptr2->mSkew=eNeutral;
if(ptr3->mSkew==eRight)
aRootNode->mSkew=eLeft;
else aRootNode->mSkew=eNeutral;
aRootNode=ptr3;
}
aRootNode->mSkew=eNeutral;
return;
}
/**
*
* @update gess12/27/98
* @param
* @return
*/
static void
avlRotateLeft(nsAVLNode*& aRootNode){
nsAVLNode* ptr2;
nsAVLNode* ptr3;
ptr2=aRootNode->mLeft;
if(ptr2->mSkew==eLeft) {
aRootNode->mLeft=ptr2->mRight;
ptr2->mRight=aRootNode;
aRootNode->mSkew=eNeutral;
aRootNode=ptr2;
}
else {
ptr3=ptr2->mRight;
ptr2->mRight=ptr3->mLeft;
ptr3->mLeft=ptr2;
aRootNode->mLeft=ptr3->mRight;
ptr3->mRight=aRootNode;
if(ptr3->mSkew==eRight)
ptr2->mSkew=eLeft;
else ptr2->mSkew=eNeutral;
if(ptr3->mSkew==eLeft)
aRootNode->mSkew=eRight;
else aRootNode->mSkew=eNeutral;
aRootNode=ptr3;
}
aRootNode->mSkew=eNeutral;
return;
}
/** ------------------------------------------------
*
*
* @update gess 4/22/98
* @param
* @return
*/ //----------------------------------------------
static eAVLStatus
avlInsert(nsAVLNode*& aRootNode, nsAVLNode* aNewNode,
nsAVLNodeComparitor& aComparitor) {
eAVLStatus result=eAVL_unknown;
if(!aRootNode) {
aRootNode = aNewNode;
return eAVL_ok;
}
if(aNewNode==aRootNode->mValue) {
return eAVL_duplicate;
}
PRInt32 theCompareResult=aComparitor(aRootNode->mValue,aNewNode->mValue);
if(0 < theCompareResult) { //if(anItem<aRootNode->mValue)
result=avlInsert(aRootNode->mLeft,aNewNode,aComparitor);
if(eAVL_ok==result) {
switch(aRootNode->mSkew){
case eLeft:
avlRotateLeft(aRootNode);
result=eAVL_fail;
break;
case eRight:
aRootNode->mSkew=eNeutral;
result=eAVL_fail;
break;
case eNeutral:
aRootNode->mSkew=eLeft;
break;
} //switch
}//if
} //if
else {
result=avlInsert(aRootNode->mRight,aNewNode,aComparitor);
if(eAVL_ok==result) {
switch(aRootNode->mSkew){
case eLeft:
aRootNode->mSkew=eNeutral;
result=eAVL_fail;
break;
case eRight:
avlRotateRight(aRootNode);
result=eAVL_fail;
break;
case eNeutral:
aRootNode->mSkew=eRight;
break;
} //switch
}
} //if
return result;
}
/** ------------------------------------------------
*
*
* @update gess 4/22/98
* @param
* @return
*/ //----------------------------------------------
static void
avlBalanceLeft(nsAVLNode*& aRootNode, PRBool& delOk){
nsAVLNode* ptr2;
nsAVLNode* ptr3;
eLean balnc2;
eLean balnc3;
switch(aRootNode->mSkew){
case eLeft:
ptr2=aRootNode->mLeft;
balnc2=ptr2->mSkew;
if(balnc2!=eRight) {
aRootNode->mLeft=ptr2->mRight;
ptr2->mRight=aRootNode;
if(balnc2==eNeutral){
aRootNode->mSkew=eLeft;
ptr2->mSkew=eRight;
delOk=PR_FALSE;
}
else{
aRootNode->mSkew=eNeutral;
ptr2->mSkew=eNeutral;
}
aRootNode=ptr2;
}
else{
ptr3=ptr2->mRight;
balnc3=ptr3->mSkew;
ptr2->mRight=ptr3->mLeft;
ptr3->mLeft=ptr2;
aRootNode->mLeft=ptr3->mRight;
ptr3->mRight=aRootNode;
if(balnc3==eRight) {
ptr2->mSkew=eLeft;
}
else {
ptr2->mSkew=eNeutral;
}
if(balnc3==eLeft) {
aRootNode->mSkew=eRight;
}
else {
aRootNode->mSkew=eNeutral;
}
aRootNode=ptr3;
ptr3->mSkew=eNeutral;
}
break;
case eRight:
aRootNode->mSkew=eNeutral;
break;
case eNeutral:
aRootNode->mSkew=eLeft;
delOk=PR_FALSE;
break;
}//switch
return;
}
/** ------------------------------------------------
*
*
* @update gess 4/22/98
* @param
* @return
*/ //----------------------------------------------
static void
avlBalanceRight(nsAVLNode*& aRootNode, PRBool& delOk){
nsAVLNode* ptr2;
nsAVLNode* ptr3;
eLean balnc2;
eLean balnc3;
switch(aRootNode->mSkew){
case eLeft:
aRootNode->mSkew=eNeutral;
break;
case eRight:
ptr2=aRootNode->mRight;
balnc2=ptr2->mSkew;
if(balnc2!=eLeft) {
aRootNode->mRight=ptr2->mLeft;
ptr2->mLeft=aRootNode;
if(balnc2==eNeutral){
aRootNode->mSkew=eRight;
ptr2->mSkew=eLeft;
delOk=PR_FALSE;
}
else{
aRootNode->mSkew=eNeutral;
ptr2->mSkew=eNeutral;
}
aRootNode=ptr2;
}
else{
ptr3=ptr2->mLeft;
balnc3=ptr3->mSkew;
ptr2->mLeft=ptr3->mRight;
ptr3->mRight=ptr2;
aRootNode->mRight=ptr3->mLeft;
ptr3->mLeft=aRootNode;
if(balnc3==eLeft) {
ptr2->mSkew=eRight;
}
else {
ptr2->mSkew=eNeutral;
}
if(balnc3==eRight) {
aRootNode->mSkew=eLeft;
}
else {
aRootNode->mSkew=eNeutral;
}
aRootNode=ptr3;
ptr3->mSkew=eNeutral;
}
break;
case eNeutral:
aRootNode->mSkew=eRight;
delOk=PR_FALSE;
break;
}//switch
return;
}
/** ------------------------------------------------
*
*
* @update gess 4/22/98
* @param
* @return
*/ //----------------------------------------------
static eAVLStatus
avlRemoveChildren(nsAVLNode*& aRootNode,nsAVLNode*& anotherNode, PRBool& delOk){
eAVLStatus result=eAVL_ok;
if(!anotherNode->mRight){
aRootNode->mValue=anotherNode->mValue; //swap
anotherNode=anotherNode->mLeft;
delOk=PR_TRUE;
}
else{
avlRemoveChildren(aRootNode,anotherNode->mRight,delOk);
if(delOk)
avlBalanceLeft(anotherNode,delOk);
}
return result;
}
/** ------------------------------------------------
*
*
* @update gess 4/22/98
* @param
* @return
*/ //----------------------------------------------
static eAVLStatus
avlRemove(nsAVLNode*& aRootNode, void* anItem, PRBool& delOk,
nsAVLNodeComparitor& aComparitor){
eAVLStatus result=eAVL_ok;
if(!aRootNode)
delOk=PR_FALSE;
else {
PRInt32 cmp=aComparitor(anItem,aRootNode->mValue);
if(cmp<0){
avlRemove(aRootNode->mLeft,anItem,delOk,aComparitor);
if(delOk)
avlBalanceRight(aRootNode,delOk);
}
else if(cmp>0){
avlRemove(aRootNode->mRight,anItem,delOk,aComparitor);
if(delOk)
avlBalanceLeft(aRootNode,delOk);
}
else{ //they match...
nsAVLNode* temp=aRootNode;
if(!aRootNode->mRight) {
aRootNode=aRootNode->mLeft;
delOk=PR_TRUE;
delete temp;
}
else if(!aRootNode->mLeft) {
aRootNode=aRootNode->mRight;
delOk=PR_TRUE;
delete temp;
}
else {
avlRemoveChildren(aRootNode,aRootNode->mLeft,delOk);
if(delOk)
avlBalanceRight(aRootNode,delOk);
}
}
}
return result;
}
/** ------------------------------------------------
*
*
* @update gess 4/22/98
* @param
* @return
*/ //----------------------------------------------
eAVLStatus
nsAVLTree::AddItem(void* anItem){
eAVLStatus result=eAVL_ok;
nsAVLNode* theNewNode=new nsAVLNode(anItem);
result=avlInsert(mRoot,theNewNode,mComparitor);
if(eAVL_duplicate!=result)
mCount++;
else {
delete theNewNode;
}
return result;
}
/** ------------------------------------------------
*
*
* @update gess 4/22/98
* @param
* @return
*/ //----------------------------------------------
void* nsAVLTree::FindItem(void* aValue) const{
nsAVLNode* result=mRoot;
PRInt32 count=0;
while(result) {
count++;
PRInt32 cmp=mComparitor(aValue,result->mValue);
if(0==cmp) {
//we matched...
break;
}
else if(0>cmp){
//theNode was greater...
result=result->mLeft;
}
else {
//aValue is greater...
result=result->mRight;
}
}
if(result) {
return result->mValue;
}
return nsnull;
}
/**
*
* @update gess12/30/98
* @param
* @return
*/
eAVLStatus
nsAVLTree::RemoveItem(void* aValue){
PRBool delOk=PR_TRUE;
eAVLStatus result=avlRemove(mRoot,aValue,delOk,mComparitor);
if(eAVL_ok==result)
mCount--;
return result;
}
/**
*
* @update gess9/11/98
* @param
* @return
*/
static void
avlForEachDepthFirst(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor){
if(aNode) {
avlForEachDepthFirst(aNode->mLeft,aFunctor);
avlForEachDepthFirst(aNode->mRight,aFunctor);
aFunctor(aNode->mValue);
}
}
/**
*
* @update gess9/11/98
* @param
* @return
*/
void
nsAVLTree::ForEachDepthFirst(nsAVLNodeFunctor& aFunctor) const{
::avlForEachDepthFirst(mRoot,aFunctor);
}
/**
*
* @update gess9/11/98
* @param
* @return
*/
static void
avlForEach(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor) {
if(aNode) {
avlForEach(aNode->mLeft,aFunctor);
aFunctor(aNode->mValue);
avlForEach(aNode->mRight,aFunctor);
}
}
/**
*
* @update gess9/11/98
* @param
* @return
*/
void
nsAVLTree::ForEach(nsAVLNodeFunctor& aFunctor) const{
::avlForEach(mRoot,aFunctor);
}
/**
*
* @update gess9/11/98
* @param
* @return
*/
static void*
avlFirstThat(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor) {
void* result=nsnull;
if(aNode) {
result = avlFirstThat(aNode->mLeft,aFunctor);
if (result) {
return result;
}
result = aFunctor(aNode->mValue);
if (result) {
return result;
}
result = avlFirstThat(aNode->mRight,aFunctor);
}
return result;
}
/**
*
* @update gess9/11/98
* @param
* @return
*/
void*
nsAVLTree::FirstThat(nsAVLNodeFunctor& aFunctor) const{
return ::avlFirstThat(mRoot,aFunctor);
}

View File

@@ -0,0 +1,78 @@
/* -*- 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) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsAVLTree_h___
#define nsAVLTree_h___
#include "nscore.h"
enum eAVLStatus {eAVL_unknown,eAVL_ok,eAVL_fail,eAVL_duplicate};
struct nsAVLNode;
/**
*
* @update gess12/26/98
* @param anObject1 is the first object to be compared
* @param anObject2 is the second object to be compared
* @return -1,0,1 if object1 is less, equal, greater than object2
*/
class NS_COM nsAVLNodeComparitor {
public:
virtual PRInt32 operator()(void* anItem1,void* anItem2)=0;
};
class NS_COM nsAVLNodeFunctor {
public:
virtual void* operator()(void* anItem)=0;
};
class NS_COM nsAVLTree {
public:
nsAVLTree(nsAVLNodeComparitor& aComparitor, nsAVLNodeFunctor* aDeallocator);
~nsAVLTree(void);
PRBool operator==(const nsAVLTree& aOther) const;
PRInt32 GetCount(void) const {return mCount;}
//main functions...
eAVLStatus AddItem(void* anItem);
eAVLStatus RemoveItem(void* anItem);
void* FindItem(void* anItem) const;
void ForEach(nsAVLNodeFunctor& aFunctor) const;
void ForEachDepthFirst(nsAVLNodeFunctor& aFunctor) const;
void* FirstThat(nsAVLNodeFunctor& aFunctor) const;
protected:
nsAVLNode* mRoot;
PRInt32 mCount;
nsAVLNodeComparitor& mComparitor;
nsAVLNodeFunctor* mDeallocator;
};
#endif /* nsAVLTree_h___ */

View File

@@ -1,70 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Srilatha Moturi <srilatha@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIDOMWindow;
/**
* This interface provides support for registering Mozilla as the default
* Mail Client. This interface can also be used to get/set the user preference
* for the default Mail Client.
*
*/
[scriptable, uuid(c5be14ba-4e0a-4eec-a1b8-04363761d63c)]
interface nsIMapiRegistry: nsISupports {
/** This is set to TRUE if Mozilla is the default Application
*/
attribute boolean isDefaultMailClient;
/** This is set TRUE only once per session.
*/
readonly attribute boolean showDialog;
/** This will bring the dialog asking the user if he/she wants to set
* Mozilla as default Mail Client.
* Call this only if Mozilla is not the default Mail client
*/
void showMailIntegrationDialog(in nsIDOMWindow parentWindow);
};
%{C++
#define NS_IMAPIREGISTRY_CONTRACTID "@mozilla.org/mapiregistry;1"
#define NS_IMAPIREGISTRY_CLASSNAME "Mozilla MAPI Registry"
%}

View File

@@ -1,54 +0,0 @@
; ***** BEGIN LICENSE BLOCK *****
; Version: MPL 1.1/GPL 2.0/LGPL 2.1
;
; The contents of this file are subject to the Mozilla Public License Version
; 1.1 (the "License"); you may not use this file except in compliance with
; the License. You may obtain a copy of the License at
; http://www.mozilla.org/MPL/
;
; Software distributed under the License is distributed on an "AS IS" basis,
; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
; for the specific language governing rights and limitations under the
; License.
;
; The Original Code is Mozilla.
;
; The Initial Developer of the Original Code is
; Netscape Communications Corp.
; Portions created by the Initial Developer are Copyright (C) 2001
; the Initial Developer. All Rights Reserved.
;
; Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
;
; Alternatively, the contents of this file may be used under the terms of
; either the GNU General Public License Version 2 or later (the "GPL"), or
; the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
; in which case the provisions of the GPL or the LGPL are applicable instead
; of those above. If you wish to allow use of your version of this file only
; under the terms of either the GPL or the LGPL, and not to allow others to
; use your version of this file under the terms of the MPL, indicate your
; decision by deleting the provisions above and replace them with the notice
; and other provisions required by the GPL or the LGPL. If you do not delete
; the provisions above, a recipient may use your version of this file under
; the terms of any one of the MPL, the GPL or the LGPL.
;
; ***** END LICENSE BLOCK *****
LIBRARY mozMapi32.dll
DESCRIPTION 'Mozilla Simple MAPI Support'
EXPORTS
MAPILogon
MAPILogoff
MAPISendMail
MAPISendDocuments
MAPIFindNext
MAPIReadMail
MAPISaveMail
MAPIDeleteMail
MAPIAddress
MAPIDetails
MAPIResolveName
MAPIFreeBuffer
GetMapiDllVersion

View File

@@ -1,346 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
* Contributor(s): Rajiv Dayal (rdayal@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <windows.h>
#include <tchar.h>
#include <mapidefs.h>
#include <mapi.h>
#include "msgMapi.h"
#include "msgMapiMain.h"
#define MAX_RECIPS 100
#define MAX_FILES 100
const CLSID CLSID_CMapiImp = {0x29f458be, 0x8866, 0x11d5,
{0xa3, 0xdd, 0x0, 0xb0, 0xd0, 0xf3, 0xba, 0xa7}};
const IID IID_nsIMapi = {0x6EDCD38E,0x8861,0x11d5,
{0xA3,0xDD,0x00,0xB0,0xD0,0xF3,0xBA,0xA7}};
DWORD tId = 0;
BOOL WINAPI DllMain(HINSTANCE aInstance, DWORD aReason, LPVOID aReserved)
{
switch (aReason)
{
case DLL_PROCESS_ATTACH : tId = TlsAlloc();
if (tId == 0xFFFFFFFF)
return FALSE;
break;
case DLL_PROCESS_DETACH : TlsFree(tId);
break;
}
return TRUE;
}
BOOL InitMozillaReference(nsIMapi **aRetValue)
{
// Check wehther this thread has a valid Interface
// by looking into thread-specific-data variable
*aRetValue = (nsIMapi *)TlsGetValue(tId);
// Check whether the pointer actually resolves to
// a valid method call; otherwise mozilla is not running
if ((*aRetValue) && (*aRetValue)->IsValid() == S_OK)
return TRUE;
HRESULT hRes = ::CoInitialize(nsnull) ;
hRes = ::CoCreateInstance(CLSID_CMapiImp, NULL, CLSCTX_LOCAL_SERVER,
IID_nsIMapi, (LPVOID *)aRetValue);
if (hRes == S_OK && (*aRetValue)->Initialize() == S_OK)
if (TlsSetValue(tId, (LPVOID)(*aRetValue)))
return TRUE;
// Either CoCreate or TlsSetValue failed; so return FALSE
if ((*aRetValue))
(*aRetValue)->Release();
::CoUninitialize();
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////////
// The MAPILogon function begins a Simple MAPI session, loading the default message ////
// store and address book providers ////
////////////////////////////////////////////////////////////////////////////////////////
ULONG FAR PASCAL MAPILogon(ULONG aUIParam, LPTSTR aProfileName,
LPTSTR aPassword, FLAGS aFlags,
ULONG aReserved, LPLHANDLE aSession)
{
HRESULT hr = 0;
ULONG nSessionId = 0;
nsIMapi *pNsMapi = NULL;
if (!InitMozillaReference(&pNsMapi))
return MAPI_E_FAILURE;
if (!(aFlags & MAPI_UNICODE))
{
// Need to convert the parameters to Unicode.
char *pUserName = (char *) aProfileName;
char *pPassWord = (char *) aPassword;
TCHAR ProfileName[MAX_NAME_LEN] = {0};
TCHAR PassWord[MAX_PW_LEN] = {0};
if (pUserName != NULL)
{
if (!MultiByteToWideChar(CP_ACP, 0, pUserName, -1, ProfileName,
MAX_NAME_LEN))
return MAPI_E_FAILURE;
}
if (pPassWord != NULL)
{
if (!MultiByteToWideChar(CP_ACP, 0, pPassWord, -1, PassWord,
MAX_NAME_LEN))
return MAPI_E_FAILURE;
}
hr = pNsMapi->Login(aUIParam, ProfileName, PassWord, aFlags,
&nSessionId);
}
else
hr = pNsMapi->Login(aUIParam, aProfileName, aPassword,
aFlags, &nSessionId);
if (hr == S_OK)
(*aSession) = (LHANDLE) nSessionId;
else
return nSessionId;
return SUCCESS_SUCCESS;
}
ULONG FAR PASCAL MAPILogoff (LHANDLE aSession, ULONG aUIParam,
FLAGS aFlags, ULONG aReserved)
{
nsIMapi *pNsMapi = (nsIMapi *)TlsGetValue(tId);
if (pNsMapi != NULL)
{
if (pNsMapi->Logoff((ULONG) aSession) == S_OK)
pNsMapi->Release();
pNsMapi = NULL;
}
TlsSetValue(tId, NULL);
::CoUninitialize();
return SUCCESS_SUCCESS;
}
ULONG FAR PASCAL MAPISendMail (LHANDLE lhSession, ULONG ulUIParam, lpnsMapiMessage lpMessage,
FLAGS flFlags, ULONG ulReserved )
{
HRESULT hr = 0;
BOOL bTempSession = FALSE ;
nsIMapi *pNsMapi = NULL;
if (!InitMozillaReference(&pNsMapi))
return MAPI_E_FAILURE;
if (lpMessage->nRecipCount > MAX_RECIPS)
return MAPI_E_TOO_MANY_RECIPIENTS ;
if (lpMessage->nFileCount > MAX_FILES)
return MAPI_E_TOO_MANY_FILES ;
if ( (!(flFlags & MAPI_DIALOG)) && (lpMessage->lpRecips == NULL) )
return MAPI_E_UNKNOWN_RECIPIENT ;
if (!lhSession || pNsMapi->IsValidSession(lhSession) != S_OK)
{
FLAGS LoginFlag ;
if ( (flFlags & MAPI_LOGON_UI) && (flFlags & MAPI_NEW_SESSION) )
LoginFlag = MAPI_LOGON_UI | MAPI_NEW_SESSION ;
else if (flFlags & MAPI_LOGON_UI)
LoginFlag = MAPI_LOGON_UI ;
hr = MAPILogon (ulUIParam, (LPTSTR) NULL, (LPTSTR) NULL, LoginFlag, 0, &lhSession) ;
if (hr != SUCCESS_SUCCESS)
return MAPI_E_LOGIN_FAILURE ;
bTempSession = TRUE ;
}
// we need to deal with null data passed in by MAPI clients, specially when MAPI_DIALOG is set.
// The MS COM type lib code generated by MIDL for the MS COM interfaces checks for these parameters
// to be non null, although null is a valid value for them here.
nsMapiRecipDesc * lpRecips ;
nsMapiFileDesc * lpFiles ;
nsMapiMessage Message ;
memset (&Message, 0, sizeof (nsMapiMessage) ) ;
nsMapiRecipDesc Recipient ;
memset (&Recipient, 0, sizeof (nsMapiRecipDesc) );
nsMapiFileDesc Files ;
memset (&Files, 0, sizeof (nsMapiFileDesc) ) ;
if(!lpMessage)
{
lpMessage = &Message ;
}
if(!lpMessage->lpRecips)
{
lpRecips = &Recipient ;
}
else
lpRecips = lpMessage->lpRecips ;
if(!lpMessage->lpFiles)
{
lpFiles = &Files ;
}
else
lpFiles = lpMessage->lpFiles ;
HANDLE hEvent = CreateEvent (NULL, FALSE, FALSE, (LPCTSTR) MAPI_SENDCOMPLETE_EVENT) ;
hr = pNsMapi->SendMail (lhSession, lpMessage,
(short) lpMessage->nRecipCount, lpRecips,
(short) lpMessage->nFileCount, lpFiles,
flFlags, ulReserved);
// we are seeing a problem when using Word, although we return success from the MAPI support
// MS COM interface in mozilla, we are getting this error here. This is a temporary hack !!
if (hr == 0x800703e6)
hr = SUCCESS_SUCCESS;
if (hr == SUCCESS_SUCCESS)
WaitForSingleObject (hEvent, INFINITE) ;
CloseHandle (hEvent) ;
if (bTempSession)
MAPILogoff (lhSession, ulUIParam, 0,0) ;
return hr ;
}
ULONG FAR PASCAL MAPISendDocuments(ULONG ulUIParam, LPTSTR lpszDelimChar, LPTSTR lpszFilePaths,
LPTSTR lpszFileNames, ULONG ulReserved)
{
LHANDLE lhSession ;
nsIMapi *pNsMapi = NULL;
if (!InitMozillaReference(&pNsMapi))
return MAPI_E_FAILURE;
unsigned long result = MAPILogon (ulUIParam, (LPTSTR) NULL, (LPTSTR) NULL, MAPI_LOGON_UI, 0, &lhSession) ;
if (result != SUCCESS_SUCCESS)
return MAPI_E_LOGIN_FAILURE ;
HRESULT hr;
HANDLE hEvent = CreateEvent (NULL, FALSE, FALSE, (LPCTSTR) MAPI_SENDCOMPLETE_EVENT) ;
hr = pNsMapi->SendDocuments(lhSession, (LPTSTR) lpszDelimChar, (LPTSTR) lpszFilePaths,
(LPTSTR) lpszFileNames, ulReserved) ;
if (hr == SUCCESS_SUCCESS)
WaitForSingleObject (hEvent, INFINITE) ;
CloseHandle (hEvent) ;
MAPILogoff (lhSession, ulUIParam, 0,0) ;
return hr ;
}
ULONG FAR PASCAL MAPIFindNext(LHANDLE lhSession, ULONG ulUIParam, LPTSTR lpszMessageType,
LPTSTR lpszSeedMessageID, FLAGS flFlags, ULONG ulReserved,
LPTSTR lpszMessageID)
{
return MAPI_E_FAILURE;
}
ULONG FAR PASCAL MAPIReadMail(LHANDLE lhSession, ULONG ulUIParam, LPTSTR lpszMessageID,
FLAGS flFlags, ULONG ulReserved, lpMapiMessage FAR *lppMessage)
{
return MAPI_E_FAILURE;
}
ULONG FAR PASCAL MAPISaveMail(LHANDLE lhSession, ULONG ulUIParam, lpMapiMessage lpMessage,
FLAGS flFlags, ULONG ulReserved, LPTSTR lpszMessageID)
{
return MAPI_E_FAILURE;
}
ULONG FAR PASCAL MAPIDeleteMail(LHANDLE lhSession, ULONG ulUIParam, LPTSTR lpszMessageID,
FLAGS flFlags, ULONG ulReserved)
{
return MAPI_E_FAILURE;
}
ULONG FAR PASCAL MAPIAddress(LHANDLE lhSession, ULONG ulUIParam, LPTSTR lpszCaption,
ULONG nEditFields, LPTSTR lpszLabels, ULONG nRecips,
lpMapiRecipDesc lpRecips, FLAGS flFlags,
ULONG ulReserved, LPULONG lpnNewRecips,
lpMapiRecipDesc FAR *lppNewRecips)
{
return MAPI_E_FAILURE;
}
ULONG FAR PASCAL MAPIDetails(LHANDLE lhSession, ULONG ulUIParam, lpMapiRecipDesc lpRecip,
FLAGS flFlags, ULONG ulReserved)
{
return MAPI_E_FAILURE;
}
ULONG FAR PASCAL MAPIResolveName(LHANDLE lhSession, ULONG ulUIParam, LPTSTR lpszName,
FLAGS flFlags, ULONG ulReserved, lpMapiRecipDesc FAR *lppRecip)
{
return MAPI_E_FAILURE;
}
ULONG FAR PASCAL MAPIFreeBuffer(LPVOID pv)
{
return MAPI_E_FAILURE;
}
ULONG FAR PASCAL GetMapiDllVersion()
{
return 94;
}

View File

@@ -1,62 +0,0 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Mozilla.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corp.
# Portions created by the Initial Developer are Copyright (C) 2001
# the Initial Developer. All Rights Reserved.
#
# Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH=..\..\..
MODULE = mozMapi32
EXPORT_LIBRARY = $(MODULE)
LIBRARY_NAME = $(MODULE)
DEFFILE = Mapi32.def
REQUIRES = MapiProxy \
msgMapi \
xpcom \
string \
$(NULL)
include <$(DEPTH)\config\config.mak>
###############################################################
LCFLAGS=-DUNICODE -D_UNICODE
OBJS= .\$(OBJDIR)\MapiDll.obj \
$(NULL)
WIN_LIBS= ole32.lib \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,47 +0,0 @@
; ***** BEGIN LICENSE BLOCK *****
; Version: MPL 1.1/GPL 2.0/LGPL 2.1
;
; The contents of this file are subject to the Mozilla Public License Version
; 1.1 (the "License"); you may not use this file except in compliance with
; the License. You may obtain a copy of the License at
; http://www.mozilla.org/MPL/
;
; Software distributed under the License is distributed on an "AS IS" basis,
; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
; for the specific language governing rights and limitations under the
; License.
;
; The Original Code is Mozilla.
;
; The Initial Developer of the Original Code is
; Netscape Communications Corp.
; Portions created by the Initial Developer are Copyright (C) 2001
; the Initial Developer. All Rights Reserved.
;
; Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
;
; Alternatively, the contents of this file may be used under the terms of
; either the GNU General Public License Version 2 or later (the "GPL"), or
; the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
; in which case the provisions of the GPL or the LGPL are applicable instead
; of those above. If you wish to allow use of your version of this file only
; under the terms of either the GPL or the LGPL, and not to allow others to
; use your version of this file under the terms of the MPL, indicate your
; decision by deleting the provisions above and replace them with the notice
; and other provisions required by the GPL or the LGPL. If you do not delete
; the provisions above, a recipient may use your version of this file under
; the terms of any one of the MPL, the GPL or the LGPL.
;
; ***** END LICENSE BLOCK *****
LIBRARY MapiProxy.dll
DESCRIPTION 'Proxy/Stub DLL'
EXPORTS
DllGetClassObject @1 PRIVATE
DllCanUnloadNow @2 PRIVATE
GetProxyDllInfo @3 PRIVATE
DllRegisterServer @4 PRIVATE
DllUnregisterServer @5 PRIVATE

View File

@@ -1,68 +0,0 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Mozilla.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corp.
# Portions created by the Initial Developer are Copyright (C) 2001
# the Initial Developer. All Rights Reserved.
#
# Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH=..\..\..\..
MODULE = MapiProxy
EXPORT_LIBRARY = $(MODULE)
LIBRARY_NAME = $(MODULE)
DEFFILE = MapiProxy.def
include <$(DEPTH)\config\config.mak>
##################################################################
LCFLAGS=-DREGISTER_PROXY_DLL -DUNICODE -D_UNICODE
OBJS= .\$(OBJDIR)\dlldata.obj \
.\$(OBJDIR)\msgMapi_p.obj \
.\$(OBJDIR)\msgMapi_i.obj \
$(NULL)
WIN_LIBS= rpcrt4.lib
EXPORTS= msgMapi.h \
$(NULL)
include <$(DEPTH)\config\rules.mak>
msgMapi.h msgMapi_p.c msgMapi_i.c dlldata.c : msgMapi.idl
midl $(UNICODE_FLAGS) msgMapi.idl
clobber::
rm -f dlldata.c msgMapi_i.c msgMapi_p.c msgMapi.h

View File

@@ -1,114 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
* Contributor(s): Rajiv Dayal (rdayal@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
// This idl will be compiled by MIDL. MS-COM is used
// as brdige between MAPI clients and the Mozilla.
import "unknwn.idl";
typedef wchar_t LOGIN_PW_TYPE[256];
typedef struct
{
unsigned long ulReserved;
unsigned long flFlags; /* Flags */
unsigned long nPosition_NotUsed; /* character in text to be replaced by attachment */
LPTSTR lpszPathName; /* Full path name including file name */
LPTSTR lpszFileName; /* Real (original) file name */
unsigned char * lpFileType_NotUsed ;
} nsMapiFileDesc, * lpnsMapiFileDesc;
typedef struct
{
unsigned long ulReserved;
unsigned long ulRecipClass; /* MAPI_TO, MAPI_CC, MAPI_BCC, MAPI_ORIG */
LPTSTR lpszName; /* Recipient name to display */
LPTSTR lpszAddress; /* Recipient email address */
unsigned long ulEIDSize_NotUsed;
unsigned char * lpEntryID_NotUsed ;
} nsMapiRecipDesc, * lpnsMapiRecipDesc;
typedef struct
{
unsigned long ulReserved;
LPTSTR lpszSubject; /* Message Subject */
LPTSTR lpszNoteText; /* Message Text */
LPTSTR lpszMessageType_NotUsed;
LPTSTR lpszDateReceived_notUsed; /* in YYYY/MM/DD HH:MM format */
LPTSTR lpszConversationID_NotUsed; /* conversation thread ID */
unsigned long flFlags; /* unread,return receipt */
lpnsMapiRecipDesc lpOriginator; /* Originator descriptor */
unsigned long nRecipCount; /* Number of recipients */
lpnsMapiRecipDesc lpRecips; /* Recipient descriptors */
unsigned long nFileCount; /* # of file attachments */
lpnsMapiFileDesc lpFiles; /* Attachment descriptors */
} nsMapiMessage, * lpnsMapiMessage;
[
object,
uuid(6EDCD38E-8861-11d5-A3DD-00B0D0F3BAA7),
helpstring("nsIMapi Inteface"),
pointer_default(unique)
]
interface nsIMapi : IUnknown
{
HRESULT Login(unsigned long aUIArg, LOGIN_PW_TYPE aLogin,
LOGIN_PW_TYPE aPassWord, unsigned long aFlags,
[out] unsigned long *aSessionId);
HRESULT Initialize();
HRESULT IsValid();
HRESULT IsValidSession([in] unsigned long aSession);
HRESULT SendMail([in] unsigned long aSession, [in] lpnsMapiMessage aMessage,
[in] short aRecipCount, [in, size_is(aRecipCount)] lpnsMapiRecipDesc aRecips,
[in] short aFileCount, [in, size_is(aFileCount)] lpnsMapiFileDesc aFiles,
[in] unsigned long aFlags, [in] unsigned long aReserved) ;
HRESULT SendDocuments( [in] unsigned long aSession,
[in] LPTSTR aDelimChar, [in] LPTSTR aFilePaths,
[in] LPTSTR aFileNames, [in] ULONG aFlags ) ;
HRESULT Logoff (unsigned long aSession);
HRESULT CleanUp();
};

View File

@@ -1,41 +0,0 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Mozilla.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corp.
# Portions created by the Initial Developer are Copyright (C) 2001
# the Initial Developer. All Rights Reserved.
#
# Contributor(s): Srilatha Moturi (srilatha@netscape.com)
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH=..\..\..
DIRS= build public src
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,49 +0,0 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 2001
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Srilatha Moturi <srilatha@netscape.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH=..\..\..\..
MODULE=msgMapi
XPIDL_MODULE=mapihook
XPIDLSRCS = \
.\nsIMapiRegistry.idl \
.\nsIMapiSupport.idl \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,70 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Srilatha Moturi <srilatha@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIDOMWindow;
/**
* This interface provides support for registering Mozilla as the default
* Mail Client. This interface can also be used to get/set the user preference
* for the default Mail Client.
*
*/
[scriptable, uuid(c5be14ba-4e0a-4eec-a1b8-04363761d63c)]
interface nsIMapiRegistry: nsISupports {
/** This is set to TRUE if Mozilla is the default Application
*/
attribute boolean isDefaultMailClient;
/** This is set TRUE only once per session.
*/
readonly attribute boolean showDialog;
/** This will bring the dialog asking the user if he/she wants to set
* Mozilla as default Mail Client.
* Call this only if Mozilla is not the default Mail client
*/
void showMailIntegrationDialog(in nsIDOMWindow parentWindow);
};
%{C++
#define NS_IMAPIREGISTRY_CONTRACTID "@mozilla.org/mapiregistry;1"
#define NS_IMAPIREGISTRY_CLASSNAME "Mozilla MAPI Registry"
%}

View File

@@ -1,64 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
/**
* This interface provides support for registering Mozilla as a COM component
* for extending the use of Mail/News through Simple MAPI.
*
*/
[noscript, uuid(8967fed2-c8bb-11d5-a3e9-00b0d0f3baa7)]
interface nsIMapiSupport : nsISupports {
/** Initiates MAPI support
*/
void initializeMAPISupport();
/** Shuts down the MAPI support
*/
void shutdownMAPISupport();
};
%{C++
#define NS_IMAPISUPPORT_CONTRACTID "@mozilla.org/mapisupport;1"
#define NS_IMAPISUPPORT_CLASSNAME "Mozilla MAPI Support"
%}

View File

@@ -1,323 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika <kkhandrika@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#undef _UNICODE
#undef UNICODE
#include <objbase.h>
#include "nsString.h"
#include "Registry.h"
#define MAPI_PROXY_DLL_NAME "MapiProxy.dll"
#define MAPI_STARTUP_ARG " /MAPIStartUp"
#define MAX_SIZE 2048
// Size of a CLSID as a string
const int CLSID_STRING_SIZE = 39;
// Proxy/Stub Dll Routines
typedef HRESULT (__stdcall ProxyServer)();
// Convert a CLSID to a char string.
BOOL CLSIDtochar(const CLSID& clsid, char* szCLSID,
int length)
{
LPOLESTR wszCLSID = NULL;
// Get CLSID
HRESULT hr = StringFromCLSID(clsid, &wszCLSID);
if (FAILED(hr))
return FALSE;
// Covert from wide characters to non-wide.
wcstombs(szCLSID, wszCLSID, length);
// Free memory.
CoTaskMemFree(wszCLSID);
return TRUE;
}
// Create a key and set its value.
BOOL setKeyAndValue(nsCAutoString keyName, const char* subKey,
const char* theValue)
{
HKEY hKey;
BOOL retValue = TRUE;
nsCAutoString theKey(keyName);
if (subKey != NULL)
{
theKey += "\\";
theKey += subKey;
}
// Create and open key and subkey.
long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, theKey.get(),
0, NULL, REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL, &hKey, NULL);
if (lResult != ERROR_SUCCESS)
return FALSE ;
// Set the Value.
if (theValue != NULL)
{
lResult = RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE *)theValue,
strlen(theValue)+1);
if (lResult != ERROR_SUCCESS)
retValue = FALSE;
}
RegCloseKey(hKey);
return TRUE;
}
// Delete a key and all of its descendents.
LONG recursiveDeleteKey(HKEY hKeyParent, // Parent of key to delete
const char* lpszKeyChild) // Key to delete
{
// Open the child.
HKEY hKeyChild ;
LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyChild, 0,
KEY_ALL_ACCESS, &hKeyChild) ;
if (lRes != ERROR_SUCCESS)
{
return lRes ;
}
// Enumerate all of the decendents of this child.
FILETIME time ;
char szBuffer[MAX_SIZE] ;
DWORD dwSize = MAX_SIZE ;
while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL,
NULL, NULL, &time) == S_OK)
{
// Delete the decendents of this child.
lRes = recursiveDeleteKey(hKeyChild, szBuffer) ;
if (lRes != ERROR_SUCCESS)
{
// Cleanup before exiting.
RegCloseKey(hKeyChild) ;
return lRes;
}
dwSize = MAX_SIZE;
}
// Close the child.
RegCloseKey(hKeyChild) ;
// Delete this child.
return RegDeleteKey(hKeyParent, lpszKeyChild) ;
}
void RegisterProxy()
{
HINSTANCE h = NULL;
ProxyServer *RegisterFunc = NULL;
char szModule[MAX_SIZE];
char *pTemp = NULL;
HMODULE hModule = GetModuleHandle(NULL);
DWORD dwResult = ::GetModuleFileName(hModule, szModule,
sizeof(szModule)/sizeof(char));
if (dwResult == 0)
return;
pTemp = strrchr(szModule, '\\');
if (pTemp == NULL)
return;
*pTemp = '\0';
nsCAutoString proxyPath(szModule);
proxyPath += "\\";
proxyPath += MAPI_PROXY_DLL_NAME;
h = LoadLibrary(proxyPath.get());
if (h == NULL)
return;
RegisterFunc = (ProxyServer *) GetProcAddress(h, "DllRegisterServer");
if (RegisterFunc)
RegisterFunc();
FreeLibrary(h);
}
void UnRegisterProxy()
{
HINSTANCE h = NULL;
ProxyServer *UnRegisterFunc = NULL;
char szModule[MAX_SIZE];
char *pTemp = NULL;
HMODULE hModule = GetModuleHandle(NULL);
DWORD dwResult = ::GetModuleFileName(hModule, szModule,
sizeof(szModule)/sizeof(char));
if (dwResult == 0)
return;
pTemp = strrchr(szModule, '\\');
if (pTemp == NULL)
return;
*pTemp = '\0';
nsCAutoString proxyPath(szModule);
proxyPath += "\\";
proxyPath += MAPI_PROXY_DLL_NAME;
h = LoadLibrary(proxyPath.get());
if (h == NULL)
return;
UnRegisterFunc = (ProxyServer *) GetProcAddress(h, "DllUnregisterServer");
if (UnRegisterFunc)
UnRegisterFunc();
FreeLibrary(h);
}
// Register the component in the registry.
HRESULT RegisterServer(const CLSID& clsid, // Class ID
const char* szFriendlyName, // Friendly Name
const char* szVerIndProgID, // Programmatic
const char* szProgID) // IDs
{
HMODULE hModule = GetModuleHandle(NULL);
char szModuleName[MAX_SIZE];
char szCLSID[CLSID_STRING_SIZE];
nsCAutoString independentProgId(szVerIndProgID);
nsCAutoString progId(szProgID);
DWORD dwResult = ::GetModuleFileName(hModule, szModuleName,
sizeof(szModuleName)/sizeof(char));
if (dwResult == 0)
return S_FALSE;
nsCAutoString moduleName(szModuleName);
nsCAutoString registryKey("CLSID\\");
moduleName += MAPI_STARTUP_ARG;
// Convert the CLSID into a char.
if (!CLSIDtochar(clsid, szCLSID, sizeof(szCLSID)))
return S_FALSE;
registryKey += szCLSID;
// Add the CLSID to the registry.
if (!setKeyAndValue(registryKey, NULL, szFriendlyName))
return S_FALSE;
if (!setKeyAndValue(registryKey, "LocalServer32", moduleName.get()))
return S_FALSE;
// Add the ProgID subkey under the CLSID key.
if (!setKeyAndValue(registryKey, "ProgID", szProgID))
return S_FALSE;
// Add the version-independent ProgID subkey under CLSID key.
if (!setKeyAndValue(registryKey, "VersionIndependentProgID", szVerIndProgID))
return S_FALSE;
// Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT.
if (!setKeyAndValue(independentProgId, NULL, szFriendlyName))
return S_FALSE;
if (!setKeyAndValue(independentProgId, "CLSID", szCLSID))
return S_FALSE;
if (!setKeyAndValue(independentProgId, "CurVer", szProgID))
return S_FALSE;
// Add the versioned ProgID subkey under HKEY_CLASSES_ROOT.
if (!setKeyAndValue(progId, NULL, szFriendlyName))
return S_FALSE;
if (!setKeyAndValue(progId, "CLSID", szCLSID))
return S_FALSE;
RegisterProxy();
return S_OK;
}
LONG UnregisterServer(const CLSID& clsid, // Class ID
const char* szVerIndProgID, // Programmatic
const char* szProgID) // IDs
{
LONG lResult = S_OK;
// Convert the CLSID into a char.
char szCLSID[CLSID_STRING_SIZE];
if (!CLSIDtochar(clsid, szCLSID, sizeof(szCLSID)))
return S_FALSE;
UnRegisterProxy();
nsCAutoString registryKey("CLSID\\");
registryKey += szCLSID;
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, registryKey.get());
if (lResult == ERROR_SUCCESS || lResult == ERROR_FILE_NOT_FOUND)
return lResult;
registryKey += "\\LocalServer32";
// Delete only the path for this server.
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, registryKey.get());
if (lResult != ERROR_SUCCESS && lResult != ERROR_FILE_NOT_FOUND)
return lResult;
// Delete the version-independent ProgID Key.
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szVerIndProgID);
if (lResult != ERROR_SUCCESS && lResult != ERROR_FILE_NOT_FOUND)
return lResult;
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szProgID);
return lResult;
}

View File

@@ -1,56 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Krishna Mohan Khandrika <kkhandrika@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _REGISTRY_H_
#define _REGISTRY_H_
#include <objbase.h>
// This function will register a component in the Registry.
HRESULT RegisterServer(const CLSID& clsid,
const char* szFriendlyName,
const char* szVerIndProgID,
const char* szProgID) ;
// This function will unregister a component.
HRESULT UnregisterServer(const CLSID& clsid,
const char* szVerIndProgID,
const char* szProgID) ;
#endif

View File

@@ -1,107 +0,0 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 2001
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Srilatha Moturi <srilatha@netscape.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH=..\..\..\..
MODULE = msgMapi
MAKE_OBJ_TYPE = DLL
LIBRARY_NAME=$(MODULE)
MODULE_NAME = $(MODULE)
REQUIRES = xpcom \
string \
MapiProxy \
appshell \
windowwatcher \
dom \
profile \
msgbase \
pref \
msgbaseutil \
msgcompo \
mailnews \
necko \
intl \
editor \
msgdb \
uriloader \
appstartup \
$(NULL)
include <$(DEPTH)\config\config.mak>
############################################################################
LCFLAGS=-DUNICODE -D_UNICODE
OBJS= \
..\build\$(OBJDIR)\msgMapi_i.obj \
.\$(OBJDIR)\msgMapiFactory.obj \
.\$(OBJDIR)\msgMapiHook.obj \
.\$(OBJDIR)\msgMapiImp.obj \
.\$(OBJDIR)\msgMapiMain.obj \
.\$(OBJDIR)\msgMapiSupport.obj \
.\$(OBJDIR)\nsMapiRegistry.obj \
.\$(OBJDIR)\nsMapiRegistryUtils.obj \
.\$(OBJDIR)\Registry.obj \
$(NULL)
LLIBS= \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\msgbsutl.lib \
$(LIBNSPR) \
$(NULL)
WIN_LIBS= \
ole32.lib \
$(NULL)
EXPORTS= \
msgMapiFactory.h \
msgMapiHook.h \
msgMapiImp.h \
msgMapiMain.h \
msgMapiSupport.h \
nsMapiRegistry.h \
nsMapiRegistryUtils.h \
Registry.h \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,118 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#undef UNICODE
#undef _UNICODE
#include "msgMapiFactory.h"
#include "msgMapiImp.h"
#include "msgMapi.h"
CMapiFactory ::CMapiFactory()
: m_cRef(1)
{
}
CMapiFactory::~CMapiFactory()
{
}
STDMETHODIMP CMapiFactory::QueryInterface(const IID& aIid, void** aPpv)
{
if ((aIid == IID_IUnknown) || (aIid == IID_IClassFactory))
{
*aPpv = static_cast<IClassFactory*>(this);
}
else
{
*aPpv = nsnull;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*aPpv)->AddRef();
return S_OK;
}
STDMETHODIMP_(ULONG) CMapiFactory::AddRef()
{
return (PR_AtomicIncrement(&m_cRef));
}
STDMETHODIMP_(ULONG) CMapiFactory::Release()
{
PRInt32 temp;
temp = PR_AtomicDecrement(&m_cRef);
if (m_cRef == 0)
{
delete this;
return 0;
}
return temp;
}
STDMETHODIMP CMapiFactory::CreateInstance(IUnknown* aUnknownOuter,
const IID& aIid,
void** aPpv)
{
// Cannot aggregate.
if (aUnknownOuter != nsnull)
{
return CLASS_E_NOAGGREGATION ;
}
// Create component.
CMapiImp* pImp = new CMapiImp();
if (pImp == nsnull)
{
return E_OUTOFMEMORY ;
}
// Get the requested interface.
HRESULT hr = pImp->QueryInterface(aIid, aPpv);
// Release the IUnknown pointer.
// (If QueryInterface failed, component will delete itself.)
pImp->Release();
return hr;
}
STDMETHODIMP CMapiFactory::LockServer(PRBool aLock)
{
return S_OK ;
}

View File

@@ -1,69 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef MSG_MAPI_FACTORY_H
#define MSG_MAPI_FACTORY_H
#include <windows.h>
#include <objbase.h>
#include "nspr.h"
class CMapiFactory : public IClassFactory
{
public :
// IUnknown
STDMETHODIMP QueryInterface (REFIID aIid, void** aPpv);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
// IClassFactory
STDMETHODIMP CreateInstance (LPUNKNOWN aUnkOuter, REFIID aIid, void **aPpv);
STDMETHODIMP LockServer (BOOL aLock);
CMapiFactory ();
~CMapiFactory ();
private :
PRInt32 m_cRef;
};
#endif // MSG_MAPI_FACTORY_H

View File

@@ -1,777 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
* Contributor(s): Srilatha Moturi (srilatha@netscape.com)
* Contributor(s): Rajiv Dayal (rdayal@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#define MAPI_STARTUP_ARG "/MAPIStartUp"
#define MAPI_STARTUP_ARG "/MAPIStartUp"
#include <mapidefs.h>
#include <mapi.h>
#include <tchar.h>
#include "nsCOMPtr.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsISupports.h"
#include "nsIPromptService.h"
#include "nsAppShellCIDs.h"
#include "nsIDOMWindowInternal.h"
#include "nsIAppShellService.h"
#include "nsINativeAppSupport.h"
#include "nsICmdLineService.h"
#include "nsIProfileInternal.h"
#include "nsIMsgAccountManager.h"
#include "nsIDOMWindowInternal.h"
#include "nsXPIDLString.h"
#include "nsReadableUtils.h"
#include "nsMsgBaseCID.h"
#include "nsIStringBundle.h"
#include "nsIPref.h"
#include "nsString.h"
#include "nsIMsgAttachment.h"
#include "nsIMsgCompFields.h"
#include "nsIMsgComposeParams.h"
#include "nsIMsgCompose.h"
#include "nsMsgCompCID.h"
#include "nsIMsgSend.h"
#include "nsIProxyObjectManager.h"
#include "nsIMsgComposeService.h"
#include "nsProxiedService.h"
#include "nsSpecialSystemDirectory.h"
#include "nsMsgI18N.h"
#include "msgMapi.h"
#include "msgMapiHook.h"
#include "msgMapiSupport.h"
#include "msgMapiMain.h"
#include "nsNetUtil.h"
static NS_DEFINE_CID(kCmdLineServiceCID, NS_COMMANDLINE_SERVICE_CID);
class nsMAPISendListener : public nsIMsgSendListener
{
public:
virtual ~nsMAPISendListener() { }
// nsISupports interface
NS_DECL_ISUPPORTS
/* void OnStartSending (in string aMsgID, in PRUint32 aMsgSize); */
NS_IMETHOD OnStartSending(const char *aMsgID, PRUint32 aMsgSize) { return NS_OK; }
/* void OnProgress (in string aMsgID, in PRUint32 aProgress, in PRUint32 aProgressMax); */
NS_IMETHOD OnProgress(const char *aMsgID, PRUint32 aProgress, PRUint32 aProgressMax) { return NS_OK;}
/* void OnStatus (in string aMsgID, in wstring aMsg); */
NS_IMETHOD OnStatus(const char *aMsgID, const PRUnichar *aMsg) { return NS_OK;}
/* void OnStopSending (in string aMsgID, in nsresult aStatus, in wstring aMsg, in nsIFileSpec returnFileSpec); */
NS_IMETHOD OnStopSending(const char *aMsgID, nsresult aStatus, const PRUnichar *aMsg,
nsIFileSpec *returnFileSpec) {
m_done = PR_TRUE;
HANDLE hEvent = CreateEvent (NULL, FALSE, FALSE, (LPCTSTR) MAPI_SENDCOMPLETE_EVENT) ;
SetEvent (hEvent) ;
CloseHandle (hEvent) ;
return NS_OK ;
}
/* void OnSendNotPerformed */
NS_IMETHOD OnSendNotPerformed(const char *aMsgID, nsresult aStatus)
{
return OnStopSending(aMsgID, aStatus, nsnull, nsnull) ;
}
/* void OnGetDraftFolderURI (); */
NS_IMETHOD OnGetDraftFolderURI(const char *aFolderURI) {return NS_OK;}
static nsresult CreateMAPISendListener( nsIMsgSendListener **ppListener);
PRBool IsDone() { return m_done ; }
protected :
nsMAPISendListener() {
NS_INIT_REFCNT();
m_done = PR_FALSE;
}
PRBool m_done;
};
NS_IMPL_THREADSAFE_ISUPPORTS1(nsMAPISendListener, nsIMsgSendListener)
nsresult nsMAPISendListener::CreateMAPISendListener( nsIMsgSendListener **ppListener)
{
NS_ENSURE_ARG_POINTER(ppListener) ;
*ppListener = new nsMAPISendListener();
if (! *ppListener)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*ppListener);
return NS_OK;
}
PRBool nsMapiHook::isMapiService = PR_FALSE;
PRBool nsMapiHook::Initialize()
{
nsresult rv;
nsCOMPtr<nsINativeAppSupport> native;
nsCOMPtr<nsICmdLineService> cmdLineArgs(do_GetService(kCmdLineServiceCID, &rv));
if (NS_FAILED(rv)) return PR_FALSE;
nsCOMPtr<nsIAppShellService> appShell (do_GetService( "@mozilla.org/appshell/appShellService;1", &rv));
if (NS_FAILED(rv)) return PR_FALSE;
rv = appShell->GetNativeAppSupport( getter_AddRefs( native ));
if (NS_FAILED(rv)) return PR_FALSE;
rv = native->EnsureProfile(cmdLineArgs);
if (NS_FAILED(rv)) return PR_FALSE;
return PR_TRUE;
}
void nsMapiHook::CleanUp()
{
// This routine will be fully implemented in future
// to cleanup mapi related stuff inside mozilla code.
}
PRBool nsMapiHook::DisplayLoginDialog(PRBool aLogin, PRUnichar **aUsername, \
PRUnichar **aPassword)
{
nsresult rv;
PRBool btnResult = PR_FALSE;
nsCOMPtr<nsIAppShellService> appShell(do_GetService( "@mozilla.org/appshell/appShellService;1", &rv));
if (NS_FAILED(rv) || !appShell) return PR_FALSE;
nsCOMPtr<nsIPromptService> dlgService(do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv));
if (NS_SUCCEEDED(rv) && dlgService)
{
nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
if (NS_FAILED(rv) || !bundleService) return PR_FALSE;
nsCOMPtr<nsIStringBundle> bundle;
rv = bundleService->CreateBundle(MAPI_PROPERTIES_CHROME, getter_AddRefs(bundle));
if (NS_FAILED(rv) || !bundle) return PR_FALSE;
nsCOMPtr<nsIStringBundle> brandBundle;
rv = bundleService->CreateBundle(
"chrome://global/locale/brand.properties",
getter_AddRefs(brandBundle));
if (NS_FAILED(rv)) return PR_FALSE;
nsXPIDLString brandName;
rv = brandBundle->GetStringFromName(
NS_LITERAL_STRING("brandShortName").get(),
getter_Copies(brandName));
if (NS_FAILED(rv)) return PR_FALSE;
nsXPIDLString loginTitle;
const PRUnichar *brandStrings[] = { brandName.get() };
NS_NAMED_LITERAL_STRING(loginTitlePropertyTag, "loginTitle");
const PRUnichar *dTitlePropertyTag = loginTitlePropertyTag.get();
rv = bundle->FormatStringFromName(dTitlePropertyTag, brandStrings, 1,
getter_Copies(loginTitle));
if (NS_FAILED(rv)) return PR_FALSE;
if (aLogin)
{
nsXPIDLString loginText;
rv = bundle->GetStringFromName(NS_LITERAL_STRING("loginTextwithName").get(),
getter_Copies(loginText));
if (NS_FAILED(rv) || !loginText) return PR_FALSE;
rv = dlgService->PromptUsernameAndPassword(nsnull, loginTitle,
loginText, aUsername, aPassword,
nsnull, PR_FALSE, &btnResult);
}
else
{
//nsString loginString;
nsXPIDLString loginText;
const PRUnichar *userNameStrings[] = { *aUsername };
NS_NAMED_LITERAL_STRING(loginTextPropertyTag, "loginText");
const PRUnichar *dpropertyTag = loginTextPropertyTag.get();
rv = bundle->FormatStringFromName(dpropertyTag, userNameStrings, 1,
getter_Copies(loginText));
if (NS_FAILED(rv)) return PR_FALSE;
rv = dlgService->PromptPassword(nsnull, loginTitle, loginText,
aPassword, nsnull, PR_FALSE, &btnResult);
}
}
return btnResult;
}
PRBool nsMapiHook::VerifyUserName(const PRUnichar *aUsername, char **aIdKey)
{
nsresult rv;
if (aUsername == nsnull)
return PR_FALSE;
nsCOMPtr<nsIMsgAccountManager> accountManager(do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv));
if (NS_FAILED(rv)) return PR_FALSE;
nsCOMPtr<nsISupportsArray> identities;
rv = accountManager->GetAllIdentities(getter_AddRefs(identities));
if (NS_FAILED(rv)) return PR_FALSE;
PRUint32 numIndentities;
identities->Count(&numIndentities);
for (PRUint32 i = 0; i < numIndentities; i++)
{
// convert supports->Identity
nsCOMPtr<nsISupports> thisSupports;
rv = identities->GetElementAt(i, getter_AddRefs(thisSupports));
if (NS_FAILED(rv)) continue;
nsCOMPtr<nsIMsgIdentity> thisIdentity(do_QueryInterface(thisSupports, &rv));
if (NS_SUCCEEDED(rv) && thisIdentity)
{
nsXPIDLCString email;
rv = thisIdentity->GetEmail(getter_Copies(email));
if (NS_FAILED(rv)) continue;
// get the username from the email and compare with the username
nsCAutoString aEmail(email.get());
PRInt32 index = aEmail.FindChar('@');
if (index != -1)
aEmail.Truncate(index);
if (nsDependentString(aUsername) == NS_ConvertASCIItoUCS2(aEmail)) // == overloaded
return NS_SUCCEEDED(thisIdentity->GetKey(aIdKey));
}
}
return PR_FALSE;
}
PRBool
nsMapiHook::IsBlindSendAllowed()
{
PRBool enabled = PR_FALSE;
PRBool warn = PR_TRUE;
nsCOMPtr<nsIPref> prefs = do_GetService(NS_PREF_CONTRACTID);
if (prefs) {
prefs->GetBoolPref(PREF_MAPI_WARN_PRIOR_TO_BLIND_SEND,&warn);
prefs->GetBoolPref(PREF_MAPI_BLIND_SEND_ENABLED,&enabled);
}
if (!enabled)
return PR_FALSE;
if (!warn)
return PR_TRUE; // Everything is okay.
nsresult rv;
nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
if (NS_FAILED(rv) || !bundleService) return PR_FALSE;
nsCOMPtr<nsIStringBundle> bundle;
rv = bundleService->CreateBundle(MAPI_PROPERTIES_CHROME, getter_AddRefs(bundle));
if (NS_FAILED(rv) || !bundle) return PR_FALSE;
nsXPIDLString warningMsg;
rv = bundle->GetStringFromName(NS_LITERAL_STRING("mapiBlindSendWarning").get(),
getter_Copies(warningMsg));
if (NS_FAILED(rv)) return PR_FALSE;
nsXPIDLString dontShowAgainMessage;
rv = bundle->GetStringFromName(NS_LITERAL_STRING("mapiBlindSendDontShowAgain").get(),
getter_Copies(dontShowAgainMessage));
if (NS_FAILED(rv)) return PR_FALSE;
nsCOMPtr<nsIPromptService> dlgService(do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv));
if (NS_FAILED(rv) || !dlgService) return PR_FALSE;
PRBool continueToWarn = PR_TRUE;
PRBool okayToContinue = PR_FALSE;
dlgService->ConfirmCheck(nsnull, nsnull, warningMsg, dontShowAgainMessage, &continueToWarn, &okayToContinue);
if (!continueToWarn && okayToContinue && prefs)
prefs->SetBoolPref(PREF_MAPI_WARN_PRIOR_TO_BLIND_SEND,PR_FALSE);
return okayToContinue;
}
// this is used for Send without UI
nsresult nsMapiHook::BlindSendMail (unsigned long aSession, nsIMsgCompFields * aCompFields)
{
nsresult rv = NS_OK ;
if (!IsBlindSendAllowed())
return NS_ERROR_FAILURE;
/** create nsIMsgComposeParams obj and other fields to populate it **/
// get parent window
nsCOMPtr<nsIAppShellService> appService = do_GetService( "@mozilla.org/appshell/appShellService;1", &rv);
if (NS_FAILED(rv)|| (!appService) ) return rv ;
nsCOMPtr<nsIDOMWindowInternal> hiddenWindow;
rv = appService->GetHiddenDOMWindow(getter_AddRefs(hiddenWindow));
if ( NS_FAILED(rv) ) return rv ;
// smtp password and Logged in used IdKey from MapiConfig (session obj)
nsMAPIConfiguration * pMapiConfig = nsMAPIConfiguration::GetMAPIConfiguration() ;
if (!pMapiConfig) return NS_ERROR_FAILURE ; // get the singelton obj
PRUnichar * password = pMapiConfig->GetPassword(aSession) ;
// password
nsCAutoString smtpPassword ;
smtpPassword.AssignWithConversion (password) ;
// Id key
char * MsgIdKey = pMapiConfig->GetIdKey(aSession) ;
// get the MsgIdentity for the above key using AccountManager
nsCOMPtr <nsIMsgAccountManager> accountManager = do_GetService (NS_MSGACCOUNTMANAGER_CONTRACTID) ;
if (NS_FAILED(rv) || (!accountManager) ) return rv ;
nsCOMPtr <nsIMsgIdentity> pMsgId ;
rv = accountManager->GetIdentity (MsgIdKey, getter_AddRefs(pMsgId)) ;
if (NS_FAILED(rv) ) return rv ;
// create a send listener to get back the send status
nsCOMPtr <nsIMsgSendListener> sendListener ;
rv = nsMAPISendListener::CreateMAPISendListener(getter_AddRefs(sendListener)) ;
if (NS_FAILED(rv) || (!sendListener) ) return rv;
// create the compose params object
nsCOMPtr<nsIMsgComposeParams> pMsgComposeParams (do_CreateInstance(NS_MSGCOMPOSEPARAMS_CONTRACTID, &rv));
if (NS_FAILED(rv) || (!pMsgComposeParams) ) return rv ;
// populate the compose params
pMsgComposeParams->SetType(nsIMsgCompType::New);
pMsgComposeParams->SetFormat(nsIMsgCompFormat::Default);
pMsgComposeParams->SetIdentity(pMsgId);
pMsgComposeParams->SetComposeFields(aCompFields);
pMsgComposeParams->SetSendListener(sendListener) ;
pMsgComposeParams->SetSmtpPassword(smtpPassword.get());
// create the nsIMsgCompose object to send the object
nsCOMPtr<nsIMsgCompose> pMsgCompose (do_CreateInstance(NS_MSGCOMPOSE_CONTRACTID, &rv));
if (NS_FAILED(rv) || (!pMsgCompose) ) return rv ;
/** initialize nsIMsgCompose, Send the message, wait for send completion response **/
rv = pMsgCompose->Initialize(hiddenWindow, pMsgComposeParams) ;
if (NS_FAILED(rv)) return rv ;
pMsgCompose->SendMsg(nsIMsgSend::nsMsgDeliverNow, pMsgId, nsnull) ;
if (NS_FAILED(rv)) return rv ;
// assign to interface pointer from nsCOMPtr to facilitate typecast below
nsIMsgSendListener * pSendListener = sendListener ;
// we need to wait here to make sure that we return only after send is completed
// so we will have a event loop here which will process the events till the Send IsDone.
nsCOMPtr<nsIEventQueueService> pEventQService = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv);
nsCOMPtr<nsIEventQueue> eventQueue;
pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,getter_AddRefs(eventQueue));
while ( !((nsMAPISendListener *) pSendListener)->IsDone() )
eventQueue->ProcessPendingEvents();
return rv ;
}
// this is used to populate comp fields with Unicode data
nsresult nsMapiHook::PopulateCompFields(lpnsMapiMessage aMessage,
nsIMsgCompFields * aCompFields)
{
nsresult rv = NS_OK ;
if (aMessage->lpOriginator)
{
PRUnichar * From = aMessage->lpOriginator->lpszAddress ;
aCompFields->SetFrom (From) ;
}
nsAutoString To ;
nsAutoString Cc ;
nsAutoString Bcc ;
nsAutoString Comma ;
Comma.AssignWithConversion(",");
if (aMessage->lpRecips)
{
for (int i=0 ; i < (int) aMessage->nRecipCount ; i++)
{
if (aMessage->lpRecips[i].lpszAddress)
{
switch (aMessage->lpRecips[i].ulRecipClass)
{
case MAPI_TO :
if (To.Length() > 0)
To += Comma ;
To += (PRUnichar *) aMessage->lpRecips[i].lpszAddress ;
break ;
case MAPI_CC :
if (Cc.Length() > 0)
Cc += Comma ;
Cc += (PRUnichar *) aMessage->lpRecips[i].lpszAddress ;
break ;
case MAPI_BCC :
if (Bcc.Length() > 0)
Bcc += Comma ;
Bcc += (PRUnichar *) aMessage->lpRecips[i].lpszAddress ;
break ;
}
}
}
}
// set To, Cc, Bcc
aCompFields->SetTo (To.get()) ;
aCompFields->SetCc (Cc.get()) ;
aCompFields->SetBcc (Bcc.get()) ;
// set subject
if (aMessage->lpszSubject)
{
PRUnichar * Subject = aMessage->lpszSubject ;
aCompFields->SetSubject(Subject) ;
}
// handle attachments as File URL
rv = HandleAttachments (aCompFields, aMessage->nFileCount, aMessage->lpFiles, PR_TRUE) ;
if (NS_FAILED(rv)) return rv ;
// set body
if (aMessage->lpszNoteText)
{
PRUnichar * Body = aMessage->lpszNoteText ;
rv = aCompFields->SetBody(Body) ;
}
#ifdef RAJIV_DEBUG
// testing what all was set in CompFields
printf ("To : %S \n", To.get()) ;
printf ("CC : %S \n", Cc.get() ) ;
printf ("BCC : %S \n", Bcc.get() ) ;
#endif
return rv ;
}
nsresult nsMapiHook::HandleAttachments (nsIMsgCompFields * aCompFields, PRInt32 aFileCount,
lpnsMapiFileDesc aFiles, BOOL aIsUnicode)
{
nsresult rv = NS_OK ;
nsCAutoString Attachments ;
nsCAutoString TempFiles ;
nsCOMPtr <nsILocalFile> pFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv) ;
if (NS_FAILED(rv) || (!pFile) ) return rv ;
for (int i=0 ; i < aFileCount ; i++)
{
if (aFiles[i].lpszPathName)
{
// check if attachment exists
if (aIsUnicode)
pFile->InitWithUnicodePath (aFiles[i].lpszPathName) ;
else
pFile->InitWithPath ((char *) aFiles[i].lpszPathName) ;
PRBool bExist ;
rv = pFile->Exists(&bExist) ;
if (NS_FAILED(rv) || (!bExist) ) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST ;
// create Msg attachment object
nsCOMPtr<nsIMsgAttachment> attachment = do_CreateInstance(NS_MSGATTACHMENT_CONTRACTID, &rv);
if (NS_FAILED(rv) || (!attachment) ) return rv ;
// set url
nsXPIDLCString pURL ;
NS_GetURLSpecFromFile(pFile, getter_Copies(pURL));
attachment->SetUrl(pURL) ;
if (aFiles[i].lpszFileName)
{
if (! aIsUnicode)
{
nsAutoString realFileName ;
realFileName.AssignWithConversion ((char *) aFiles[i].lpszFileName) ;
attachment->SetName(realFileName.get()) ;
// attachment->SetName( (nsDependentString(aFiles[i].lpszFileName)).get() );
}
else
attachment->SetName(aFiles[i].lpszFileName) ;
}
attachment->SetTemporary(PR_FALSE) ;
rv = aCompFields->AddAttachment (attachment);
}
}
return rv ;
}
// this is used to convert non Unicode data and then populate comp fields
nsresult nsMapiHook::PopulateCompFieldsWithConversion(lpnsMapiMessage aMessage,
nsIMsgCompFields * aCompFields)
{
nsresult rv = NS_OK ;
if (aMessage->lpOriginator)
{
nsAutoString From ;
From.AssignWithConversion((char *) aMessage->lpOriginator->lpszAddress);
aCompFields->SetFrom (From.get()) ;
}
nsAutoString To ;
nsAutoString Cc ;
nsAutoString Bcc ;
nsAutoString Comma ;
Comma.AssignWithConversion(",");
if (aMessage->lpRecips)
{
for (int i=0 ; i < (int) aMessage->nRecipCount ; i++)
{
if (aMessage->lpRecips[i].lpszAddress)
{
switch (aMessage->lpRecips[i].ulRecipClass)
{
case MAPI_TO :
if (To.Length() > 0)
To += Comma ;
To.AppendWithConversion ((char *) aMessage->lpRecips[i].lpszAddress);
break ;
case MAPI_CC :
if (Cc.Length() > 0)
Cc += Comma ;
Cc.AppendWithConversion ((char *) aMessage->lpRecips[i].lpszAddress);
break ;
case MAPI_BCC :
if (Bcc.Length() > 0)
Bcc += Comma ;
Bcc.AppendWithConversion ((char *) aMessage->lpRecips[i].lpszAddress) ;
break ;
}
}
}
}
// set To, Cc, Bcc
aCompFields->SetTo (To.get()) ;
aCompFields->SetCc (Cc.get()) ;
aCompFields->SetBcc (Bcc.get()) ;
nsCAutoString platformCharSet;
// set subject
if (aMessage->lpszSubject)
{
nsAutoString Subject ;
if (platformCharSet.IsEmpty())
platformCharSet.Assign(nsMsgI18NFileSystemCharset());
rv = ConvertToUnicode(platformCharSet.get(), (char *) aMessage->lpszSubject, Subject);
if (NS_FAILED(rv)) return rv ;
aCompFields->SetSubject(Subject.get()) ;
}
// handle attachments as File URL
rv = HandleAttachments (aCompFields, aMessage->nFileCount, aMessage->lpFiles, PR_FALSE) ;
if (NS_FAILED(rv)) return rv ;
// set body
if (aMessage->lpszNoteText)
{
nsAutoString Body ;
if (platformCharSet.IsEmpty())
platformCharSet.Assign(nsMsgI18NFileSystemCharset());
rv = ConvertToUnicode(platformCharSet.get(), (char *) aMessage->lpszNoteText, Body);
if (NS_FAILED(rv)) return rv ;
rv = aCompFields->SetBody(Body.get()) ;
}
#ifdef RAJIV_DEBUG
// testing what all was set in CompFields
printf ("To : %S \n", To.get()) ;
printf ("CC : %S \n", Cc.get() ) ;
printf ("BCC : %S \n", Bcc.get() ) ;
#endif
return rv ;
}
// this is used to populate the docs as attachments in the Comp fields for Send Documents
nsresult nsMapiHook::PopulateCompFieldsForSendDocs(nsIMsgCompFields * aCompFields, ULONG aFlags,
PRUnichar * aDelimChar, PRUnichar * aFilePaths)
{
nsAutoString strDelimChars ;
nsString strFilePaths;
nsresult rv = NS_OK ;
if (aFlags & MAPI_UNICODE)
{
if (aDelimChar)
strDelimChars.Assign (aDelimChar) ;
if (aFilePaths)
strFilePaths.Assign (aFilePaths) ;
}
else
{
if (aDelimChar)
strDelimChars.AssignWithConversion ((char*) aDelimChar) ;
if (aFilePaths)
strFilePaths.AssignWithConversion ((char *) aFilePaths) ;
}
// check for comma in filename
if (strDelimChars.Find (",") == kNotFound) // if comma is not in the delimiter specified by user
{
if (strFilePaths.Find(",") != kNotFound) // if comma found in filenames return error
return NS_ERROR_FILE_INVALID_PATH ;
}
nsCString Attachments ;
// only 1 file is to be sent, no delim specified
if ((!strDelimChars.Length()) && (strFilePaths.Length()>0))
{
nsCOMPtr <nsILocalFile> pFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv) ;
if (NS_FAILED(rv) || (!pFile) ) return rv ;
pFile->InitWithUnicodePath (strFilePaths.get()) ;
PRBool bExist ;
rv = pFile->Exists(&bExist) ;
if (NS_FAILED(rv) || (!bExist) ) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST ;
nsXPIDLCString pURL ;
NS_GetURLSpecFromFile(pFile, getter_Copies(pURL));
if (pURL)
Attachments.Assign(pURL) ;
// set attachments for comp field and return
rv = aCompFields->SetAttachments (Attachments.get());
return rv ;
}
// multiple files to be sent, delim specified
nsCOMPtr <nsILocalFile> pFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv) ;
if (NS_FAILED(rv) || (!pFile) ) return rv ;
PRInt32 offset = 0 ;
PRInt32 FilePathsLen = strFilePaths.Length() ;
if (FilePathsLen)
{
PRUnichar * newFilePaths = (PRUnichar *) strFilePaths.get() ;
while (offset != kNotFound)
{
nsString RemainingPaths ;
RemainingPaths.Assign(newFilePaths) ;
offset = RemainingPaths.Find (strDelimChars) ;
if (offset != kNotFound)
{
RemainingPaths.SetLength (offset) ;
if ((offset + strDelimChars.Length()) < FilePathsLen)
newFilePaths += offset + strDelimChars.Length() ;
}
pFile->InitWithUnicodePath (RemainingPaths.get()) ;
#ifdef RAJIV_DEBUG
printf ("File : %S \n", RemainingPaths.get()) ;
#endif
PRBool bExist ;
rv = pFile->Exists(&bExist) ;
if (NS_FAILED(rv) || (!bExist) ) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST ;
nsXPIDLCString pURL ;
NS_GetURLSpecFromFile(pFile, getter_Copies(pURL));
if (pURL)
{
if (Attachments.Length() > 0)
Attachments.Append(",") ;
Attachments.Append(pURL) ;
}
}
rv = aCompFields->SetAttachments (Attachments.get());
}
return rv ;
}
// this used for Send with UI
nsresult nsMapiHook::ShowComposerWindow (unsigned long aSession, nsIMsgCompFields * aCompFields)
{
nsresult rv = NS_OK ;
// create a send listener to get back the send status
nsCOMPtr <nsIMsgSendListener> sendListener ;
rv = nsMAPISendListener::CreateMAPISendListener(getter_AddRefs(sendListener)) ;
if (NS_FAILED(rv) || (!sendListener) ) return rv ;
// create the compose params object
nsCOMPtr<nsIMsgComposeParams> pMsgComposeParams (do_CreateInstance(NS_MSGCOMPOSEPARAMS_CONTRACTID, &rv));
if (NS_FAILED(rv) || (!pMsgComposeParams) ) return rv ;
// populate the compose params
pMsgComposeParams->SetType(nsIMsgCompType::New);
pMsgComposeParams->SetFormat(nsIMsgCompFormat::Default);
pMsgComposeParams->SetComposeFields(aCompFields);
pMsgComposeParams->SetSendListener(sendListener) ;
/** get the nsIMsgComposeService object to open the compose window **/
nsCOMPtr <nsIMsgComposeService> compService = do_GetService (NS_MSGCOMPOSESERVICE_CONTRACTID) ;
if (NS_FAILED(rv)|| (!compService) ) return rv ;
rv = compService->OpenComposeWindowWithParams(nsnull, pMsgComposeParams) ;
if (NS_FAILED(rv)) return rv ;
return rv ;
}

View File

@@ -1,66 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef MSG_MAPI_HOOK_H_
#define MSG_MAPI_HOOK_H_
#include "prtypes.h"
class nsMapiHook
{
public :
static PRBool Initialize();
static PRBool DisplayLoginDialog(PRBool aLogin, PRUnichar **aUsername,
PRUnichar **aPassword);
static PRBool VerifyUserName(const PRUnichar *aUsername, char **aIdKey);
static PRBool IsBlindSendAllowed () ;
static nsresult BlindSendMail (unsigned long aSession, nsIMsgCompFields * aCompFields) ;
static nsresult ShowComposerWindow (unsigned long aSession, nsIMsgCompFields * aCompFields) ;
static nsresult PopulateCompFields(lpnsMapiMessage aMessage, nsIMsgCompFields * aCompFields) ;
static nsresult PopulateCompFieldsWithConversion(lpnsMapiMessage aMessage,
nsIMsgCompFields * aCompFields) ;
static nsresult PopulateCompFieldsForSendDocs(nsIMsgCompFields * aCompFields,
ULONG aFlags, LPTSTR aDelimChar, LPTSTR aFilePaths) ;
static nsresult HandleAttachments (nsIMsgCompFields * aCompFields, PRInt32 aFileCount,
lpnsMapiFileDesc aFiles, BOOL aIsUnicode) ;
static void CleanUp();
static PRBool isMapiService;
};
#endif // MSG_MAPI_HOOK_H_

View File

@@ -1,266 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
* Contributor(s): Rajiv Dayal (rdayal@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <mapidefs.h>
#include <mapi.h>
#include "msgMapi.h"
#include "msgMapiImp.h"
#include "msgMapiFactory.h"
#include "msgMapiMain.h"
#include "nsMsgCompFields.h"
#include "msgMapiHook.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsISupports.h"
#include "nsMsgCompCID.h"
CMapiImp::CMapiImp()
: m_cRef(1)
{
m_Lock = PR_NewLock();
}
CMapiImp::~CMapiImp()
{
if (m_Lock)
PR_DestroyLock(m_Lock);
}
STDMETHODIMP CMapiImp::QueryInterface(const IID& aIid, void** aPpv)
{
if (aIid == IID_IUnknown)
{
*aPpv = static_cast<nsIMapi*>(this);
}
else if (aIid == IID_nsIMapi)
{
*aPpv = static_cast<nsIMapi*>(this);
}
else
{
*aPpv = nsnull;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*aPpv)->AddRef();
return S_OK;
}
STDMETHODIMP_(ULONG) CMapiImp::AddRef()
{
return PR_AtomicIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG) CMapiImp::Release()
{
PRInt32 temp;
temp = PR_AtomicDecrement(&m_cRef);
if (m_cRef == 0)
{
delete this;
return 0;
}
return temp;
}
STDMETHODIMP CMapiImp::IsValid()
{
return S_OK;
}
STDMETHODIMP CMapiImp::IsValidSession(unsigned long aSession)
{
nsMAPIConfiguration *pConfig = nsMAPIConfiguration::GetMAPIConfiguration();
if (pConfig && pConfig->IsSessionValid(aSession))
return S_OK;
return E_FAIL;
}
STDMETHODIMP CMapiImp::Initialize()
{
HRESULT hr = E_FAIL;
if (!m_Lock)
return E_FAIL;
PR_Lock(m_Lock);
// Initialize MAPI Configuration
nsMAPIConfiguration *pConfig = nsMAPIConfiguration::GetMAPIConfiguration();
if (pConfig != nsnull)
if (nsMapiHook::Initialize())
hr = S_OK;
PR_Unlock(m_Lock);
return hr;
}
STDMETHODIMP CMapiImp::Login(unsigned long aUIArg, LOGIN_PW_TYPE aLogin, LOGIN_PW_TYPE aPassWord,
unsigned long aFlags, unsigned long *aSessionId)
{
HRESULT hr = E_FAIL;
PRBool bNewSession = PR_FALSE;
char *id_key = nsnull;
if (aFlags & MAPI_NEW_SESSION)
bNewSession = PR_TRUE;
// Check For Profile Name
if (aLogin != nsnull && aLogin[0] != '\0')
{
if (nsMapiHook::VerifyUserName(aLogin, &id_key) == PR_FALSE)
{
*aSessionId = MAPI_E_LOGIN_FAILURE;
return hr;
}
}
// finally register(create) the session.
PRUint32 nSession_Id;
PRInt16 nResult = 0;
nsMAPIConfiguration *pConfig = nsMAPIConfiguration::GetMAPIConfiguration();
if (pConfig != nsnull)
nResult = pConfig->RegisterSession(aUIArg, aLogin, aPassWord,
(aFlags & MAPI_FORCE_DOWNLOAD), bNewSession,
&nSession_Id, id_key);
switch (nResult)
{
case -1 :
{
*aSessionId = MAPI_E_TOO_MANY_SESSIONS;
return hr;
}
case 0 :
{
*aSessionId = MAPI_E_INSUFFICIENT_MEMORY;
return hr;
}
default :
{
*aSessionId = nSession_Id;
break;
}
}
return S_OK;
}
STDMETHODIMP CMapiImp::SendMail( unsigned long aSession, lpnsMapiMessage aMessage,
short aRecipCount, lpnsMapiRecipDesc aRecips , short aFileCount, lpnsMapiFileDesc aFiles ,
unsigned long aFlags, unsigned long aReserved)
{
nsresult rv = NS_OK ;
// Assign the pointers in the aMessage struct to the array of Recips and Files
// recieved here from MS COM. These are used in BlindSendMail and ShowCompWin fns
aMessage->lpRecips = aRecips ;
aMessage->lpFiles = aFiles ;
/** create nsIMsgCompFields obj and populate it **/
nsCOMPtr<nsIMsgCompFields> pCompFields = do_CreateInstance(NS_MSGCOMPFIELDS_CONTRACTID, &rv) ;
if (NS_FAILED(rv) || (!pCompFields) ) return MAPI_E_INSUFFICIENT_MEMORY ;
if (aFlags & MAPI_UNICODE)
rv = nsMapiHook::PopulateCompFields(aMessage, pCompFields) ;
else
rv = nsMapiHook::PopulateCompFieldsWithConversion(aMessage, pCompFields) ;
if (NS_SUCCEEDED (rv))
{
// see flag to see if UI needs to be brought up
if (!(aFlags & MAPI_DIALOG))
{
rv = nsMapiHook::BlindSendMail(aSession, pCompFields);
}
else
{
rv = nsMapiHook::ShowComposerWindow(aSession, pCompFields);
}
}
return nsMAPIConfiguration::GetMAPIErrorFromNSError (rv) ;
}
STDMETHODIMP CMapiImp::SendDocuments( unsigned long aSession, LPTSTR aDelimChar,
LPTSTR aFilePaths, LPTSTR aFileNames, ULONG aFlags)
{
nsresult rv = NS_OK ;
/** create nsIMsgCompFields obj and populate it **/
nsCOMPtr<nsIMsgCompFields> pCompFields = do_CreateInstance(NS_MSGCOMPFIELDS_CONTRACTID, &rv) ;
if (NS_FAILED(rv) || (!pCompFields) ) return MAPI_E_INSUFFICIENT_MEMORY ;
if (aFilePaths)
{
rv = nsMapiHook::PopulateCompFieldsForSendDocs(pCompFields, aFlags, aDelimChar, aFilePaths) ;
}
if (NS_SUCCEEDED (rv))
rv = nsMapiHook::ShowComposerWindow(aSession, pCompFields);
return nsMAPIConfiguration::GetMAPIErrorFromNSError (rv) ;
}
STDMETHODIMP CMapiImp::Logoff (unsigned long aSession)
{
nsMAPIConfiguration *pConfig = nsMAPIConfiguration::GetMAPIConfiguration();
if (pConfig->UnRegisterSession((PRUint32)aSession))
return S_OK;
return E_FAIL;
}
STDMETHODIMP CMapiImp::CleanUp()
{
nsMapiHook::CleanUp();
return S_OK;
}

View File

@@ -1,92 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef MSG_MAPI_IMP_H
#define MSG_MAPI_IMP_H
#include <windows.h>
#include <mapi.h>
#include "msgMapi.h"
#include "nsXPIDLString.h"
#include "nspr.h"
const CLSID CLSID_CMapiImp = {0x29f458be, 0x8866, 0x11d5, {0xa3, 0xdd, 0x0, 0xb0, 0xd0, 0xf3, 0xba, 0xa7}};
// this class implements the MS COM interface nsIMapi that provides the methods
// called by mapi32.dll to perform the mail operations as specified by MAPI.
// These class methods in turn use the Mozilla Mail XPCOM interfaces to do so.
class CMapiImp : public nsIMapi
{
public :
// IUnknown
STDMETHODIMP QueryInterface(const IID& aIid, void** aPpv);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// Interface INsMapi
STDMETHODIMP Login(unsigned long aUIArg, LOGIN_PW_TYPE aLogin,
LOGIN_PW_TYPE aPassWord, unsigned long aFlags,
unsigned long *aSessionId);
STDMETHODIMP SendMail( unsigned long aSession, lpnsMapiMessage aMessage,
short aRecipCount, lpnsMapiRecipDesc aRecips ,
short aFileCount, lpnsMapiFileDesc aFiles ,
unsigned long aFlags, unsigned long aReserved) ;
STDMETHODIMP SendDocuments( unsigned long aSession, LPTSTR aDelimChar,
LPTSTR aFilePaths, LPTSTR aFileNames, ULONG aFlags);
STDMETHODIMP Initialize();
STDMETHODIMP IsValid();
STDMETHODIMP IsValidSession(unsigned long aSession);
STDMETHODIMP Logoff (unsigned long aSession);
STDMETHODIMP CleanUp();
CMapiImp();
~CMapiImp();
private :
PRLock *m_Lock;
PRInt32 m_cRef;
};
#endif // MSG_MAPI_IMP_H

View File

@@ -1,376 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <mapidefs.h>
#include <mapi.h>
#include "msgCore.h"
#include "nsMsgComposeStringBundle.h"
#include "msgMapiMain.h"
#include "nsIServiceManager.h"
#include "nsCOMPtr.h"
// move to xpcom bug 81956.
class nsPRUintKey : public nsHashKey {
protected:
PRUint32 mKey;
public:
nsPRUintKey(PRUint32 key) : mKey(key) {}
PRUint32 HashCode(void) const {
return mKey;
}
PRBool Equals(const nsHashKey *aKey) const {
return mKey == ((const nsPRUintKey *) aKey)->mKey;
}
nsHashKey *Clone() const {
return new nsPRUintKey(mKey);
}
PRUint32 GetValue() { return mKey; }
};
//
nsMAPIConfiguration *nsMAPIConfiguration::m_pSelfRef = nsnull;
PRUint32 nsMAPIConfiguration::session_generator = 0;
PRUint32 nsMAPIConfiguration::sessionCount = 0;
nsMAPIConfiguration *nsMAPIConfiguration::GetMAPIConfiguration()
{
if (m_pSelfRef == nsnull)
m_pSelfRef = new nsMAPIConfiguration();
return m_pSelfRef;
}
nsMAPIConfiguration::nsMAPIConfiguration()
: m_nMaxSessions(MAX_SESSIONS)
{
m_Lock = PR_NewLock();
}
static PRBool
FreeSessionMapEntries(nsHashKey *aKey, void *aData, void* aClosure)
{
nsMAPISession *pTemp = (nsMAPISession*) aData;
if (pTemp)
{
delete pTemp;
pTemp = nsnull;
}
return PR_TRUE;
}
static PRBool
FreeProfileMapEntries(nsHashKey *aKey, void *aData, void* aClosure)
{
return PR_TRUE;
}
nsMAPIConfiguration::~nsMAPIConfiguration()
{
if (m_Lock)
PR_DestroyLock(m_Lock);
m_SessionMap.Reset(FreeSessionMapEntries);
m_ProfileMap.Reset(FreeProfileMapEntries);
}
void nsMAPIConfiguration::OpenConfiguration()
{
// No. of max. sessions is set to MAX_SESSIONS. In future
// if it is decided to have configuration (registry)
// parameter, this function can be used to set the
// max sessions;
return;
}
PRInt16 nsMAPIConfiguration::RegisterSession(PRUint32 aHwnd,
const PRUnichar *aUserName, const PRUnichar *aPassword,
PRBool aForceDownLoad, PRBool aNewSession,
PRUint32 *aSession, char *aIdKey)
{
PRInt16 nResult = 0;
PRUint32 n_SessionId = 0;
PR_Lock(m_Lock);
// Check whether max sessions is exceeded
if (sessionCount >= m_nMaxSessions)
{
PR_Unlock(m_Lock);
return -1;
}
if (aUserName != nsnull && aUserName[0] != '\0')
{
nsStringKey usernameKey(aUserName);
n_SessionId = (PRUint32) m_ProfileMap.Get(&usernameKey);
}
// try to share a session; if not create a session
if (n_SessionId > 0)
{
nsPRUintKey sessionKey(n_SessionId);
nsMAPISession *pTemp = (nsMAPISession *)m_SessionMap.Get(&sessionKey);
if (pTemp != nsnull)
{
pTemp->IncrementSession();
*aSession = n_SessionId;
nResult = 1;
}
}
else if (aNewSession || n_SessionId == 0) // checking for n_SessionId is a concession
{
// create a new session ; if new session is specified OR there is no session
nsMAPISession *pTemp = nsnull;
pTemp = new nsMAPISession(aHwnd, aUserName,
aPassword, aForceDownLoad, aIdKey);
if (pTemp != nsnull)
{
session_generator++;
// I don't think there will be (2 power 32) sessions alive
// in a cycle. This is an assumption
if (session_generator == 0)
session_generator++;
nsPRUintKey sessionKey(session_generator);
m_SessionMap.Put(&sessionKey, pTemp);
if (aUserName != nsnull && aUserName[0] != '\0')
{
nsStringKey usernameKey(aUserName);
m_ProfileMap.Put(&usernameKey, (void*)session_generator);
}
*aSession = session_generator;
sessionCount++;
nResult = 1;
}
}
PR_Unlock(m_Lock);
return nResult;
}
PRBool nsMAPIConfiguration::UnRegisterSession(PRUint32 aSessionID)
{
PRBool bResult = PR_FALSE;
PR_Lock(m_Lock);
if (aSessionID != 0)
{
nsPRUintKey sessionKey(aSessionID);
nsMAPISession *pTemp = (nsMAPISession *)m_SessionMap.Get(&sessionKey);
if (pTemp != nsnull)
{
if (pTemp->DecrementSession() == 0)
{
if (pTemp->m_pProfileName.get() != nsnull)
{
nsStringKey stringKey(pTemp->m_pProfileName.get());
m_ProfileMap.Remove(&stringKey);
}
m_SessionMap.Remove(&sessionKey);
sessionCount--;
bResult = PR_TRUE;
}
}
}
PR_Unlock(m_Lock);
return bResult;
}
PRBool nsMAPIConfiguration::IsSessionValid(PRUint32 aSessionID)
{
if (aSessionID == 0)
return PR_FALSE;
PRBool retValue = PR_FALSE;
nsPRUintKey sessionKey(aSessionID);
PR_Lock(m_Lock);
retValue = m_SessionMap.Exists(&sessionKey);
PR_Unlock(m_Lock);
return retValue;
}
PRUnichar *nsMAPIConfiguration::GetPassword(PRUint32 aSessionID)
{
PRUnichar *pResult = nsnull;
PR_Lock(m_Lock);
if (aSessionID != 0)
{
nsPRUintKey sessionKey(aSessionID);
nsMAPISession *pTemp = (nsMAPISession *)m_SessionMap.Get(&sessionKey);
if (pTemp)
{
pResult = pTemp->GetPassword();
}
}
PR_Unlock(m_Lock);
return pResult;
}
char *nsMAPIConfiguration::GetIdKey(PRUint32 aSessionID)
{
char *pResult = nsnull;
PR_Lock(m_Lock);
if (aSessionID != 0)
{
nsPRUintKey sessionKey(aSessionID);
nsMAPISession *pTemp = (nsMAPISession *)m_SessionMap.Get(&sessionKey);
if (pTemp)
{
pResult = pTemp->GetIdKey();
}
}
PR_Unlock(m_Lock);
return pResult;
}
// util func
HRESULT nsMAPIConfiguration::GetMAPIErrorFromNSError (nsresult res)
{
HRESULT hr = SUCCESS_SUCCESS ;
if (NS_SUCCEEDED (hr)) return hr ;
// if failure return the related MAPI failure code
switch (res)
{
case NS_MSG_NO_RECIPIENTS :
hr = MAPI_E_BAD_RECIPTYPE ;
break ;
case NS_ERROR_COULD_NOT_GET_USERS_MAIL_ADDRESS :
hr = MAPI_E_INVALID_RECIPS ;
break ;
case NS_ERROR_COULD_NOT_LOGIN_TO_SMTP_SERVER :
hr = MAPI_E_LOGIN_FAILURE ;
break ;
case NS_MSG_UNABLE_TO_OPEN_FILE :
case NS_MSG_UNABLE_TO_OPEN_TMP_FILE :
case NS_MSG_COULDNT_OPEN_FCC_FOLDER :
case NS_ERROR_FILE_INVALID_PATH :
hr = MAPI_E_ATTACHMENT_OPEN_FAILURE ;
break ;
case NS_ERROR_FILE_TARGET_DOES_NOT_EXIST :
hr = MAPI_E_ATTACHMENT_NOT_FOUND ;
break ;
case NS_MSG_CANCELLING :
hr = MAPI_E_USER_ABORT ;
break ;
case NS_MSG_ERROR_WRITING_FILE :
case NS_MSG_UNABLE_TO_SAVE_TEMPLATE :
case NS_MSG_UNABLE_TO_SAVE_DRAFT :
hr = MAPI_E_ATTACHMENT_WRITE_FAILURE ;
break ;
default :
hr = MAPI_E_FAILURE ;
break ;
}
return hr ;
}
nsMAPISession::nsMAPISession(PRUint32 aHwnd, const PRUnichar *aUserName,\
const PRUnichar *aPassword, \
PRBool aForceDownLoad, char *aKey)
: m_bIsForcedDownLoad(aForceDownLoad),
m_hAppHandle(aHwnd),
m_nShared(1),
m_pIdKey(aKey)
{
m_pProfileName.Assign(aUserName);
m_pPassword.Assign(aPassword);
}
nsMAPISession::~nsMAPISession()
{
if (m_pIdKey != nsnull)
{
delete [] m_pIdKey;
m_pIdKey = nsnull;
}
}
PRUint32 nsMAPISession::IncrementSession()
{
return ++m_nShared;
}
PRUint32 nsMAPISession::DecrementSession()
{
return --m_nShared;
}
PRUint32 nsMAPISession::GetSessionCount()
{
return m_nShared;
}
PRUnichar *nsMAPISession::GetPassword()
{
return (PRUnichar *)m_pPassword.get();
}
char *nsMAPISession::GetIdKey()
{
return m_pIdKey;
}

View File

@@ -1,112 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef MSG_MAPI_MAIN_H_
#define NSG_MAPI_MAIN_H_
#define MAX_NAME_LEN 256
#define MAX_PW_LEN 256
#define MAX_SESSIONS 50
#define MAPI_SENDCOMPLETE_EVENT "SendCompletionEvent"
#define MAPI_PROPERTIES_CHROME "chrome://messenger-mapi/locale/mapi.properties"
#define PREF_MAPI_WARN_PRIOR_TO_BLIND_SEND "mapi.blind-send.warn"
#define PREF_MAPI_BLIND_SEND_ENABLED "mapi.blind-send.enabled"
#include "nsXPIDLString.h"
#include "nspr.h"
#include "nsString.h"
#include "nsHashtable.h"
class nsMAPIConfiguration
{
private :
static PRUint32 session_generator;
static PRUint32 sessionCount;
static nsMAPIConfiguration *m_pSelfRef;
PRLock *m_Lock;
PRUint32 m_nMaxSessions;
nsHashtable m_ProfileMap;
nsHashtable m_SessionMap;
nsMAPIConfiguration();
public :
static nsMAPIConfiguration *GetMAPIConfiguration();
void OpenConfiguration();
PRInt16 RegisterSession(PRUint32 aHwnd, const PRUnichar *aUserName, \
const PRUnichar *aPassword, PRBool aForceDownLoad, \
PRBool aNewSession, PRUint32 *aSession, char *aIdKey);
PRBool IsSessionValid(PRUint32 aSessionID);
PRBool UnRegisterSession(PRUint32 aSessionID);
PRUnichar *GetPassword(PRUint32 aSessionID);
char *GetIdKey(PRUint32 aSessionID);
~nsMAPIConfiguration();
// a util func
static HRESULT GetMAPIErrorFromNSError (nsresult res) ;
};
class nsMAPISession
{
friend class nsMAPIConfiguration;
private :
PRBool m_bIsForcedDownLoad;
PRBool m_bApp_or_Service;
PRUint32 m_hAppHandle;
PRUint32 m_nShared;
char *m_pIdKey;
nsString m_pProfileName;
nsString m_pPassword;
public :
nsMAPISession(PRUint32 aHwnd, const PRUnichar *aUserName, \
const PRUnichar *aPassword, \
PRBool aForceDownLoad, char *aKey);
PRUint32 IncrementSession();
PRUint32 DecrementSession();
PRUint32 GetSessionCount();
PRUnichar *nsMAPISession::GetPassword();
char *nsMAPISession::GetIdKey();
~nsMAPISession();
};
#endif // MSG_MAPI_MAIN_H_

View File

@@ -1,209 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "objbase.h"
#include "nsISupports.h"
#include "nsIGenericFactory.h"
#include "nsIObserverService.h"
#include "nsIAppStartupNotifier.h"
#include "nsIServiceManager.h"
#include "nsIComponentManager.h"
#include "nsICategoryManager.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsIPrefBranchInternal.h"
#include "msgMapiSupport.h"
#include "nsMapiRegistryUtils.h"
#include "nsMapiRegistry.h"
#include "msgMapiImp.h"
/** Implementation of the nsIMapiSupport interface.
* Use standard implementation of nsISupports stuff.
*/
NS_IMPL_THREADSAFE_ISUPPORTS2(nsMapiSupport, nsIMapiSupport, nsIObserver);
static NS_METHOD nsMapiRegistrationProc(nsIComponentManager *aCompMgr,
nsIFile *aPath, const char *registryLocation, const char *componentType,
const nsModuleComponentInfo *info)
{
nsresult rv;
nsCOMPtr<nsICategoryManager> categoryManager(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
if (NS_SUCCEEDED(rv))
rv = categoryManager->AddCategoryEntry(APPSTARTUP_CATEGORY, "Mapi Support",
"service," NS_IMAPISUPPORT_CONTRACTID, PR_TRUE, PR_TRUE, nsnull);
return rv ;
}
NS_IMETHODIMP
nsMapiSupport::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)
{
nsresult rv = NS_OK ;
if (!nsCRT::strcmp(aTopic, "profile-after-change"))
return InitializeMAPISupport();
if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID))
return ShutdownMAPISupport();
if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID))
{
nsCOMPtr<nsIPrefBranch> prefs = do_QueryInterface(aSubject, &rv);
if (NS_FAILED(rv)) return rv;
// which preference changed?
if (!nsCRT::strcmp(MAILNEWS_ALLOW_DEFAULT_MAIL_CLIENT, NS_ConvertUCS2toUTF8(aData).get()))
{
PRBool bIsDefault = PR_FALSE ;
rv = prefs->GetBoolPref(MAILNEWS_ALLOW_DEFAULT_MAIL_CLIENT, &bIsDefault);
if (NS_FAILED(rv)) return rv;
nsCOMPtr <nsIMapiRegistry> mapiRegistry = do_CreateInstance(NS_IMAPIREGISTRY_CONTRACTID, &rv) ;
if (NS_FAILED(rv)) return rv;
return mapiRegistry->SetIsDefaultMailClient(bIsDefault) ;
}
return rv ;
}
nsCOMPtr<nsIObserverService> observerService(do_GetService("@mozilla.org/observer-service;1", &rv));
if (NS_FAILED(rv)) return rv;
rv = observerService->AddObserver(this,"profile-after-change", PR_FALSE);
if (NS_FAILED(rv)) return rv;
rv = observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIPrefBranchInternal> prefInternal = do_QueryInterface(prefs, &rv);
if (NS_FAILED(rv)) return rv;
rv = prefInternal->AddObserver(MAILNEWS_ALLOW_DEFAULT_MAIL_CLIENT, this, PR_FALSE);
if (NS_FAILED(rv)) return rv;
return rv;
}
nsMapiSupport::nsMapiSupport()
: m_dwRegister(0),
m_nsMapiFactory(nsnull)
{
NS_INIT_ISUPPORTS();
}
nsMapiSupport::~nsMapiSupport()
{
}
NS_IMETHODIMP
nsMapiSupport::InitializeMAPISupport()
{
::CoInitialize(nsnull) ;
if (m_nsMapiFactory == nsnull) // No Registering if already done. Sanity Check!!
{
m_nsMapiFactory = new CMapiFactory();
if (m_nsMapiFactory != nsnull)
{
HRESULT hr = ::CoRegisterClassObject(CLSID_CMapiImp, \
m_nsMapiFactory, \
CLSCTX_LOCAL_SERVER, \
REGCLS_MULTIPLEUSE, \
&m_dwRegister);
if (FAILED(hr))
{
m_nsMapiFactory->Release() ;
m_nsMapiFactory = nsnull;
return NS_ERROR_FAILURE;
}
}
}
return NS_OK;
}
NS_IMETHODIMP
nsMapiSupport::ShutdownMAPISupport()
{
if (m_dwRegister != 0)
::CoRevokeClassObject(m_dwRegister);
if (m_nsMapiFactory != nsnull)
{
m_nsMapiFactory->Release();
m_nsMapiFactory = nsnull;
}
::CoUninitialize();
return NS_OK ;
}
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMapiRegistry);
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMapiSupport);
// The list of components we register
static nsModuleComponentInfo components[] =
{
{
NS_IMAPIREGISTRY_CLASSNAME,
NS_IMAPIREGISTRY_CID,
NS_IMAPIREGISTRY_CONTRACTID,
nsMapiRegistryConstructor
},
{
NS_IMAPISUPPORT_CLASSNAME,
NS_IMAPISUPPORT_CID,
NS_IMAPISUPPORT_CONTRACTID,
nsMapiSupportConstructor,
nsMapiRegistrationProc,
nsnull
}
};
NS_IMPL_NSGETMODULE(msgMapiModule, components);

View File

@@ -1,66 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla
*
* The Initial Developer of the Original Code is
# Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Krishna Mohan Khandrika (kkhandrika@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef MSG_MAPI_SUPPORT_H_
#define MSG_MAPI_SUPPORT_H_
#include "nsIObserver.h"
#include "nsIMapiSupport.h"
#include "msgMapiFactory.h"
#define NS_IMAPISUPPORT_CID \
{0x8967fed2, 0xc8bb, 0x11d5, \
{ 0xa3, 0xe9, 0x00, 0xb0, 0xd0, 0xf3, 0xba, 0xa7 }}
class nsMapiSupport : public nsIMapiSupport,
public nsIObserver
{
public :
nsMapiSupport();
~nsMapiSupport();
// Declare all interface methods we must implement.
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSIMAPISUPPORT
private :
DWORD m_dwRegister;
CMapiFactory *m_nsMapiFactory;
};
#endif // MSG_MAPI_SUPPORT_H_

View File

@@ -1,167 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Srilatha Moturi <srilatha@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIServiceManager.h"
#include "nsXPIDLString.h"
#include "nsIPromptService.h"
#include "nsIProxyObjectManager.h"
#include "nsProxiedService.h"
#include "nsMapiRegistryUtils.h"
#include "nsMapiRegistry.h"
static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
/** Implementation of the nsIMapiRegistry interface.
* Use standard implementation of nsISupports stuff.
*/
NS_IMPL_ISUPPORTS1(nsMapiRegistry, nsIMapiRegistry);
nsMapiRegistry::nsMapiRegistry() {
NS_INIT_ISUPPORTS();
m_ShowDialog = ! m_registryUtils.verifyRestrictedAccess();
m_DefaultMailClient = m_registryUtils.IsDefaultMailClient();
}
nsMapiRegistry::~nsMapiRegistry() {
}
NS_IMETHODIMP
nsMapiRegistry::GetIsDefaultMailClient(PRBool * retval) {
// we need to get the value from registry everytime
// because the registry settings can be changed from
// other mail applications.
*retval = m_registryUtils.IsDefaultMailClient();
return NS_OK;
}
NS_IMETHODIMP
nsMapiRegistry::GetShowDialog(PRBool * retval) {
*retval = m_ShowDialog;
return NS_OK;
}
NS_IMETHODIMP
nsMapiRegistry::SetIsDefaultMailClient(PRBool aIsDefaultMailClient)
{
nsresult rv = NS_OK ;
if (aIsDefaultMailClient)
{
rv = m_registryUtils.setDefaultMailClient();
if (NS_SUCCEEDED(rv))
m_DefaultMailClient = PR_TRUE;
else
m_registryUtils.ShowMapiErrorDialog();
}
else
{
rv = m_registryUtils.unsetDefaultMailClient();
if (NS_SUCCEEDED(rv))
m_DefaultMailClient = PR_FALSE;
else
m_registryUtils.ShowMapiErrorDialog();
}
return rv ;
}
/** This will bring up the dialog box only once per session and
* only if the current app is not default Mail Client.
* This also checks the registry if the registry key
* showMapiDialog is set
*/
NS_IMETHODIMP
nsMapiRegistry::ShowMailIntegrationDialog(nsIDOMWindow *aParentWindow) {
nsresult rv;
if (!m_ShowDialog || !m_registryUtils.getShowDialog()) return NS_OK;
nsCOMPtr<nsIPromptService> promptService(do_GetService(
"@mozilla.org/embedcomp/prompt-service;1", &rv));
if (NS_SUCCEEDED(rv) && promptService)
{
nsCOMPtr<nsIStringBundle> bundle;
rv = m_registryUtils.MakeMapiStringBundle (getter_AddRefs (bundle)) ;
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsXPIDLString dialogTitle;
const PRUnichar *brandStrings[] = { m_registryUtils.brandName() };
NS_NAMED_LITERAL_STRING(dialogTitlePropertyTag, "dialogTitle");
rv = bundle->FormatStringFromName(dialogTitlePropertyTag.get(),
brandStrings, 1,
getter_Copies(dialogTitle));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsXPIDLString dialogText;
NS_NAMED_LITERAL_STRING(dialogTextPropertyTag, "dialogText");
rv = bundle->FormatStringFromName(dialogTextPropertyTag.get(),
brandStrings, 1,
getter_Copies(dialogText));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsXPIDLString checkboxText;
rv = bundle->GetStringFromName(
NS_LITERAL_STRING("checkboxText").get(),
getter_Copies(checkboxText));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
PRBool checkValue = PR_FALSE;
PRInt32 buttonPressed = 0;
rv = promptService->ConfirmEx(aParentWindow,
dialogTitle,
dialogText.get(),
(nsIPromptService::BUTTON_TITLE_YES *
nsIPromptService::BUTTON_POS_0) +
(nsIPromptService::BUTTON_TITLE_NO *
nsIPromptService::BUTTON_POS_1),
nsnull,
nsnull,
nsnull,
checkboxText,
&checkValue,
&buttonPressed);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
rv = m_registryUtils.SetRegistryKey(HKEY_LOCAL_MACHINE, "Software\\Mozilla\\Desktop",
"showMapiDialog", (checkValue) ? "0" : "1");
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
m_ShowDialog = PR_FALSE;
if (!buttonPressed)
rv = SetIsDefaultMailClient(PR_TRUE) ; // SetDefaultMailClient();
}
return rv;
}

View File

@@ -1,76 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Srilatha Moturi <srilatha@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsmapiregistry_h____
#define nsmapiregistry_h____
#include "nsIMapiRegistry.h"
#ifndef MAX_BUF
#define MAX_BUF 4096
#endif
/* c5be14ba-4e0a-4eec-a1b8-04363761d63c */
#define NS_IMAPIREGISTRY_CID \
{ 0xc5be14ba, 0x4e0a, 0x4eec, {0xa1, 0xb8, 0x04, 0x36, 0x37, 0x61, 0xd6, 0x3c} }
#define NS_IMAPIREGISTRY_CONTRACTID "@mozilla.org/mapiregistry;1"
#define NS_IMAPIREGISTRY_CLASSNAME "Mozilla MAPI Registry"
#define MAILNEWS_ALLOW_DEFAULT_MAIL_CLIENT "mailnews.default_mail_client"
class nsMapiRegistry : public nsIMapiRegistry {
public:
// ctor/dtor
nsMapiRegistry();
virtual ~nsMapiRegistry();
// Declare all interface methods we must implement.
NS_DECL_ISUPPORTS
NS_DECL_NSIMAPIREGISTRY
protected:
PRBool m_DefaultMailClient;
PRBool m_ShowDialog;
nsMapiRegistryUtils m_registryUtils ;
private:
// Special member to handle initialization.
PRBool mHaveBeenSet;
}; // nsMapiRegistry
#endif // nsmapiregistry_h____

View File

@@ -1,743 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Srilatha Moturi <srilatha@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#undef UNICODE
#undef _UNICODE
#include "nsIServiceManager.h"
#include "msgMapiImp.h"
#include "msgMapiMain.h"
#include "nsMapiRegistryUtils.h"
#include "nsString.h"
#include "nsIStringBundle.h"
#include "nsIPromptService.h"
#include "nsXPIDLString.h"
#include "nsSpecialSystemDirectory.h"
#include "nsDirectoryService.h"
#include "nsDirectoryServiceDefs.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsIPref.h"
static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
#define EXE_EXTENSION ".exe"
#define USERAGENT_VERSION_PREF "general.useragent.misc"
#define USERAGENT_VERSION_NS_PREF "general.useragent.vendorSub"
#define USERAGENT_PREF_PREFIX "rv:"
nsMapiRegistryUtils::nsMapiRegistryUtils()
{
m_mapiStringBundle = nsnull ;
}
const char * nsMapiRegistryUtils::thisApplication()
{
if (m_thisApp.IsEmpty()) {
char buffer[MAX_PATH] = {0};
DWORD len = ::GetModuleFileName(NULL, buffer, MAX_PATH);
if (!len) return nsnull ;
char shortPathBuf[MAX_PATH] = {0};
len = ::GetShortPathName(buffer, shortPathBuf, MAX_PATH);
if (!len) return nsnull ;
m_thisApp = buffer;
m_thisApp.ToUpperCase();
}
return m_thisApp.get() ;
}
const PRUnichar * nsMapiRegistryUtils::brandName()
{
nsresult rv;
if (m_brand.IsEmpty()) {
nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(
kStringBundleServiceCID, &rv));
if (NS_SUCCEEDED(rv) && bundleService) {
nsCOMPtr<nsIStringBundle> brandBundle;
rv = bundleService->CreateBundle(
"chrome://global/locale/brand.properties",
getter_AddRefs(brandBundle));
if (NS_SUCCEEDED(rv)) {
nsXPIDLString brandName;
rv = brandBundle->GetStringFromName(
NS_LITERAL_STRING("brandShortName").get(),
getter_Copies(brandName));
if (NS_SUCCEEDED(rv)) {
m_brand = brandName ;
}
}
}
}
return m_brand.get() ;
}
const PRUnichar * nsMapiRegistryUtils::versionNo()
{
if (!m_versionNo.IsEmpty())
return m_versionNo.get() ;
nsCOMPtr<nsIPref> prefs = do_GetService(NS_PREF_CONTRACTID);
if (prefs) {
nsXPIDLCString versionStr ;
nsresult rv = prefs->GetCharPref(USERAGENT_VERSION_NS_PREF, getter_Copies(versionStr));
if (NS_SUCCEEDED(rv) && versionStr)
m_versionNo.AssignWithConversion (versionStr.get()) ;
else {
rv = prefs->GetCharPref(USERAGENT_VERSION_PREF, getter_Copies(versionStr));
if (NS_SUCCEEDED(rv) && versionStr) {
m_versionNo.AssignWithConversion (versionStr.get()) ;
m_versionNo.StripChars (USERAGENT_PREF_PREFIX) ;
}
}
}
return m_versionNo.get() ;
}
PRBool nsMapiRegistryUtils::verifyRestrictedAccess() {
char subKey[] = "Software\\Mozilla - Test Key";
PRBool result = PR_FALSE;
DWORD dwDisp = 0;
HKEY key;
// Try to create/open a subkey under HKLM.
DWORD rc = ::RegCreateKeyEx(HKEY_LOCAL_MACHINE,
subKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&key,
&dwDisp);
if (rc == ERROR_SUCCESS) {
// Key was opened; first close it.
::RegCloseKey(key);
// Delete it if we just created it.
switch(dwDisp) {
case REG_CREATED_NEW_KEY:
::RegDeleteKey(HKEY_LOCAL_MACHINE, subKey);
break;
case REG_OPENED_EXISTING_KEY:
break;
}
} else {
// Can't create/open it; we don't have access.
result = PR_TRUE;
}
return result;
}
nsresult nsMapiRegistryUtils::SetRegistryKey(HKEY baseKey, const char * keyName,
const char * valueName, char * value)
{
nsresult result = NS_ERROR_FAILURE;
HKEY key;
LONG rc = ::RegCreateKey(baseKey, keyName, &key);
if (rc == ERROR_SUCCESS) {
rc = ::RegSetValueEx(key, valueName, NULL, REG_SZ,
(LPBYTE)(const char*)value, strlen(value));
if (rc == ERROR_SUCCESS) {
result = NS_OK;
}
::RegCloseKey(key);
}
return result;
}
nsresult nsMapiRegistryUtils::DeleteRegistryValue(HKEY baseKey, const char * keyName,
const char * valueName)
{
nsresult result = NS_ERROR_FAILURE;
HKEY key;
LONG rc = ::RegOpenKey(baseKey, keyName, &key);
if (rc == ERROR_SUCCESS) {
rc = ::RegDeleteValue(key, valueName);
if (rc == ERROR_SUCCESS)
result = NS_OK;
::RegCloseKey(key);
}
return result;
}
void nsMapiRegistryUtils::GetRegistryKey(HKEY baseKey, const char * keyName,
const char * valueName, nsCAutoString & value)
{
HKEY key;
LONG rc = ::RegOpenKey(baseKey, keyName, &key);
if (rc == ERROR_SUCCESS) {
char buffer[MAX_PATH] = {0};
DWORD len = sizeof buffer;
rc = ::RegQueryValueEx(key, valueName, NULL, NULL,
(LPBYTE)buffer, &len);
if (rc == ERROR_SUCCESS) {
if (len)
value = buffer;
}
::RegCloseKey(key);
}
}
PRBool nsMapiRegistryUtils::IsDefaultMailClient()
{
if (!isSmartDll() && !isMozDll())
return PR_FALSE;
nsCAutoString name;
GetRegistryKey(HKEY_LOCAL_MACHINE, "Software\\Clients\\Mail", "", name);
if (!name.IsEmpty()) {
nsCAutoString keyName("Software\\Clients\\Mail\\");
keyName += name.get();
keyName += "\\protocols\\mailto\\shell\\open\\command";
nsCAutoString result;
GetRegistryKey(HKEY_LOCAL_MACHINE, keyName.get(), "", result);
if (!result.IsEmpty()) {
nsCAutoString strExtension;
strExtension.Assign(EXE_EXTENSION);
result.ToUpperCase();
strExtension.ToUpperCase();
PRInt32 index = result.RFind(strExtension.get());
if (index != kNotFound) {
result.Truncate(index + strExtension.Length());
}
nsCAutoString thisApp (thisApplication()) ;
return (result == thisApp);
}
}
return PR_FALSE;
}
nsresult nsMapiRegistryUtils::saveDefaultMailClient()
{
nsresult rv;
nsCAutoString name ;
GetRegistryKey(HKEY_LOCAL_MACHINE,"Software\\Clients\\Mail", "", name);
if (!name.IsEmpty()) {
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"HKEY_LOCAL_MACHINE\\Software\\Clients\\Mail",
(char *)name.get());
if (NS_SUCCEEDED(rv)) {
nsCAutoString keyName("Software\\Clients\\Mail\\");
keyName += name.get();
keyName += "\\protocols\\mailto\\shell\\open\\command";
nsCAutoString appPath ;
GetRegistryKey(HKEY_LOCAL_MACHINE, keyName.get(), "", appPath);
if (!appPath.IsEmpty()) {
nsCAutoString stringName("HKEY_LOCAL_MACHINE\\");
stringName += keyName.get();
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
stringName.get(), (char *)appPath.get());
}
}
}
else
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"HKEY_LOCAL_MACHINE\\Software\\Clients\\Mail",
"");
return rv;
}
nsresult nsMapiRegistryUtils::saveUserDefaultMailClient()
{
nsresult rv;
nsCAutoString name ;
GetRegistryKey(HKEY_CURRENT_USER,"Software\\Clients\\Mail", "", name);
if (!name.IsEmpty()) {
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"HKEY_CURRENT_USER\\Software\\Clients\\Mail",
(char *)name.get());
}
else {
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"HKEY_CURRENT_USER\\Software\\Clients\\Mail",
"");
}
return rv;
}
/**
* Check whether it is a smart dll or not. Smart dll is the one installed by
* IE5 or Outlook Express which forwards the MAPI calls to the dll based on the
* registry key setttings.
* Returns TRUE if is a smart dll.
*/
typedef HRESULT (FAR PASCAL GetOutlookVersionFunc)();
PRBool nsMapiRegistryUtils::isSmartDll()
{
char buffer[MAX_PATH] = {0};
if (GetSystemDirectory(buffer, sizeof(buffer)) == 0)
return PR_FALSE;
PL_strcatn(buffer, sizeof(buffer), "\\Mapi32.dll");
HINSTANCE hInst;
GetOutlookVersionFunc *doesExist = nsnull;
hInst = LoadLibrary(buffer);
if (hInst == nsnull)
return PR_FALSE;
doesExist = (GetOutlookVersionFunc *) GetProcAddress (hInst, "GetOutlookVersion");
FreeLibrary(hInst);
return (doesExist != nsnull);
}
typedef HRESULT (FAR PASCAL GetMapiDllVersion)();
/**
* Checks whether mapi32.dll is installed by this app.
* Returns TRUE if it is.
*/
PRBool nsMapiRegistryUtils::isMozDll()
{
char buffer[MAX_PATH] = {0};
if (GetSystemDirectory(buffer, sizeof(buffer)) == 0)
return PR_FALSE;
PL_strcatn(buffer, sizeof(buffer), "\\Mapi32.dll");
HINSTANCE hInst;
GetMapiDllVersion *doesExist = nsnull;
hInst = LoadLibrary(buffer);
if (hInst == nsnull)
return PR_FALSE;
doesExist = (GetMapiDllVersion *) GetProcAddress (hInst, "GetMapiDllVersion");
FreeLibrary(hInst);
return (doesExist != nsnull);
}
/** Renames Mapi32.dl in system directory to Mapi32_moz_bak.dll
* copies the mozMapi32.dll from bin directory to the system directory
*/
nsresult nsMapiRegistryUtils::CopyMozMapiToWinSysDir()
{
nsresult rv;
char buffer[MAX_PATH] = {0};
if (GetSystemDirectory(buffer, sizeof(buffer)) == 0)
return NS_ERROR_FAILURE;
nsCAutoString filePath(buffer);
filePath.Append("\\Mapi32_moz_bak.dll");
nsCOMPtr<nsILocalFile> pCurrentMapiFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv);
if (NS_FAILED(rv) || !pCurrentMapiFile) return rv;
pCurrentMapiFile->InitWithPath(filePath.get());
nsCOMPtr<nsIFile> pMozMapiFile;
nsCOMPtr<nsIProperties> directoryService =
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
if (!directoryService) return NS_ERROR_FAILURE;
rv = directoryService->Get(NS_OS_CURRENT_PROCESS_DIR,
NS_GET_IID(nsIFile),
getter_AddRefs(pMozMapiFile));
if (NS_FAILED(rv)) return rv;
pMozMapiFile->Append("mozMapi32.dll");
PRBool bExist;
rv = pMozMapiFile->Exists(&bExist);
if (NS_FAILED(rv) || !bExist) return rv;
rv = pCurrentMapiFile->Exists(&bExist);
if (NS_SUCCEEDED(rv) && bExist)
{
rv = pCurrentMapiFile->Remove(PR_FALSE);
}
if (NS_FAILED(rv)) return rv;
filePath.Assign(buffer);
filePath.Append("\\Mapi32.dll");
pCurrentMapiFile->InitWithPath(filePath.get());
rv = pCurrentMapiFile->Exists(&bExist);
if (NS_SUCCEEDED(rv) && bExist)
{
rv = pCurrentMapiFile->MoveTo(nsnull, "Mapi32_moz_bak.dll");
if (NS_FAILED(rv)) return rv;
nsCAutoString fullFilePath(buffer);
fullFilePath.Append("\\Mapi32_moz_bak.dll");
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"Mapi_backup_dll",
(char *)fullFilePath.get());
if (NS_FAILED(rv)) {
RestoreBackedUpMapiDll();
return rv;
}
}
NS_NAMED_LITERAL_STRING(fileName, "Mapi32.dll");
filePath.Assign(buffer);
pCurrentMapiFile->InitWithPath(filePath.get());
rv = pMozMapiFile->CopyToUnicode(pCurrentMapiFile, fileName.get());
if (NS_FAILED(rv))
RestoreBackedUpMapiDll();
return rv;
}
/** deletes the Mapi32.dll in system directory and renames Mapi32_moz_bak.dll
* to Mapi32.dll
*/
nsresult nsMapiRegistryUtils::RestoreBackedUpMapiDll()
{
nsresult rv;
char buffer[MAX_PATH] = {0};
if (GetSystemDirectory(buffer, sizeof(buffer)) == 0)
return NS_ERROR_FAILURE;
nsCAutoString filePath(buffer);
nsCAutoString previousFileName(buffer);
filePath.Append("\\Mapi32.dll");
previousFileName.Append("\\Mapi32_moz_bak.dll");
nsCOMPtr <nsILocalFile> pCurrentMapiFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
if (NS_FAILED(rv) || !pCurrentMapiFile) return NS_ERROR_FAILURE;
pCurrentMapiFile->InitWithPath(filePath.get());
nsCOMPtr<nsILocalFile> pPreviousMapiFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv);
if (NS_FAILED(rv) || !pPreviousMapiFile) return NS_ERROR_FAILURE;
pPreviousMapiFile->InitWithPath(previousFileName.get());
PRBool bExist;
rv = pCurrentMapiFile->Exists(&bExist);
if (NS_SUCCEEDED(rv) && bExist) {
rv = pCurrentMapiFile->Remove(PR_FALSE);
if (NS_FAILED(rv)) return rv;
}
rv = pPreviousMapiFile->Exists(&bExist);
if (NS_SUCCEEDED(rv) && bExist)
rv = pPreviousMapiFile->MoveTo(nsnull, "Mapi32.dll");
if (NS_SUCCEEDED(rv))
DeleteRegistryValue(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"Mapi_backup_dll");
return rv;
}
/** Sets Mozilla as default Mail Client
*/
nsresult nsMapiRegistryUtils::setDefaultMailClient()
{
nsresult rv;
nsresult mailKeySet=NS_ERROR_FAILURE;
if (verifyRestrictedAccess()) return NS_ERROR_FAILURE;
if (!isSmartDll()) {
if (NS_FAILED(CopyMozMapiToWinSysDir())) return NS_ERROR_FAILURE;
}
rv = saveDefaultMailClient();
if (NS_FAILED(saveUserDefaultMailClient()) ||
NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsCAutoString keyName("Software\\Clients\\Mail\\");
nsCAutoString appName (NS_ConvertUCS2toUTF8(brandName()).get());
if (!appName.IsEmpty()) {
keyName.Append(appName.get());
nsCOMPtr<nsIStringBundle> bundle;
rv = MakeMapiStringBundle (getter_AddRefs (bundle)) ;
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsXPIDLString defaultMailTitle;
const PRUnichar *keyValuePrefixStr[] = { brandName(), versionNo() };
NS_NAMED_LITERAL_STRING(defaultMailTitleTag, "defaultMailDisplayTitle");
rv = bundle->FormatStringFromName(defaultMailTitleTag.get(),
keyValuePrefixStr, 2,
getter_Copies(defaultMailTitle));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
keyName.get(),
"", NS_CONST_CAST(char *, NS_ConvertUCS2toUTF8(defaultMailTitle).get()) ) ;
}
else
rv = NS_ERROR_FAILURE;
if (NS_SUCCEEDED(rv)) {
nsCAutoString thisApp (thisApplication()) ;
if (NS_FAILED(rv)) return rv ;
nsCAutoString dllPath (thisApp) ;
PRInt32 index = dllPath.RFind("\\");
if (index != kNotFound)
dllPath.Truncate(index + 1);
dllPath += "mozMapi32.dll";
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
keyName.get(), "DLLPath",
(char *)dllPath.get());
if (NS_SUCCEEDED(rv)) {
keyName.Append("\\protocols\\mailto");
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
keyName.get(),
"", "URL:MailTo Protocol");
if (NS_SUCCEEDED(rv)) {
nsCAutoString appPath (thisApp);
appPath += " \"%1\"";
keyName.Append("\\shell\\open\\command");
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
keyName.get(),
"", (char *)appPath.get());
if (NS_SUCCEEDED(rv)) {
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Clients\\Mail",
"", (char *)appName.get());
}
if (NS_SUCCEEDED(rv)) {
nsCAutoString mailAppPath(thisApp);
mailAppPath += " -mail";
nsCAutoString appKeyName ("Software\\Clients\\Mail\\");
appKeyName.Append(appName.get());
appKeyName.Append("\\shell\\open\\command");
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
appKeyName.get(),
"", (char *)mailAppPath.get());
}
if (NS_SUCCEEDED(rv)) {
nsCAutoString iconPath(thisApp);
iconPath += ",0";
nsCAutoString iconKeyName ("Software\\Clients\\Mail\\");
iconKeyName.Append(appName.get());
iconKeyName.Append("\\DefaultIcon");
mailKeySet = SetRegistryKey(HKEY_LOCAL_MACHINE,
iconKeyName.get(),
"", (char *)iconPath.get());
}
}
}
}
if (NS_SUCCEEDED(mailKeySet)) {
nsresult desktopKeySet = SetRegistryKey(HKEY_CURRENT_USER,
"Software\\Clients\\Mail",
"", (char *)appName.get());
if (NS_SUCCEEDED(desktopKeySet)) {
desktopKeySet = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"defaultMailHasBeenSet", "1");
}
::SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
(LPARAM)"Software\\Clients\\Mail");
RegisterServer(CLSID_CMapiImp, "Mozilla MAPI", "mozMapi", "mozMapi.1");
return desktopKeySet;
}
return mailKeySet;
}
/** Removes Mozilla as the default Mail client and restores the previous setting
*/
nsresult nsMapiRegistryUtils::unsetDefaultMailClient() {
nsresult result = NS_OK;
nsresult mailKeySet = NS_ERROR_FAILURE;
if (verifyRestrictedAccess()) return NS_ERROR_FAILURE;
if (!isSmartDll()) {
if (NS_FAILED(RestoreBackedUpMapiDll())) return NS_ERROR_FAILURE;
}
nsCAutoString name ;
GetRegistryKey(HKEY_LOCAL_MACHINE, "Software\\Mozilla\\Desktop",
"HKEY_LOCAL_MACHINE\\Software\\Clients\\Mail", name);
nsCAutoString appName (NS_ConvertUCS2toUTF8(brandName()).get());
if (!name.IsEmpty() && !appName.IsEmpty() && name.Equals(appName)) {
nsCAutoString keyName("HKEY_LOCAL_MACHINE\\Software\\Clients\\Mail\\");
keyName.Append(appName.get());
keyName.Append("\\protocols\\mailto\\shell\\open\\command");
nsCAutoString appPath ;
GetRegistryKey(HKEY_LOCAL_MACHINE, "Software\\Mozilla\\Desktop",
keyName.get(), appPath);
if (!appPath.IsEmpty()) {
keyName.Assign("Software\\Clients\\Mail\\");
keyName.Append(appName.get());
keyName.Append("\\protocols\\mailto\\shell\\open\\command");
result = SetRegistryKey(HKEY_LOCAL_MACHINE,
keyName.get(),
"", (char *)appPath.get());
if (NS_SUCCEEDED(result)) {
PRInt32 index = appPath.RFind("\\");
if (index != kNotFound)
appPath.Truncate(index + 1);
appPath += "mozMapi32.dll";
keyName.Assign("Software\\Clients\\Mail\\");
keyName.Append(appName.get());
result = SetRegistryKey(HKEY_LOCAL_MACHINE,
keyName.get(),
"DLLPath", (char *) appPath.get());
}
}
}
if (!name.IsEmpty()) {
if (NS_SUCCEEDED(result)) {
mailKeySet = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Clients\\Mail",
"", (char *)name.get());
}
}
else
mailKeySet = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Clients\\Mail",
"", "");
if (NS_SUCCEEDED(mailKeySet)) {
nsCAutoString userAppName ;
GetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"HKEY_CURRENT_USER\\Software\\Clients\\Mail", userAppName);
nsresult desktopKeySet = NS_OK;
if (!userAppName.IsEmpty()) {
desktopKeySet = SetRegistryKey(HKEY_CURRENT_USER,
"Software\\Clients\\Mail",
"", (char *)userAppName.get());
}
else {
DeleteRegistryValue(HKEY_CURRENT_USER, "Software\\Clients\\Mail", "");
}
if (NS_SUCCEEDED(desktopKeySet)) {
desktopKeySet = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"defaultMailHasBeenSet", "0");
}
::SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
(LPARAM)"Software\\Clients\\Mail");
UnregisterServer(CLSID_CMapiImp, "mozMapi", "mozMapi.1");
return desktopKeySet;
}
return mailKeySet;
}
/** Returns FALSE if showMapiDialog is set to 0.
* Returns TRUE otherwise
* Also returns TRUE if the Mozilla has been set as the default mail client
* and some other application has changed that setting.
* This function gets called only if the current app is not the default mail
* client
*/
PRBool nsMapiRegistryUtils::getShowDialog() {
PRBool rv = PR_FALSE;
nsCAutoString showDialog ;
GetRegistryKey(HKEY_LOCAL_MACHINE, "Software\\Mozilla\\Desktop",
"showMapiDialog", showDialog);
// if the user has not selected the checkbox, show dialog
if (showDialog.IsEmpty() || showDialog.Equals("1"))
rv = PR_TRUE;
if (!rv) {
// even if the user has selected the checkbox
// show it if some other application has changed the
// default setting.
nsCAutoString setMailDefault ;
GetRegistryKey(HKEY_LOCAL_MACHINE,"Software\\Mozilla\\Desktop",
"defaultMailHasBeenSet", setMailDefault);
if (setMailDefault.Equals("1")) {
// need to reset the defaultMailHasBeenSet to "0"
// so that after the dialog is displayed once,
// we do not keep displaying this dialog after the user has
// selected the checkbox
rv = SetRegistryKey(HKEY_LOCAL_MACHINE,
"Software\\Mozilla\\Desktop",
"defaultMailHasBeenSet", "0");
rv = PR_TRUE;
}
}
return rv;
}
nsresult nsMapiRegistryUtils::MakeMapiStringBundle(nsIStringBundle ** aMapiStringBundle)
{
nsresult rv = NS_OK ;
if (m_mapiStringBundle)
{
*aMapiStringBundle = m_mapiStringBundle ;
NS_ADDREF(*aMapiStringBundle);
return rv ;
}
nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(
kStringBundleServiceCID, &rv));
if (NS_FAILED(rv) || !bundleService) return NS_ERROR_FAILURE;
rv = bundleService->CreateBundle(
MAPI_PROPERTIES_CHROME,
getter_AddRefs(m_mapiStringBundle));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
NS_ADDREF(*aMapiStringBundle = m_mapiStringBundle) ;
return rv ;
}
nsresult nsMapiRegistryUtils::ShowMapiErrorDialog()
{
nsresult rv;
nsCOMPtr<nsIPromptService> promptService(do_GetService(
"@mozilla.org/embedcomp/prompt-service;1", &rv));
if (NS_SUCCEEDED(rv) && promptService)
{
nsCOMPtr<nsIStringBundle> bundle;
rv = MakeMapiStringBundle (getter_AddRefs (bundle)) ;
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsXPIDLString dialogTitle;
const PRUnichar *brandStrings[] = { brandName() };
NS_NAMED_LITERAL_STRING(dialogTitlePropertyTag, "errorMessageTitle");
rv = bundle->FormatStringFromName(dialogTitlePropertyTag.get(),
brandStrings, 1,
getter_Copies(dialogTitle));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsXPIDLString dialogText;
NS_NAMED_LITERAL_STRING(dialogTextPropertyTag, "errorMessage");
rv = bundle->FormatStringFromName(dialogTextPropertyTag.get(),
brandStrings, 1,
getter_Copies(dialogText));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
rv = promptService->Alert(nsnull, dialogTitle,
dialogText);
}
return rv;
}

View File

@@ -1,112 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Srilatha Moturi <srilatha@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsmapiregistryutils_h____
#define nsmapiregistryutils_h____
#include <windows.h>
#include <string.h>
#include <winreg.h>
#include "Registry.h"
#include "nsString.h"
#include "nsIStringBundle.h"
class nsMapiRegistryUtils
{
private :
nsCAutoString m_thisApp ;
nsAutoString m_brand ;
nsAutoString m_versionNo ;
nsCOMPtr<nsIStringBundle> m_mapiStringBundle ;
public :
nsMapiRegistryUtils() ;
// returns TRUE if the Mapi32.dll is smart dll.
PRBool isSmartDll();
// returns TRUE if the Mapi32.dll is a Mozilla dll.
PRBool isMozDll();
// Returns the (fully-qualified) name of this executable.
const char * thisApplication() ;
// This returns the brand name for this application
const PRUnichar * brandName() ;
// This returns the version no for this application
const PRUnichar * versionNo() ;
// verifyRestrictedAccess - Returns PR_TRUE if this user only has restricted access
// to the registry keys we need to modify.
PRBool verifyRestrictedAccess() ;
// set the Windows registry key
nsresult SetRegistryKey(HKEY baseKey, const char * keyName,
const char * valueName, char * value);
// delete a registry key
nsresult DeleteRegistryValue(HKEY baseKey, const char * keyName,
const char * valueName);
// get a Windows registry key
void GetRegistryKey(HKEY baseKey, const char * keyName,
const char * valueName, nsCAutoString & value) ;
// Returns TRUE if the current application is default mail client.
PRBool IsDefaultMailClient();
// Sets Mozilla as default Mail Client
nsresult setDefaultMailClient() ;
// Removes Mozilla as the default Mail client and restores the previous setting
nsresult unsetDefaultMailClient() ;
// Saves the current setting of the default Mail Client in
// HKEY_LOCAL_MACHINE\\Software\\Mozilla\\Desktop
nsresult saveDefaultMailClient();
// Saves the current user setting of the default Mail Client in
// HKEY_LOCAL_MACHINE\\Software\\Mozilla\\Desktop
nsresult saveUserDefaultMailClient();
nsresult CopyMozMapiToWinSysDir();
nsresult RestoreBackedUpMapiDll();
// Returns FALSE if showMapiDialog is set to 0.
PRBool getShowDialog() ;
// create a string bundle for MAPI messages
nsresult MakeMapiStringBundle(nsIStringBundle ** aMapiStringBundle) ;
// display an error dialog for MAPI messages
nsresult ShowMapiErrorDialog() ;
} ;
#endif

View File

@@ -1,30 +0,0 @@
<?xml version="1.0"?>
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
<!-- list all the packages being supplied by this jar -->
<RDF:Seq about="urn:mozilla:package:root">
<RDF:li resource="urn:mozilla:package:messenger-mapi"/>
</RDF:Seq>
<!-- package information -->
<RDF:Description about="urn:mozilla:package:messenger-mapi"
chrome:displayName="Messenger"
chrome:author="mozilla.org"
chrome:name="messenger-mapi"
chrome:localeVersion="0.9.7"
chrome:skinVersion="0.9.4">
</RDF:Description>
<!-- overlay information -->
<RDF:Seq about="urn:mozilla:overlays">
<RDF:li resource="chrome://messenger/content/pref-mailnews.xul"/>
</RDF:Seq>
<!-- mapi items for Mail And Newsgroups preferences pane -->
<RDF:Seq about="chrome://messenger/content/pref-mailnews.xul">
<RDF:li>chrome://messenger-mapi/content/pref-mailnewsOverlay.xul</RDF:li>
</RDF:Seq>
</RDF:RDF>

View File

@@ -1,3 +0,0 @@
messenger.jar:
content/messenger-mapi/pref-mailnewsOverlay.xul
content/messenger-mapi/contents.rdf

View File

@@ -1,14 +0,0 @@
<?xml version="1.0"?>
<RDF:RDF xmlns:chrome="http://www.mozilla.org/rdf/chrome#"
xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<!-- mapi items for mailnews preferences -->
<RDF:Seq about="urn:mozilla:overlays">
<RDF:li resource="chrome://messenger/content/pref-mailnews.xul"/>
</RDF:Seq>
<RDF:Seq about="chrome://messenger/content/pref-mailnews.xul">
<RDF:li>chrome://messenger/content/pref-mailnewsOverlay.xul</RDF:li>
</RDF:Seq>
</RDF:RDF>

View File

@@ -1,104 +0,0 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Srilatha Moturi <srilatha@netscape.com>
*/
function mailnewsOverlayStartup() {
mailnewsOverlayInit();
parent.hPrefWindow.registerOKCallbackFunc(onOK);
if (!("mapiPref" in parent)) {
parent.mapiPref = new Object;
parent.mapiPref.isDefaultMailClient =
document.getElementById("mailnewsEnableMapi").checked;
}
else {
// when we switch between different panes
// set the checkbox based on the saved state
var mailnewsEnableMapi = document.getElementById("mailnewsEnableMapi");
if (parent.mapiPref.isDefaultMailClient)
mailnewsEnableMapi.setAttribute("checked", "true");
else
mailnewsEnableMapi.setAttribute("checked", "false");
}
}
function mailnewsOverlayInit() {
try {
var mapiRegistry = Components.classes[ "@mozilla.org/mapiregistry;1" ].
getService( Components.interfaces.nsIMapiRegistry );
}
catch(ex){
mapiRegistry = null;
}
const prefbase = "system.windows.lock_ui.";
var mailnewsEnableMapi = document.getElementById("mailnewsEnableMapi");
if (mapiRegistry) {
// initialise preference component.
// While the data is coming from the system registry, we use a set
// of parallel preferences to indicate if the ui should be locked.
try {
var prefService = Components.classes["@mozilla.org/preferences-service;1"]
.getService()
.QueryInterface(Components.interfaces.nsIPrefService);
var prefBranch = prefService.getBranch(prefbase);
if (prefBranch && prefBranch.prefIsLocked("default_mail_client")) {
if (prefBranch.getBoolPref("default_mail_client"))
mapiRegistry.setDefaultMailClient();
else
mapiRegistry.unsetDefaultMailClient();
mailnewsEnableMapi.setAttribute("disabled", "true");
}
}
catch(ex) {}
if (mapiRegistry.isDefaultMailClient)
mailnewsEnableMapi.setAttribute("checked", "true");
else
mailnewsEnableMapi.setAttribute("checked", "false");
}
else
mailnewsEnableMapi.setAttribute("disabled", "true");
}
function onEnableMapi() {
// save the state of the checkbox
if ("mapiPref" in parent)
parent.mapiPref.isDefaultMailClient =
document.getElementById("mailnewsEnableMapi").checked;
}
function onOK()
{
try {
var mapiRegistry = Components.classes[ "@mozilla.org/mapiregistry;1" ].
getService( Components.interfaces.nsIMapiRegistry );
}
catch(ex){
mapiRegistry = null;
}
if (mapiRegistry &&
("mapiPref" in parent) &&
(mapiRegistry.isDefaultMailClient != parent.mapiPref.isDefaultMailClient)) {
if (parent.mapiPref.isDefaultMailClient)
mapiRegistry.setDefaultMailClient();
else
mapiRegistry.unsetDefaultMailClient();
}
}

View File

@@ -1,44 +0,0 @@
<?xml version="1.0"?>
<!--
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/
oftware 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) 2001 Netscape Communications Corporation. All
Rights Reserved.
Contributor(s):
Srilatha Moturi <srilatha@netscape.com>
-->
<!DOCTYPE window [
<!ENTITY % brandDTD SYSTEM "chrome://global/locale/brand.dtd" >
%brandDTD;
<!ENTITY % prefMailnewsOverlayDTD SYSTEM "chrome://messenger-mapi/locale/pref-mailnewsOverlay.dtd" >
%prefMailnewsOverlayDTD;
]>
<overlay id="prefMailnewsOverlay"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/x-javascript">
<![CDATA[
_elementIDs.push("mailnewsEnableMapi");
]]>
</script>
<script type="application/x-javascript" src="chrome://messenger-mapi/content/pref-mailnewsOverlay.js"/>
<hbox autostretch="never" id="mapi">
<checkbox id="mailnewsEnableMapi" label="&enableMapi.label;"
accesskey="&enableMapi.accesskey;"
preftype="bool" prefstring="mailnews.default_mail_client" prefattribute="checked"/>
</hbox>
</overlay>

View File

@@ -1,23 +0,0 @@
<?xml version="1.0"?>
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
<!-- list all the skins being supplied by this package -->
<RDF:Seq about="urn:mozilla:locale:root">
<RDF:li resource="urn:mozilla:locale:en-US"/>
</RDF:Seq>
<!-- locale information -->
<RDF:Description about="urn:mozilla:locale:en-US">
<chrome:packages>
<RDF:Seq about="urn:mozilla:locale:en-US:packages">
<RDF:li resource="urn:mozilla:locale:en-US:messenger-mapi"/>
</RDF:Seq>
</chrome:packages>
</RDF:Description>
<!-- Version Information. State that we work only with major version of this
package. -->
<RDF:Description about="urn:mozilla:locale:en-US:messenger-mapi"
chrome:localeVersion="0.9.7"/>
</RDF:RDF>

View File

@@ -1,4 +0,0 @@
en-US.jar:
locale/en-US/messenger-mapi/pref-mailnewsOverlay.dtd
locale/en-US/messenger-mapi/mapi.properties
locale/en-US/messenger-mapi/contents.rdf

View File

@@ -1,23 +0,0 @@
# Mail Integration Dialog
dialogTitle=%S Mail
dialogText=Do you want to use %S as the default mail application?
checkboxText=Do not display this dialog again
# MAPI Messages
loginText=Please enter your password for %S:
loginTextwithName=Please enter your username and password
loginTitle=%S Mail
PasswordTitle=%S Mail
# MAPI Error Messages
errorMessage=%S Mail could not be set as the default mail application because a registry key could not be updated. Verify with your system administrator that you have write access to your system registry, and then try again.
errorMessageTitle=%S Mail
# MAPI Security Messages
mapiBlindSendWarning=Another application is attempting to send mail using your user profile. Are you sure you want to send mail?
mapiBlindSendDontShowAgain=Warn me whenever other applications try to send mail from me
#Default Mail Display String
# localization note, $1%S is the app name, $2%S is the version
defaultMailDisplayTitle=%S %S Mail

View File

@@ -1,3 +0,0 @@
<!ENTITY enableMapiTitle.label "When sending mail from other applications">
<!ENTITY enableMapi.label "Use &vendorShortName; Mail as the default mail application.">
<!ENTITY enableMapi.accesskey "u">

View File

@@ -0,0 +1,124 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "MPL"); you may not use this file except in
* compliance with the MPL. You may obtain a copy of the MPL at
* http://www.mozilla.org/MPL/
*
* Software distributed under the MPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
* for the specific language governing rights and limitations under the
* MPL.
*
* The Initial Developer of this code under the MPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsISupports.idl"
#include "nsIEnumerator.idl"
typedef PRUint32 nsRegistryKey;
typedef long nsWellKnownRegistry;
[scriptable,uuid(5D41A440-8E37-11d2-8059-00600811A9C3)]
interface nsIRegistry : nsISupports
{
const long None = 0;
const long Users = 1;
const long Common = 2;
const long CurrentUser = 3;
const long ApplicationComponentRegistry = 1;
const long ApplicationRegistry = 2;
// Dont use this one. This for internal use only.
const long ApplicationCustomRegistry = -1;
void open(in string regFile);
void openWellKnownRegistry(in nsWellKnownRegistry regid);
void flush();
boolean isOpen();
nsRegistryKey addKey(in nsRegistryKey baseKey, in wstring keyname);
nsRegistryKey getKey(in nsRegistryKey baseKey, in wstring keyname);
void removeKey(in nsRegistryKey baseKey, in wstring keyname);
wstring getString(in nsRegistryKey baseKey, in wstring valname);
void setString(in nsRegistryKey baseKey, in wstring valname, in wstring value);
string getStringUTF8(in nsRegistryKey baseKey, in string path);
void setStringUTF8(in nsRegistryKey baseKey, in string path, in string value);
void getBytesUTF8(in nsRegistryKey baseKey, in string path, out PRUint32 length, [retval, array, size_is(length)] out PRUint8 valueArray);
void setBytesUTF8(in nsRegistryKey baseKey, in string path, in PRUint32 length, [array, size_is(length)] in PRUint8 valueArray);
PRInt32 getInt(in nsRegistryKey baseKey, in string path);
void setInt(in nsRegistryKey baseKey, in string path, in PRInt32 value);
PRInt64 getLongLong(in nsRegistryKey baseKey, in string path);
void setLongLong(in nsRegistryKey baseKey, in string path, inout PRInt64 value);
/**
* addSubtree() and friends need to be renamed to addKeyUTF8().
* If you are using these forms make sure you pass UTF8 data
*/
nsRegistryKey addSubtree(in nsRegistryKey baseKey, in string path);
void removeSubtree(in nsRegistryKey baseKey, in string path);
nsRegistryKey getSubtree(in nsRegistryKey baseKey, in string path);
nsRegistryKey addSubtreeRaw(in nsRegistryKey baseKey, in string path);
void removeSubtreeRaw(in nsRegistryKey baseKey, in string path);
nsRegistryKey getSubtreeRaw(in nsRegistryKey baseKey, in string path);
nsIEnumerator enumerateSubtrees(in nsRegistryKey baseKey);
nsIEnumerator enumerateAllSubtrees(in nsRegistryKey baseKey);
nsIEnumerator enumerateValues(in nsRegistryKey baseKey);
const unsigned long String = 1;
const unsigned long Int32 = 2;
const unsigned long Bytes = 3;
const unsigned long File = 4;
unsigned long getValueType(in nsRegistryKey baseKey, in string path);
PRUint32 getValueLength(in nsRegistryKey baseKey, in string path);
void deleteValue(in nsRegistryKey baseKey, in string path);
/**
* escapeKey() takes arbitrary binary data and converts it into
* valid ASCII which can be used as registry key or value names
*/
void escapeKey([array, size_is(length)] in PRUint8 key, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 escaped);
void unescapeKey([array, size_is(length)] in PRUint8 escaped, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 key);
attribute string currentUserName;
void pack();
};
[scriptable, uuid(8cecf236-1dd2-11b2-893c-f9848956eaec)]
interface nsIRegistryEnumerator : nsIEnumerator
{
void currentItemInPlaceUTF8(out nsRegistryKey key,
[shared, retval] out string item);
};
[scriptable, uuid(D1B54831-AC07-11d2-805E-00600811A9C3)]
interface nsIRegistryNode : nsISupports
{
readonly attribute string nameUTF8;
readonly attribute wstring name;
readonly attribute nsRegistryKey key;
};
[scriptable,uuid(5316C380-B2F8-11d2-A374-0080C6F80E4B)]
interface nsIRegistryValue : nsISupports
{
readonly attribute wstring name;
readonly attribute string nameUTF8;
readonly attribute unsigned long type;
readonly attribute PRUint32 length;
};
%{ C++
#include "nsIRegistryUtils.h"
%}

View File

@@ -0,0 +1,44 @@
/* -*- Mode: C++; tab-width: 4; 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 __nsIRegistryUtils_h
#define __nsIRegistryUtils_h
#define NS_REGISTRY_CONTRACTID "@mozilla.org/registry;1"
#define NS_REGISTRY_CLASSNAME "Mozilla Registry"
/* be761f00-a3b0-11d2-996c-0080c7cb1081 */
#define NS_REGISTRY_CID \
{ 0xbe761f00, 0xa3b0, 0x11d2, \
{0x99, 0x6c, 0x00, 0x80, 0xc7, 0xcb, 0x10, 0x81} }
/*------------------------------- Error Codes ----------------------------------
------------------------------------------------------------------------------*/
#define NS_ERROR_REG_BADTYPE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 1 )
#define NS_ERROR_REG_NO_MORE NS_ERROR_GENERATE_SUCCESS( NS_ERROR_MODULE_REG, 2 )
#define NS_ERROR_REG_NOT_FOUND NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 3 )
#define NS_ERROR_REG_NOFILE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 4 )
#define NS_ERROR_REG_BUFFER_TOO_SMALL NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 5 )
#define NS_ERROR_REG_NAME_TOO_LONG NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 6 )
#define NS_ERROR_REG_NO_PATH NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 7 )
#define NS_ERROR_REG_READ_ONLY NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 8 )
#define NS_ERROR_REG_BAD_UTF8 NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 9 )
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,55 @@
/* -*- Mode: C++; tab-width: 8; 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):
* Edward Kandrot <kandrot@netscape.com>
*/
#ifndef nsRegistry_h__
#define nsRegistry_h__
#include "nsIRegistry.h"
#include "NSReg.h"
struct nsRegistry : public nsIRegistry {
// This class implements the nsISupports interface functions.
NS_DECL_ISUPPORTS
// This class implements the nsIRegistry interface functions.
NS_DECL_NSIREGISTRY
// ctor/dtor
nsRegistry();
virtual ~nsRegistry();
int SetBufferSize( int bufsize ); // changes the file buffer size for this registry
protected:
HREG mReg; // Registry handle.
#ifdef EXTRA_THREADSAFE
PRLock *mregLock; // libreg isn't threadsafe. Use locks to synchronize.
#endif
char *mCurRegFile; // these are to prevent open from opening the registry again
nsWellKnownRegistry mCurRegID;
NS_IMETHOD Close();
}; // nsRegistry
#endif

View File

@@ -0,0 +1,621 @@
/* -*- 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) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsAVLTree.h"
enum eLean {eLeft,eNeutral,eRight};
struct NS_COM nsAVLNode {
public:
nsAVLNode(void* aValue) {
mLeft=0;
mRight=0;
mSkew=eNeutral;
mValue=aValue;
}
nsAVLNode* mLeft;
nsAVLNode* mRight;
eLean mSkew;
void* mValue;
};
/************************************************************
Now begin the tree class. Don't forget that the comparison
between nodes must occur via the comparitor function,
otherwise all you're testing is pointer addresses.
************************************************************/
/** ------------------------------------------------
*
*
* @update gess 4/22/98
* @param
* @return
*/ //----------------------------------------------
nsAVLTree::nsAVLTree(nsAVLNodeComparitor& aComparitor,
nsAVLNodeFunctor* aDeallocator) :
mComparitor(aComparitor), mDeallocator(aDeallocator) {
mRoot=0;
mCount=0;
}
static void
avlDeleteTree(nsAVLNode* aNode){
if (aNode) {
avlDeleteTree(aNode->mLeft);
avlDeleteTree(aNode->mRight);
delete aNode;
}
}
/**
*
* @update gess12/27/98
* @param
* @return
*/
nsAVLTree::~nsAVLTree(){
if (mDeallocator) {
ForEachDepthFirst(*mDeallocator);
}
avlDeleteTree(mRoot);
}
class CDoesntExist: public nsAVLNodeFunctor {
public:
CDoesntExist(const nsAVLTree& anotherTree) : mOtherTree(anotherTree) {
}
virtual void* operator()(void* anItem) {
void* result=mOtherTree.FindItem(anItem);
if(result)
return nsnull;
return anItem;
}
protected:
const nsAVLTree& mOtherTree;
};
/**
* This method compares two trees (members by identity).
* @update gess12/27/98
* @param tree to compare against
* @return true if they are identical (contain same stuff).
*/
PRBool nsAVLTree::operator==(const nsAVLTree& aCopy) const{
CDoesntExist functor(aCopy);
void* theItem=FirstThat(functor);
PRBool result=PRBool(!theItem);
return result;
}
/**
*
* @update gess12/27/98
* @param
* @return
*/
static void
avlRotateRight(nsAVLNode*& aRootNode){
nsAVLNode* ptr2;
nsAVLNode* ptr3;
ptr2=aRootNode->mRight;
if(ptr2->mSkew==eRight) {
aRootNode->mRight=ptr2->mLeft;
ptr2->mLeft=aRootNode;
aRootNode->mSkew=eNeutral;
aRootNode=ptr2;
}
else {
ptr3=ptr2->mLeft;
ptr2->mLeft=ptr3->mRight;
ptr3->mRight=ptr2;
aRootNode->mRight=ptr3->mLeft;
ptr3->mLeft=aRootNode;
if(ptr3->mSkew==eLeft)
ptr2->mSkew=eRight;
else ptr2->mSkew=eNeutral;
if(ptr3->mSkew==eRight)
aRootNode->mSkew=eLeft;
else aRootNode->mSkew=eNeutral;
aRootNode=ptr3;
}
aRootNode->mSkew=eNeutral;
return;
}
/**
*
* @update gess12/27/98
* @param
* @return
*/
static void
avlRotateLeft(nsAVLNode*& aRootNode){
nsAVLNode* ptr2;
nsAVLNode* ptr3;
ptr2=aRootNode->mLeft;
if(ptr2->mSkew==eLeft) {
aRootNode->mLeft=ptr2->mRight;
ptr2->mRight=aRootNode;
aRootNode->mSkew=eNeutral;
aRootNode=ptr2;
}
else {
ptr3=ptr2->mRight;
ptr2->mRight=ptr3->mLeft;
ptr3->mLeft=ptr2;
aRootNode->mLeft=ptr3->mRight;
ptr3->mRight=aRootNode;
if(ptr3->mSkew==eRight)
ptr2->mSkew=eLeft;
else ptr2->mSkew=eNeutral;
if(ptr3->mSkew==eLeft)
aRootNode->mSkew=eRight;
else aRootNode->mSkew=eNeutral;
aRootNode=ptr3;
}
aRootNode->mSkew=eNeutral;
return;
}
/** ------------------------------------------------
*
*
* @update gess 4/22/98
* @param
* @return
*/ //----------------------------------------------
static eAVLStatus
avlInsert(nsAVLNode*& aRootNode, nsAVLNode* aNewNode,
nsAVLNodeComparitor& aComparitor) {
eAVLStatus result=eAVL_unknown;
if(!aRootNode) {
aRootNode = aNewNode;
return eAVL_ok;
}
if(aNewNode==aRootNode->mValue) {
return eAVL_duplicate;
}
PRInt32 theCompareResult=aComparitor(aRootNode->mValue,aNewNode->mValue);
if(0 < theCompareResult) { //if(anItem<aRootNode->mValue)
result=avlInsert(aRootNode->mLeft,aNewNode,aComparitor);
if(eAVL_ok==result) {
switch(aRootNode->mSkew){
case eLeft:
avlRotateLeft(aRootNode);
result=eAVL_fail;
break;
case eRight:
aRootNode->mSkew=eNeutral;
result=eAVL_fail;
break;
case eNeutral:
aRootNode->mSkew=eLeft;
break;
} //switch
}//if
} //if
else {
result=avlInsert(aRootNode->mRight,aNewNode,aComparitor);
if(eAVL_ok==result) {
switch(aRootNode->mSkew){
case eLeft:
aRootNode->mSkew=eNeutral;
result=eAVL_fail;
break;
case eRight:
avlRotateRight(aRootNode);
result=eAVL_fail;
break;
case eNeutral:
aRootNode->mSkew=eRight;
break;
} //switch
}
} //if
return result;
}
/** ------------------------------------------------
*
*
* @update gess 4/22/98
* @param
* @return
*/ //----------------------------------------------
static void
avlBalanceLeft(nsAVLNode*& aRootNode, PRBool& delOk){
nsAVLNode* ptr2;
nsAVLNode* ptr3;
eLean balnc2;
eLean balnc3;
switch(aRootNode->mSkew){
case eLeft:
ptr2=aRootNode->mLeft;
balnc2=ptr2->mSkew;
if(balnc2!=eRight) {
aRootNode->mLeft=ptr2->mRight;
ptr2->mRight=aRootNode;
if(balnc2==eNeutral){
aRootNode->mSkew=eLeft;
ptr2->mSkew=eRight;
delOk=PR_FALSE;
}
else{
aRootNode->mSkew=eNeutral;
ptr2->mSkew=eNeutral;
}
aRootNode=ptr2;
}
else{
ptr3=ptr2->mRight;
balnc3=ptr3->mSkew;
ptr2->mRight=ptr3->mLeft;
ptr3->mLeft=ptr2;
aRootNode->mLeft=ptr3->mRight;
ptr3->mRight=aRootNode;
if(balnc3==eRight) {
ptr2->mSkew=eLeft;
}
else {
ptr2->mSkew=eNeutral;
}
if(balnc3==eLeft) {
aRootNode->mSkew=eRight;
}
else {
aRootNode->mSkew=eNeutral;
}
aRootNode=ptr3;
ptr3->mSkew=eNeutral;
}
break;
case eRight:
aRootNode->mSkew=eNeutral;
break;
case eNeutral:
aRootNode->mSkew=eLeft;
delOk=PR_FALSE;
break;
}//switch
return;
}
/** ------------------------------------------------
*
*
* @update gess 4/22/98
* @param
* @return
*/ //----------------------------------------------
static void
avlBalanceRight(nsAVLNode*& aRootNode, PRBool& delOk){
nsAVLNode* ptr2;
nsAVLNode* ptr3;
eLean balnc2;
eLean balnc3;
switch(aRootNode->mSkew){
case eLeft:
aRootNode->mSkew=eNeutral;
break;
case eRight:
ptr2=aRootNode->mRight;
balnc2=ptr2->mSkew;
if(balnc2!=eLeft) {
aRootNode->mRight=ptr2->mLeft;
ptr2->mLeft=aRootNode;
if(balnc2==eNeutral){
aRootNode->mSkew=eRight;
ptr2->mSkew=eLeft;
delOk=PR_FALSE;
}
else{
aRootNode->mSkew=eNeutral;
ptr2->mSkew=eNeutral;
}
aRootNode=ptr2;
}
else{
ptr3=ptr2->mLeft;
balnc3=ptr3->mSkew;
ptr2->mLeft=ptr3->mRight;
ptr3->mRight=ptr2;
aRootNode->mRight=ptr3->mLeft;
ptr3->mLeft=aRootNode;
if(balnc3==eLeft) {
ptr2->mSkew=eRight;
}
else {
ptr2->mSkew=eNeutral;
}
if(balnc3==eRight) {
aRootNode->mSkew=eLeft;
}
else {
aRootNode->mSkew=eNeutral;
}
aRootNode=ptr3;
ptr3->mSkew=eNeutral;
}
break;
case eNeutral:
aRootNode->mSkew=eRight;
delOk=PR_FALSE;
break;
}//switch
return;
}
/** ------------------------------------------------
*
*
* @update gess 4/22/98
* @param
* @return
*/ //----------------------------------------------
static eAVLStatus
avlRemoveChildren(nsAVLNode*& aRootNode,nsAVLNode*& anotherNode, PRBool& delOk){
eAVLStatus result=eAVL_ok;
if(!anotherNode->mRight){
aRootNode->mValue=anotherNode->mValue; //swap
anotherNode=anotherNode->mLeft;
delOk=PR_TRUE;
}
else{
avlRemoveChildren(aRootNode,anotherNode->mRight,delOk);
if(delOk)
avlBalanceLeft(anotherNode,delOk);
}
return result;
}
/** ------------------------------------------------
*
*
* @update gess 4/22/98
* @param
* @return
*/ //----------------------------------------------
static eAVLStatus
avlRemove(nsAVLNode*& aRootNode, void* anItem, PRBool& delOk,
nsAVLNodeComparitor& aComparitor){
eAVLStatus result=eAVL_ok;
if(!aRootNode)
delOk=PR_FALSE;
else {
PRInt32 cmp=aComparitor(anItem,aRootNode->mValue);
if(cmp<0){
avlRemove(aRootNode->mLeft,anItem,delOk,aComparitor);
if(delOk)
avlBalanceRight(aRootNode,delOk);
}
else if(cmp>0){
avlRemove(aRootNode->mRight,anItem,delOk,aComparitor);
if(delOk)
avlBalanceLeft(aRootNode,delOk);
}
else{ //they match...
nsAVLNode* temp=aRootNode;
if(!aRootNode->mRight) {
aRootNode=aRootNode->mLeft;
delOk=PR_TRUE;
delete temp;
}
else if(!aRootNode->mLeft) {
aRootNode=aRootNode->mRight;
delOk=PR_TRUE;
delete temp;
}
else {
avlRemoveChildren(aRootNode,aRootNode->mLeft,delOk);
if(delOk)
avlBalanceRight(aRootNode,delOk);
}
}
}
return result;
}
/** ------------------------------------------------
*
*
* @update gess 4/22/98
* @param
* @return
*/ //----------------------------------------------
eAVLStatus
nsAVLTree::AddItem(void* anItem){
eAVLStatus result=eAVL_ok;
nsAVLNode* theNewNode=new nsAVLNode(anItem);
result=avlInsert(mRoot,theNewNode,mComparitor);
if(eAVL_duplicate!=result)
mCount++;
else {
delete theNewNode;
}
return result;
}
/** ------------------------------------------------
*
*
* @update gess 4/22/98
* @param
* @return
*/ //----------------------------------------------
void* nsAVLTree::FindItem(void* aValue) const{
nsAVLNode* result=mRoot;
PRInt32 count=0;
while(result) {
count++;
PRInt32 cmp=mComparitor(aValue,result->mValue);
if(0==cmp) {
//we matched...
break;
}
else if(0>cmp){
//theNode was greater...
result=result->mLeft;
}
else {
//aValue is greater...
result=result->mRight;
}
}
if(result) {
return result->mValue;
}
return nsnull;
}
/**
*
* @update gess12/30/98
* @param
* @return
*/
eAVLStatus
nsAVLTree::RemoveItem(void* aValue){
PRBool delOk=PR_TRUE;
eAVLStatus result=avlRemove(mRoot,aValue,delOk,mComparitor);
if(eAVL_ok==result)
mCount--;
return result;
}
/**
*
* @update gess9/11/98
* @param
* @return
*/
static void
avlForEachDepthFirst(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor){
if(aNode) {
avlForEachDepthFirst(aNode->mLeft,aFunctor);
avlForEachDepthFirst(aNode->mRight,aFunctor);
aFunctor(aNode->mValue);
}
}
/**
*
* @update gess9/11/98
* @param
* @return
*/
void
nsAVLTree::ForEachDepthFirst(nsAVLNodeFunctor& aFunctor) const{
::avlForEachDepthFirst(mRoot,aFunctor);
}
/**
*
* @update gess9/11/98
* @param
* @return
*/
static void
avlForEach(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor) {
if(aNode) {
avlForEach(aNode->mLeft,aFunctor);
aFunctor(aNode->mValue);
avlForEach(aNode->mRight,aFunctor);
}
}
/**
*
* @update gess9/11/98
* @param
* @return
*/
void
nsAVLTree::ForEach(nsAVLNodeFunctor& aFunctor) const{
::avlForEach(mRoot,aFunctor);
}
/**
*
* @update gess9/11/98
* @param
* @return
*/
static void*
avlFirstThat(nsAVLNode* aNode, nsAVLNodeFunctor& aFunctor) {
void* result=nsnull;
if(aNode) {
result = avlFirstThat(aNode->mLeft,aFunctor);
if (result) {
return result;
}
result = aFunctor(aNode->mValue);
if (result) {
return result;
}
result = avlFirstThat(aNode->mRight,aFunctor);
}
return result;
}
/**
*
* @update gess9/11/98
* @param
* @return
*/
void*
nsAVLTree::FirstThat(nsAVLNodeFunctor& aFunctor) const{
return ::avlFirstThat(mRoot,aFunctor);
}

View File

@@ -0,0 +1,78 @@
/* -*- 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) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsAVLTree_h___
#define nsAVLTree_h___
#include "nscore.h"
enum eAVLStatus {eAVL_unknown,eAVL_ok,eAVL_fail,eAVL_duplicate};
struct nsAVLNode;
/**
*
* @update gess12/26/98
* @param anObject1 is the first object to be compared
* @param anObject2 is the second object to be compared
* @return -1,0,1 if object1 is less, equal, greater than object2
*/
class NS_COM nsAVLNodeComparitor {
public:
virtual PRInt32 operator()(void* anItem1,void* anItem2)=0;
};
class NS_COM nsAVLNodeFunctor {
public:
virtual void* operator()(void* anItem)=0;
};
class NS_COM nsAVLTree {
public:
nsAVLTree(nsAVLNodeComparitor& aComparitor, nsAVLNodeFunctor* aDeallocator);
~nsAVLTree(void);
PRBool operator==(const nsAVLTree& aOther) const;
PRInt32 GetCount(void) const {return mCount;}
//main functions...
eAVLStatus AddItem(void* anItem);
eAVLStatus RemoveItem(void* anItem);
void* FindItem(void* anItem) const;
void ForEach(nsAVLNodeFunctor& aFunctor) const;
void ForEachDepthFirst(nsAVLNodeFunctor& aFunctor) const;
void* FirstThat(nsAVLNodeFunctor& aFunctor) const;
protected:
nsAVLNode* mRoot;
PRInt32 mCount;
nsAVLNodeComparitor& mComparitor;
nsAVLNodeFunctor* mDeallocator;
};
#endif /* nsAVLTree_h___ */

View File

@@ -0,0 +1,923 @@
/* -*- 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.
*
* Original Author:
* Rick Gessner <rickg@netscape.com>
*
* Contributor(s):
* Scott Collins <scc@mozilla.org>
*/
/******************************************************************************************
MODULE NOTES:
This file contains the nsStr data structure.
This general purpose buffer management class is used as the basis for our strings.
It's benefits include:
1. An efficient set of library style functions for manipulating nsStrs
2. Support for 1 and 2 byte character strings (which can easily be increased to n)
3. Unicode awareness and interoperability.
*******************************************************************************************/
#include "nsStr.h"
#include "bufferRoutines.h"
#include <stdio.h> //only used for printf
#include "nsCRT.h"
#include "nsDeque.h"
//static const char* kCallFindChar = "For better performance, call FindChar() for targets whose length==1.";
//static const char* kCallRFindChar = "For better performance, call RFindChar() for targets whose length==1.";
static const PRUnichar gCommonEmptyBuffer[1] = {0};
static PRBool gStringAcquiredMemory = PR_TRUE;
/**
* This method initializes all the members of the nsStr structure
*
* @update gess10/30/98
* @param
* @return
*/
void nsStr::Initialize(nsStr& aDest,eCharSize aCharSize) {
aDest.mStr=(char*)gCommonEmptyBuffer;
aDest.mLength=0;
aDest.mCapacity=0;
aDest.mCharSize=aCharSize;
aDest.mOwnsBuffer=0;
}
/**
* This method initializes all the members of the nsStr structure
* @update gess10/30/98
* @param
* @return
*/
void nsStr::Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 aLength,eCharSize aCharSize,PRBool aOwnsBuffer){
aDest.mStr=(aCString) ? aCString : (char*)gCommonEmptyBuffer;
aDest.mLength=aLength;
aDest.mCapacity=aCapacity;
aDest.mCharSize=aCharSize;
aDest.mOwnsBuffer=aOwnsBuffer;
}
/**
* This member destroys the memory buffer owned by an nsStr object (if it actually owns it)
* @update gess10/30/98
* @param
* @return
*/
void nsStr::Destroy(nsStr& aDest) {
if((aDest.mStr) && (aDest.mStr!=(char*)gCommonEmptyBuffer)) {
Free(aDest);
}
}
/**
* This method gets called when the internal buffer needs
* to grow to a given size. The original contents are not preserved.
* @update gess 3/30/98
* @param aNewLength -- new capacity of string in charSize units
* @return void
*/
PRBool nsStr::EnsureCapacity(nsStr& aString,PRUint32 aNewLength) {
PRBool result=PR_TRUE;
if(aNewLength>aString.mCapacity) {
result=Realloc(aString,aNewLength);
if(aString.mStr)
AddNullTerminator(aString);
}
return result;
}
/**
* This method gets called when the internal buffer needs
* to grow to a given size. The original contents ARE preserved.
* @update gess 3/30/98
* @param aNewLength -- new capacity of string in charSize units
* @return void
*/
PRBool nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength) {
PRBool result=PR_TRUE;
if(aNewLength>aDest.mCapacity) {
nsStr theTempStr;
nsStr::Initialize(theTempStr,aDest.mCharSize);
#ifndef NS_USE_OLD_STRING_ALLOCATION_STRATEGY
// the new strategy is, allocate exact size, double on grows
if ( aDest.mCapacity ) {
PRUint32 newCapacity = aDest.mCapacity;
while ( newCapacity < aNewLength )
newCapacity <<= 1;
aNewLength = newCapacity;
}
#endif
result=EnsureCapacity(theTempStr,aNewLength);
if(result) {
if(aDest.mLength) {
StrAppend(theTempStr,aDest,0,aDest.mLength);
}
Free(aDest);
aDest.mStr = theTempStr.mStr;
theTempStr.mStr=0; //make sure to null this out so that you don't lose the buffer you just stole...
aDest.mLength=theTempStr.mLength;
aDest.mCapacity=theTempStr.mCapacity;
aDest.mOwnsBuffer=theTempStr.mOwnsBuffer;
}
}
return result;
}
/**
* Replaces the contents of aDest with aSource, up to aCount of chars.
* @update gess10/30/98
* @param aDest is the nsStr that gets changed.
* @param aSource is where chars are copied from
* @param aCount is the number of chars copied from aSource
*/
void nsStr::StrAssign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount){
if(&aDest!=&aSource){
Truncate(aDest,0);
StrAppend(aDest,aSource,anOffset,aCount);
}
}
/**
* This method appends the given nsStr to this one. Note that we have to
* pay attention to the underlying char-size of both structs.
* @update gess10/30/98
* @param aDest is the nsStr to be manipulated
* @param aSource is where char are copied from
* @aCount is the number of bytes to be copied
*/
void nsStr::StrAppend(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount){
if(anOffset<aSource.mLength){
PRUint32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength);
PRUint32 theLength=(anOffset+theRealLen<aSource.mLength) ? theRealLen : (aSource.mLength-anOffset);
if(0<theLength){
PRBool isBigEnough=PR_TRUE;
if(aDest.mLength+theLength > aDest.mCapacity) {
isBigEnough=GrowCapacity(aDest,aDest.mLength+theLength);
}
if(isBigEnough) {
//now append new chars, starting at offset
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDest.mLength,aSource.mStr,anOffset,theLength);
aDest.mLength+=theLength;
AddNullTerminator(aDest);
NSSTR_SEEN(aDest);
}
}
}
}
/**
* This method inserts up to "aCount" chars from a source nsStr into a dest nsStr.
* @update gess10/30/98
* @param aDest is the nsStr that gets changed
* @param aDestOffset is where in aDest the insertion is to occur
* @param aSource is where chars are copied from
* @param aSrcOffset is where in aSource chars are copied from
* @param aCount is the number of chars from aSource to be inserted into aDest
*/
void nsStr::StrInsert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount){
//there are a few cases for insert:
// 1. You're inserting chars into an empty string (assign)
// 2. You're inserting onto the end of a string (append)
// 3. You're inserting onto the 1..n-1 pos of a string (the hard case).
if(0<aSource.mLength){
if(aDest.mLength){
if(aDestOffset<aDest.mLength){
PRInt32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength);
PRInt32 theLength=(aSrcOffset+theRealLen<aSource.mLength) ? theRealLen : (aSource.mLength-aSrcOffset);
if(aSrcOffset<aSource.mLength) {
//here's the only new case we have to handle.
//chars are really being inserted into our buffer...
if(aDest.mLength+theLength > aDest.mCapacity) {
nsStr theTempStr;
nsStr::Initialize(theTempStr,aDest.mCharSize);
PRBool isBigEnough=EnsureCapacity(theTempStr,aDest.mLength+theLength); //grow the temp buffer to the right size
if(isBigEnough) {
if(aDestOffset) {
StrAppend(theTempStr,aDest,0,aDestOffset); //first copy leftmost data...
}
StrAppend(theTempStr,aSource,0,aSource.mLength); //next copy inserted (new) data
PRUint32 theRemains=aDest.mLength-aDestOffset;
if(theRemains) {
StrAppend(theTempStr,aDest,aDestOffset,theRemains); //next copy rightmost data
}
Free(aDest);
aDest.mStr = theTempStr.mStr;
theTempStr.mStr=0; //make sure to null this out so that you don't lose the buffer you just stole...
aDest.mCapacity=theTempStr.mCapacity;
aDest.mOwnsBuffer=theTempStr.mOwnsBuffer;
}
}
else {
//shift the chars right by theDelta...
(*gShiftChars[aDest.mCharSize][KSHIFTRIGHT])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
//now insert new chars, starting at offset
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDestOffset,aSource.mStr,aSrcOffset,theLength);
}
//finally, make sure to update the string length...
aDest.mLength+=theLength;
AddNullTerminator(aDest);
NSSTR_SEEN(aDest);
}//if
//else nothing to do!
}
else StrAppend(aDest,aSource,0,aCount);
}
else StrAppend(aDest,aSource,0,aCount);
}
}
/**
* This method deletes up to aCount chars from aDest
* @update gess10/30/98
* @param aDest is the nsStr to be manipulated
* @param aDestOffset is where in aDest deletion is to occur
* @param aCount is the number of chars to be deleted in aDest
*/
void nsStr::Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount){
if(aDestOffset<aDest.mLength){
PRUint32 theDelta=aDest.mLength-aDestOffset;
PRUint32 theLength=(theDelta<aCount) ? theDelta : aCount;
if(aDestOffset+theLength<aDest.mLength) {
//if you're here, it means we're cutting chars out of the middle of the string...
//so shift the chars left by theLength...
(*gShiftChars[aDest.mCharSize][KSHIFTLEFT])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
aDest.mLength-=theLength;
AddNullTerminator(aDest);
NSSTR_SEEN(aDest);
}
else Truncate(aDest,aDestOffset);
}//if
}
/**
* This method truncates the given nsStr at given offset
* @update gess10/30/98
* @param aDest is the nsStr to be truncated
* @param aDestOffset is where in aDest truncation is to occur
*/
void nsStr::Truncate(nsStr& aDest,PRUint32 aDestOffset){
if(aDest.mCapacity && aDestOffset<=aDest.mCapacity){
aDest.mLength=aDestOffset;
AddNullTerminator(aDest);
NSSTR_SEEN(aDest);
}
}
/**
* This method forces the given string to upper or lowercase
* @update gess1/7/99
* @param aDest is the string you're going to change
* @param aToUpper: if TRUE, then we go uppercase, otherwise we go lowercase
* @return
*/
void nsStr::ChangeCase(nsStr& aDest,PRBool aToUpper) {
// somehow UnicharUtil return failed, fallback to the old ascii only code
gCaseConverters[aDest.mCharSize](aDest.mStr,aDest.mLength,aToUpper);
}
/**
* This method removes characters from the given set from this string.
* NOTE: aSet is a char*, and it's length is computed using strlen, which assumes null termination.
*
* @update gess 11/7/99
* @param aDest
* @param aSet
* @param aEliminateLeading
* @param aEliminateTrailing
* @return nothing
*/
void nsStr::Trim(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing){
if((aDest.mLength>0) && aSet){
PRInt32 theIndex=-1;
PRInt32 theMax=aDest.mLength;
PRInt32 theSetLen=nsCRT::strlen(aSet);
if(aEliminateLeading) {
while(++theIndex<=theMax) {
PRUnichar theChar=GetCharAt(aDest,theIndex);
PRInt32 thePos=gFindChars[eOneByte](aSet,theSetLen,0,theChar,PR_FALSE,theSetLen);
if(kNotFound==thePos)
break;
}
if(0<theIndex) {
if(theIndex<theMax) {
Delete(aDest,0,theIndex);
}
else Truncate(aDest,0);
}
}
if(aEliminateTrailing) {
theIndex=aDest.mLength;
PRInt32 theNewLen=theIndex;
while(--theIndex>=0) {
PRUnichar theChar=GetCharAt(aDest,theIndex); //read at end now...
PRInt32 thePos=gFindChars[eOneByte](aSet,theSetLen,0,theChar,PR_FALSE,theSetLen);
if(kNotFound<thePos)
theNewLen=theIndex;
else break;
}
if(theNewLen<theMax) {
Truncate(aDest,theNewLen);
}
}
}
}
/**
*
* @update gess1/7/99
* @param
* @return
*/
void nsStr::CompressSet(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing){
Trim(aDest,aSet,aEliminateLeading,aEliminateTrailing);
PRUint32 aNewLen=gCompressChars[aDest.mCharSize](aDest.mStr,aDest.mLength,aSet);
aDest.mLength=aNewLen;
NSSTR_SEEN(aDest);
}
/**
*
* @update gess1/7/99
* @param
* @return
*/
void nsStr::StripChars(nsStr& aDest,const char* aSet){
if((0<aDest.mLength) && (aSet)) {
PRUint32 aNewLen=gStripChars[aDest.mCharSize](aDest.mStr,aDest.mLength,aSet);
aDest.mLength=aNewLen;
NSSTR_SEEN(aDest);
}
}
/**************************************************************
Searching methods...
**************************************************************/
/**
* This searches aDest for a given substring
*
* @update gess 2/04/00: added aCount argument to restrict search
* @param aDest string to search
* @param aTarget is the substring you're trying to find.
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search
* @param aCount tells us how many iterations to make from offset; -1 means the full length of the string
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::FindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
PRInt32 theMaxPos = aDest.mLength-aTarget.mLength; //this is the last pos that is feasible for starting the search, with given lengths...
if(0<=theMaxPos) {
if(anOffset<0)
anOffset=0;
if((0<aDest.mLength) && (anOffset<=theMaxPos) && (aTarget.mLength)) {
if(aCount<0)
aCount = MaxInt(theMaxPos,1);
if(0<aCount) {
PRInt32 aDelta= (aDest.mCharSize == eOneByte) ? 1 : 2;
const char* root = aDest.mStr;
const char* left = root+(anOffset*aDelta);
const char* last = left+((aCount)*aDelta);
const char* max = root+(theMaxPos*aDelta);
const char* right = (last<max) ? last : max;
while(left<=right){
PRInt32 cmp=(*gCompare[aDest.mCharSize][aTarget.mCharSize])(left,aTarget.mStr,aTarget.mLength,aIgnoreCase);
if(0==cmp) {
return (left-root)/aDelta;
}
left+=aDelta;
} //while
} //if
}
} //if
return kNotFound;
}
/**
* This searches aDest for a given character
*
* @update gess 2/04/00: added aCount argument to restrict search
* @param aDest string to search
* @param char is the character you're trying to find.
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search
* @param aCount tell us how many chars to search from offset
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::FindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
return gFindChars[aDest.mCharSize](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase,aCount);
}
/**
* This searches aDest for a character found in aSet.
*
* @update gess 3/25/98
* @param aDest string to search
* @param aSet contains a list of chars to be searched for
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset) {
//NS_PRECONDITION(aSet.mLength!=1,kCallFindChar);
PRInt32 index=(0<=anOffset) ? anOffset-1 : -1;
PRInt32 thePos;
//Note that the search is inverted here. We're scanning aDest, one char at a time
//but doing the search against the given set. That's why we use 0 as the offset below.
if((0<aDest.mLength) && (0<aSet.mLength)){
while(++index<(PRInt32)aDest.mLength) {
PRUnichar theChar=GetCharAt(aDest,index);
thePos=gFindChars[aSet.mCharSize](aSet.mStr,aSet.mLength,0,theChar,aIgnoreCase,aSet.mLength);
if(kNotFound!=thePos)
return index;
} //while
}
return kNotFound;
}
/**************************************************************
Reverse Searching methods...
**************************************************************/
/**
* This searches aDest (in reverse) for a given substring
*
* @update gess 2/18/00
* @param aDest string to search
* @param aTarget is the substring you're trying to find.
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search (counting from left)
* @param aCount tell us how many iterations to perform from offset
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::RFindSubstr(const nsStr& aDest,const nsStr& aTarget,PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
if(anOffset<0)
anOffset=(PRInt32)aDest.mLength-1;
if(aCount<0)
aCount = aDest.mLength;
if((0<aDest.mLength) && ((PRUint32)anOffset<aDest.mLength) && (aTarget.mLength)) {
if(0<aCount) {
PRInt32 aDelta = (aDest.mCharSize == eOneByte) ? 1 : 2;
const char* root = aDest.mStr;
const char* destLast = root+(aDest.mLength*aDelta); //pts to last char in aDest (likely null)
const char* rightmost = root+(anOffset*aDelta);
const char* min = rightmost-((aCount-1)*aDelta);
const char* leftmost = (min<root) ? root: min;
while(leftmost<=rightmost) {
//don't forget to divide by delta in next text (bug found by rhp)...
if(aTarget.mLength<=PRUint32((destLast-rightmost)/aDelta)) {
PRInt32 result=(*gCompare[aDest.mCharSize][aTarget.mCharSize])(rightmost,aTarget.mStr,aTarget.mLength,aIgnoreCase);
if(0==result) {
return (rightmost-root)/aDelta;
}
} //if
rightmost-=aDelta;
} //while
}
}
return kNotFound;
}
/**
* This searches aDest (in reverse) for a given character
*
* @update gess 2/04/00
* @param aDest string to search
* @param char is the character you're trying to find.
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search; -1 means start at very end (mLength)
* @param aCount tell us how many iterations to perform from offset; -1 means use full length.
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
return gRFindChars[aDest.mCharSize](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase,aCount);
}
/**
* This searches aDest (in reverese) for a character found in aSet.
*
* @update gess 3/25/98
* @param aDest string to search
* @param aSet contains a list of chars to be searched for
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset) {
//NS_PRECONDITION(aSet.mLength!=1,kCallRFindChar);
PRInt32 index=(0<=anOffset) ? anOffset : aDest.mLength;
PRInt32 thePos;
//note that the search is inverted here. We're scanning aDest, one char at a time
//but doing the search against the given set. That's why we use 0 as the offset below.
if(0<aDest.mLength) {
while(--index>=0) {
PRUnichar theChar=GetCharAt(aDest,index);
thePos=gFindChars[aSet.mCharSize](aSet.mStr,aSet.mLength,0,theChar,aIgnoreCase,aSet.mLength);
if(kNotFound!=thePos)
return index;
} //while
}
return kNotFound;
}
/**
* Compare source and dest strings, up to an (optional max) number of chars
* @param aDest is the first str to compare
* @param aSource is the second str to compare
* @param aCount -- if (-1), then we use length of longer string; if (0<aCount) then it gives the max # of chars to compare
* @param aIgnorecase tells us whether to search with case sensitivity
* @return aDest<aSource=-1;aDest==aSource==0;aDest>aSource=1
*/
PRInt32 nsStr::StrCompare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase) {
PRInt32 result=0;
if(aCount) {
PRInt32 minlen=(aSource.mLength<aDest.mLength) ? aSource.mLength : aDest.mLength;
if(0==minlen) {
if ((aDest.mLength == 0) && (aSource.mLength == 0))
return 0;
if (aDest.mLength == 0)
return -1;
return 1;
}
PRInt32 theCount = (aCount<0) ? minlen: MinInt(aCount,minlen);
result=(*gCompare[aDest.mCharSize][aSource.mCharSize])(aDest.mStr,aSource.mStr,theCount,aIgnoreCase);
if (0==result) {
if(-1==aCount) {
//Since the caller didn't give us a length to test, and minlen characters matched,
//we have to assume that the longer string is greater.
if (aDest.mLength != aSource.mLength) {
//we think they match, but we've only compared minlen characters.
//if the string lengths are different, then they don't really match.
result = (aDest.mLength<aSource.mLength) ? -1 : 1;
}
} //if
}
}
return result;
}
/**
* Overwrites the contents of dest at offset with contents of aSource
*
* @param aDest is the first str to compare
* @param aSource is the second str to compare
* @param aDestOffset is the offset within aDest where source should be copied
* @return error code
*/
void nsStr::Overwrite(nsStr& aDest,const nsStr& aSource,PRInt32 aDestOffset) {
if(aDest.mLength && aSource.mLength) {
if((aDest.mLength-aDestOffset)>=aSource.mLength) {
//if you're here, then both dest and source have valid lengths
//and there's enough room in dest (at offset) to contain source.
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDestOffset,aSource.mStr,0,aSource.mLength);
}
}
}
//----------------------------------------------------------------------------------------
PRBool nsStr::Alloc(nsStr& aDest,PRUint32 aCount) {
static int mAllocCount=0;
mAllocCount++;
#ifdef NS_USE_OLD_STRING_ALLOCATION_STRATEGY
//we're given the acount value in charunits; now scale up to next multiple.
PRUint32 theNewCapacity=kDefaultStringSize;
while(theNewCapacity<aCount){
theNewCapacity<<=1;
}
aDest.mCapacity=theNewCapacity++;
PRUint32 theSize=(theNewCapacity<<aDest.mCharSize);
aDest.mStr = (char*)nsMemory::Alloc(theSize);
#else
// the new strategy is, allocate exact size, double on grows
aDest.mCapacity = aCount;
aDest.mStr = (char*)nsMemory::Alloc((aCount+1)<<aDest.mCharSize);
#endif
if(aDest.mStr) {
aDest.mOwnsBuffer=1;
gStringAcquiredMemory=PR_TRUE;
}
else gStringAcquiredMemory=PR_FALSE;
return gStringAcquiredMemory;
}
PRBool nsStr::Free(nsStr& aDest){
if(aDest.mStr){
if(aDest.mOwnsBuffer){
nsMemory::Free(aDest.mStr);
}
aDest.mStr=0;
aDest.mOwnsBuffer=0;
return PR_TRUE;
}
return PR_FALSE;
}
PRBool nsStr::Realloc(nsStr& aDest,PRUint32 aCount){
nsStr temp;
memcpy(&temp,&aDest,sizeof(aDest));
PRBool result=Alloc(temp,aCount);
if(result) {
Free(aDest);
aDest.mStr=temp.mStr;
aDest.mCapacity=temp.mCapacity;
aDest.mOwnsBuffer=temp.mOwnsBuffer;
}
return result;
}
/**
* Retrieve last memory error
*
* @update gess 10/11/99
* @return memory error (usually returns PR_TRUE)
*/
PRBool nsStr::DidAcquireMemory(void) {
return gStringAcquiredMemory;
}
//----------------------------------------------------------------------------------------
CBufDescriptor::CBufDescriptor(char* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
mBuffer=aString;
mCharSize=eOneByte;
mStackBased=aStackBased;
mIsConst=PR_FALSE;
mLength=mCapacity=0;
if(aString && aCapacity>1) {
mCapacity=aCapacity-1;
mLength=(-1==aLength) ? strlen(aString) : aLength;
if(mLength>PRInt32(mCapacity))
mLength=mCapacity;
}
}
CBufDescriptor::CBufDescriptor(const char* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
mBuffer=(char*)aString;
mCharSize=eOneByte;
mStackBased=aStackBased;
mIsConst=PR_TRUE;
mLength=mCapacity=0;
if(aString && aCapacity>1) {
mCapacity=aCapacity-1;
mLength=(-1==aLength) ? strlen(aString) : aLength;
if(mLength>PRInt32(mCapacity))
mLength=mCapacity;
}
}
CBufDescriptor::CBufDescriptor(PRUnichar* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
mBuffer=(char*)aString;
mCharSize=eTwoByte;
mStackBased=aStackBased;
mLength=mCapacity=0;
mIsConst=PR_FALSE;
if(aString && aCapacity>1) {
mCapacity=aCapacity-1;
mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength;
if(mLength>PRInt32(mCapacity))
mLength=mCapacity;
}
}
CBufDescriptor::CBufDescriptor(const PRUnichar* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
mBuffer=(char*)aString;
mCharSize=eTwoByte;
mStackBased=aStackBased;
mLength=mCapacity=0;
mIsConst=PR_TRUE;
if(aString && aCapacity>1) {
mCapacity=aCapacity-1;
mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength;
if(mLength>PRInt32(mCapacity))
mLength=mCapacity;
}
}
//----------------------------------------------------------------------------------------
PRUint32
nsStr::HashCode(const nsStr& aDest)
{
if (aDest.mCharSize == eTwoByte)
return nsCRT::HashCode(aDest.mUStr);
else
return nsCRT::HashCode(aDest.mStr);
}
#ifdef NS_STR_STATS
#include <ctype.h>
#ifdef XP_MAC
#define isascii(c) ((unsigned)(c) < 0x80)
#endif
void
nsStr::Print(const nsStr& aDest, FILE* out, PRBool truncate)
{
PRInt32 printLen = (PRInt32)aDest.mLength;
if (aDest.mCharSize == eOneByte) {
const char* chars = aDest.mStr;
while (printLen-- && (!truncate || *chars != '\n')) {
fputc(*chars++, out);
}
}
else {
const PRUnichar* chars = aDest.mUStr;
while (printLen-- && (!truncate || *chars != '\n')) {
if (isascii(*chars))
fputc((char)(*chars++), out);
else
fputc('-', out);
}
}
}
////////////////////////////////////////////////////////////////////////////////
// String Usage Statistics Routines
static PLHashTable* gStringInfo = nsnull;
PRLock* gStringInfoLock = nsnull;
PRBool gNoStringInfo = PR_FALSE;
nsStringInfo::nsStringInfo(nsStr& str)
: mCount(0)
{
nsStr::Initialize(mStr, str.mCharSize);
nsStr::StrAssign(mStr, str, 0, -1);
// nsStr::Print(mStr, stdout);
// fputc('\n', stdout);
}
PR_EXTERN(PRHashNumber)
nsStr_Hash(const void* key)
{
nsStr* str = (nsStr*)key;
return nsStr::HashCode(*str);
}
PR_EXTERN(PRIntn)
nsStr_Compare(const void *v1, const void *v2)
{
nsStr* str1 = (nsStr*)v1;
nsStr* str2 = (nsStr*)v2;
return nsStr::StrCompare(*str1, *str2, -1, PR_FALSE) == 0;
}
nsStringInfo*
nsStringInfo::GetInfo(nsStr& str)
{
if (gStringInfo == nsnull) {
gStringInfo = PL_NewHashTable(1024,
nsStr_Hash,
nsStr_Compare,
PL_CompareValues,
NULL, NULL);
gStringInfoLock = PR_NewLock();
}
PR_Lock(gStringInfoLock);
nsStringInfo* info =
(nsStringInfo*)PL_HashTableLookup(gStringInfo, &str);
if (info == NULL) {
gNoStringInfo = PR_TRUE;
info = new nsStringInfo(str);
if (info) {
PLHashEntry* e = PL_HashTableAdd(gStringInfo, &info->mStr, info);
if (e == NULL) {
delete info;
info = NULL;
}
}
gNoStringInfo = PR_FALSE;
}
PR_Unlock(gStringInfoLock);
return info;
}
void
nsStringInfo::Seen(nsStr& str)
{
if (!gNoStringInfo) {
nsStringInfo* info = GetInfo(str);
info->mCount++;
}
}
void
nsStringInfo::Report(FILE* out)
{
if (gStringInfo) {
fprintf(out, "\n== String Stats\n");
PL_HashTableEnumerateEntries(gStringInfo, nsStringInfo::ReportEntry, out);
}
}
PRIntn
nsStringInfo::ReportEntry(PLHashEntry *he, PRIntn i, void *arg)
{
nsStringInfo* entry = (nsStringInfo*)he->value;
FILE* out = (FILE*)arg;
fprintf(out, "%d ==> (%d) ", entry->mCount, entry->mStr.mLength);
nsStr::Print(entry->mStr, out, PR_TRUE);
fputc('\n', out);
return HT_ENUMERATE_NEXT;
}
#endif // NS_STR_STATS
////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,523 @@
/* -*- 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):
* Rick Gessner <rickg@netscape.com> (original author)
* Scott Collins <scc@mozilla.org>
*/
/***********************************************************************
MODULE NOTES:
1. There are two philosophies to building string classes:
A. Hide the underlying buffer & offer API's allow indirect iteration
B. Reveal underlying buffer, risk corruption, but gain performance
We chose the option B for performance reasons.
2 Our internal buffer always holds capacity+1 bytes.
The nsStr struct is a simple structure (no methods) that contains
the necessary info to be described as a string. This simple struct
is manipulated by the static methods provided in this class.
(Which effectively makes this a library that works on structs).
There are also object-based versions called nsString and nsAutoString
which use nsStr but makes it look at feel like an object.
***********************************************************************/
/***********************************************************************
ASSUMPTIONS:
1. nsStrings and nsAutoString are always null terminated. However,
since it maintains a length byte, you can store NULL's inside
the string. Just be careful passing such buffers to 3rd party
API's that assume that NULL always terminate the buffer.
2. nsCStrings can be upsampled into nsString without data loss
3. Char searching is faster than string searching. Use char interfaces
if your needs will allow it.
4. It's easy to use the stack for nsAutostring buffer storage (fast too!).
See the CBufDescriptor class in this file.
5. If you don't provide the optional count argument to Append() and Insert(),
the method will assume that the given buffer is terminated by the first
NULL it encounters.
6. Downsampling from nsString to nsCString can be lossy -- avoid it if possible!
7. Calls to ToNewCString() and ToNewUnicode() should be matched with calls to nsMemory::Free().
***********************************************************************/
/**********************************************************************************
AND NOW FOR SOME GENERAL DOCUMENTATION ON STRING USAGE...
The fundamental datatype in the string library is nsStr. It's a structure that
provides the buffer storage and meta-info. It also provides a C-style library
of functions for direct manipulation (for those of you who prefer K&R to Bjarne).
Here's a diagram of the class hierarchy:
nsStr
|___nsString
| |
| ------nsAutoString
|
|___nsCString
|
------nsCAutoString
Why so many string classes? The 4 variants give you the control you need to
determine the best class for your purpose. There are 2 dimensions to this
flexibility: 1) stack vs. heap; and 2) 1-byte chars vs. 2-byte chars.
Note: While nsAutoString and nsCAutoString begin life using stack-based storage,
they may not stay that way. Like all nsString classes, autostrings will
automatically grow to contain the data you provide. When autostrings
grow beyond their intrinsic buffer, they switch to heap based allocations.
(We avoid alloca to avoid considerable platform difficulties; see the
GNU documentation for more details).
I should also briefly mention that all the string classes use a "memory agent"
object to perform memory operations. This class proxies the standard nsMemory
for actual memory calls, but knows the structure of nsStr making heap operations
more localized.
CHOOSING A STRING CLASS:
In order to choose a string class for you purpose, use this handy table:
heap-based stack-based
-----------------------------------
ascii data | nsCString nsCAutoString |
|----------------------------------
unicode data | nsString nsAutoString |
-----------------------------------
Note: The i18n folks will stenuously object if we get too carried away with the
use of nsCString's that pass interface boundaries. Try to limit your
use of these to external interfaces that demand them, or for your own
private purposes in cases where they'll never be seen by humans.
--- FAQ ---
Q. When should I use nsCString instead of nsString?
A. You should really try to stick with nsString, so that we stay as unicode
compliant as possible. But there are cases where an interface you use requires
a char*. In such cases, it's fair to use nsCString.
Q. I know that my string is going to be a certain size. Can I pre-size my nsString?
A. Yup, here's how:
{
nsString mBuffer;
mBuffer.SetCapacity(aReasonableSize);
}
Q. Should nsAutoString or nsCAutoString ever live on the heap?
A. That would be counterproductive. The point of nsAutoStrings is to preallocate your
buffers, and to auto-destroy the string when it goes out of scope.
Q. I already have a char*. Can I use the nsString functionality on that buffer?
A. Yes you can -- by using an intermediate class called CBufDescriptor.
The CBufDescriptor class is used to tell nsString about an external buffer (heap or stack) to use
instead of it's own internal buffers. Here's an example:
{
char theBuffer[256];
CBufDescritor theBufDecriptor( theBuffer, PR_TRUE, sizeof(theBuffer), 0);
nsCAutoString s3( theBufDescriptor );
s3="HELLO, my name is inigo montoya, you killed my father, prepare to die!.";
}
The assignment statment to s3 will cause the given string to be written to your
stack-based buffer via the normal nsString/nsCString interfaces. Cool, huh?
Note however that just like any other nsStringXXX use, if you write more data
than will fit in the buffer, a visit to the heap manager will be in order.
Q. What is the simplest way to get from a char* to PRUnichar*?
A. The simplest way is by construction (or assignment):
{
char* theBuf = "hello there";
nsAutoString foo(theBuf);
}
If you don't want the char* to be copied into the nsAutoString, the use a
CBufDescriptor instead.
**********************************************************************************/
#ifndef _nsStr
#define _nsStr
#include "nscore.h"
#include "nsMemory.h"
#include <string.h>
#include <stdio.h>
#include "plhash.h"
//----------------------------------------------------------------------------------------
enum eCharSize {eOneByte=0,eTwoByte=1};
#define kDefaultCharSize eTwoByte
#define kRadix10 (10)
#define kRadix16 (16)
#define kAutoDetect (100)
#define kRadixUnknown (kAutoDetect+1)
#define IGNORE_CASE (PR_TRUE)
const PRInt32 kDefaultStringSize = 64;
const PRInt32 kNotFound = -1;
//----------------------------------------------------------------------------------------
class NS_COM CBufDescriptor {
public:
CBufDescriptor(char* aString, PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
CBufDescriptor(const char* aString, PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
CBufDescriptor(PRUnichar* aString, PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
CBufDescriptor(const PRUnichar* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
char* mBuffer;
eCharSize mCharSize;
PRUint32 mCapacity;
PRInt32 mLength;
PRBool mStackBased;
PRBool mIsConst;
};
//----------------------------------------------------------------------------------------
struct NS_COM nsStr {
nsStr() {
MOZ_COUNT_CTOR(nsStr);
}
~nsStr() {
MOZ_COUNT_DTOR(nsStr);
}
/**
* This method initializes an nsStr for use
*
* @update gess 01/04/99
* @param aString is the nsStr to be initialized
* @param aCharSize tells us the requested char size (1 or 2 bytes)
*/
static void Initialize(nsStr& aDest,eCharSize aCharSize);
/**
* This method initializes an nsStr for use
*
* @update gess 01/04/99
* @param aString is the nsStr to be initialized
* @param aCharSize tells us the requested char size (1 or 2 bytes)
*/
static void Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 aLength,eCharSize aCharSize,PRBool aOwnsBuffer);
/**
* This method destroys the given nsStr, and *MAY*
* deallocate it's memory depending on the setting
* of the internal mOwnsBUffer flag.
*
* @update gess 01/04/99
* @param aString is the nsStr to be manipulated
* @param anAgent is the allocator to be used to the nsStr
*/
static void Destroy(nsStr& aDest);
/**
* These methods are where memory allocation/reallocation occur.
*
* @update gess 01/04/99
* @param aString is the nsStr to be manipulated
* @param anAgent is the allocator to be used on the nsStr
* @return
*/
static PRBool EnsureCapacity(nsStr& aString,PRUint32 aNewLength);
static PRBool GrowCapacity(nsStr& aString,PRUint32 aNewLength);
/**
* These methods are used to append content to the given nsStr
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param aSource is the buffer to be copied from
* @param anOffset tells us where in source to start copying
* @param aCount tells us the (max) # of chars to copy
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrAppend(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount);
/**
* These methods are used to assign contents of a source string to dest string
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param aSource is the buffer to be copied from
* @param anOffset tells us where in source to start copying
* @param aCount tells us the (max) # of chars to copy
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrAssign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount);
/**
* These methods are used to insert content from source string to the dest nsStr
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param aDestOffset tells us where in dest to start insertion
* @param aSource is the buffer to be copied from
* @param aSrcOffset tells us where in source to start copying
* @param aCount tells us the (max) # of chars to insert
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrInsert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount);
/**
* This method deletes chars from the given str.
* The given allocator may choose to resize the str as well.
*
* @update gess 01/04/99
* @param aDest is the nsStr to be deleted from
* @param aDestOffset tells us where in dest to start deleting
* @param aCount tells us the (max) # of chars to delete
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount);
/**
* This method is used to truncate the given string.
* The given allocator may choose to resize the str as well (but it's not likely).
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param aDestOffset tells us where in dest to start insertion
* @param aSource is the buffer to be copied from
* @param aSrcOffset tells us where in source to start copying
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void Truncate(nsStr& aDest,PRUint32 aDestOffset);
/**
* This method is used to perform a case conversion on the given string
*
* @update gess 01/04/99
* @param aDest is the nsStr to be case shifted
* @param toUpper tells us to go upper vs. lower
*/
static void ChangeCase(nsStr& aDest,PRBool aToUpper);
/**
* This method trims chars (given in aSet) from the edges of given buffer
*
* @update gess 01/04/99
* @param aDest is the buffer to be manipulated
* @param aSet tells us which chars to remove from given buffer
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
*/
static void Trim(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing);
/**
* This method compresses duplicate runs of a given char from the given buffer
*
* @update gess 01/04/99
* @param aDest is the buffer to be manipulated
* @param aSet tells us which chars to compress from given buffer
* @param aChar is the replacement char
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
*/
static void CompressSet(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing);
/**
* This method removes all occurances of chars in given set from aDest
*
* @update gess 01/04/99
* @param aDest is the buffer to be manipulated
* @param aSet tells us which chars to compress from given buffer
* @param aChar is the replacement char
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
*/
static void StripChars(nsStr& aDest,const char* aSet);
/**
* This method compares the data bewteen two nsStr's
*
* @update gess 01/04/99
* @param aStr1 is the first buffer to be compared
* @param aStr2 is the 2nd buffer to be compared
* @param aCount is the number of chars to compare
* @param aIgnorecase tells us whether to use a case-sensitive comparison
* @return -1,0,1 depending on <,==,>
*/
static PRInt32 StrCompare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase);
/**
* These methods scan the given string for 1 or more chars in a given direction
*
* @update gess 01/04/99
* @param aDest is the nsStr to be searched to
* @param aSource (or aChar) is the substr we're looking to find
* @param aIgnoreCase tells us whether to search in a case-sensitive manner
* @param anOffset tells us where in the dest string to start searching
* @return the index of the source (substr) in dest, or -1 (kNotFound) if not found.
*/
static PRInt32 FindSubstr(const nsStr& aDest,const nsStr& aSource, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
static PRInt32 FindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
static PRInt32 FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset);
static PRInt32 RFindSubstr(const nsStr& aDest,const nsStr& aSource, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
static PRInt32 RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
static PRInt32 RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset);
static void Overwrite(nsStr& aDest,const nsStr& aSource,PRInt32 anOffset);
static PRBool DidAcquireMemory(void);
/**
* Returns a hash code for the string for use in a PLHashTable.
*/
static PRUint32 HashCode(const nsStr& aDest);
#ifdef NS_STR_STATS
/**
* Prints an nsStr. If truncate is true, the string is only printed up to
* the first newline. (Note: The current implementation doesn't handle
* non-ascii unicode characters.)
*/
static void Print(const nsStr& aDest, FILE* out, PRBool truncate = PR_FALSE);
#endif
PRUint32 mLength;
PRUint32 mCapacity;
eCharSize mCharSize;
PRBool mOwnsBuffer;
union {
char* mStr;
PRUnichar* mUStr;
};
private:
static PRBool Alloc(nsStr& aString,PRUint32 aCount);
static PRBool Realloc(nsStr& aString,PRUint32 aCount);
static PRBool Free(nsStr& aString);
};
/**************************************************************
A couple of tiny helper methods used in the string classes.
**************************************************************/
inline PRInt32 MinInt(PRInt32 anInt1,PRInt32 anInt2){
return (anInt1<anInt2) ? anInt1 : anInt2;
}
inline PRInt32 MaxInt(PRInt32 anInt1,PRInt32 anInt2){
return (anInt1<anInt2) ? anInt2 : anInt1;
}
inline void AddNullTerminator(nsStr& aDest) {
if(eTwoByte==aDest.mCharSize)
aDest.mUStr[aDest.mLength]=0;
else aDest.mStr[aDest.mLength]=0;
}
/**
* Deprecated: don't use |Recycle|, just call |nsMemory::Free| directly
*
* Return the given buffer to the heap manager. Calls allocator::Free()
* @return string length
*/
inline void Recycle( char* aBuffer) { nsMemory::Free(aBuffer); }
inline void Recycle( PRUnichar* aBuffer) { nsMemory::Free(aBuffer); }
/**
* This method is used to access a given char in the given string
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param anIndex tells us where in dest to get the char from
* @return the given char, or 0 if anIndex is out of range
*/
inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex){
if(anIndex<aDest.mLength) {
return (eTwoByte==aDest.mCharSize) ? aDest.mUStr[anIndex] : (PRUnichar)aDest.mStr[anIndex];
}//if
return 0;
}
#ifdef NS_STR_STATS
class nsStringInfo {
public:
nsStringInfo(nsStr& str);
~nsStringInfo() {}
static nsStringInfo* GetInfo(nsStr& str);
static void Seen(nsStr& str);
static void Report(FILE* out = stdout);
static PRIntn ReportEntry(PLHashEntry *he, PRIntn i, void *arg);
protected:
nsStr mStr;
PRUint32 mCount;
};
#define NSSTR_SEEN(str) nsStringInfo::Seen(str)
#else // !NS_STR_STATS
#define NSSTR_SEEN(str) /* nothing */
#endif // !NS_STR_STATS
#endif // _nsStr

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,629 @@
/* -*- 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):
* Rick Gessner <rickg@netscape.com> (original author)
* Scott Collins <scc@mozilla.org>
*/
/***********************************************************************
MODULE NOTES:
See nsStr.h for a more general description of string classes.
This version of the nsString class offers many improvements over the
original version:
1. Wide and narrow chars
2. Allocators
3. Much smarter autostrings
4. Subsumable strings
***********************************************************************/
#ifndef _nsCString_
#define _nsCString_
#include "nsString2.h"
#include "prtypes.h"
#include "nscore.h"
#include <stdio.h>
#include "nsStr.h"
#include "nsIAtom.h"
#include "nsAWritableString.h"
class NS_COM nsSubsumeCStr;
class NS_COM nsCString :
public nsAWritableCString,
public nsStr {
protected:
virtual const void* Implementation() const { return "nsCString"; }
virtual const char* GetReadableFragment( nsReadableFragment<char>&, nsFragmentRequest, PRUint32 ) const;
virtual char* GetWritableFragment( nsWritableFragment<char>&, nsFragmentRequest, PRUint32 );
public:
/**
* Default constructor.
*/
nsCString();
/**
* This is our copy constructor
* @param reference to another nsCString
*/
nsCString(const nsCString& aString);
explicit nsCString( const nsAReadableCString& );
explicit nsCString(const char*);
nsCString(const char*, PRInt32);
/**
* This constructor takes a subsumestr
* @param reference to subsumestr
*/
explicit nsCString(nsSubsumeCStr& aSubsumeStr);
/**
* Destructor
*
*/
virtual ~nsCString();
/**
* Retrieve the length of this string
* @return string length
*/
virtual PRUint32 Length() const { return mLength; }
/**
* Retrieve the size of this string
* @return string length
*/
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
/**
* Call this method if you want to force a different string capacity
* @update gess7/30/98
* @param aLength -- contains new length for mStr
* @return
*/
void SetLength(PRUint32 aLength);
/**
* Sets the new length of the string.
* @param aLength is new string length.
* @return nada
*/
void SetCapacity(PRUint32 aLength);
/**
* This method truncates this string to given length.
*
* @param anIndex -- new length of string
* @return nada
*/
void Truncate(PRUint32 anIndex=0) {
NS_ASSERTION(anIndex<=mLength, "Can't use |Truncate()| to make a string longer.");
if ( anIndex < mLength )
SetLength(anIndex);
}
/**********************************************************************
Accessor methods...
*********************************************************************/
/**
* Retrieve const ptr to internal buffer; DO NOT TRY TO FREE IT!
*/
const char* GetBuffer(void) const;
PRBool SetCharAt(PRUnichar aChar,PRUint32 anIndex);
/**********************************************************************
Lexomorphic transforms...
*********************************************************************/
/**
* Converts chars in this to lowercase
* @update gess 7/27/98
*/
void ToLowerCase();
/**
* Converts chars in this to lowercase, and
* stores them in aOut
* @update gess 7/27/98
* @param aOut is a string to contain result
*/
void ToLowerCase(nsCString& aString) const;
/**
* Converts chars in this to uppercase
* @update gess 7/27/98
*/
void ToUpperCase();
/**
* Converts chars in this to lowercase, and
* stores them in a given output string
* @update gess 7/27/98
* @param aOut is a string to contain result
*/
void ToUpperCase(nsCString& aString) const;
/**
* This method is used to remove all occurances of the
* characters found in aSet from this string.
*
* @param aSet -- characters to be cut from this
* @return *this
*/
void StripChars(const char* aSet);
void StripChar(PRUnichar aChar,PRInt32 anOffset=0);
void StripChar(char aChar,PRInt32 anOffset=0) { StripChar((PRUnichar) (unsigned char)aChar,anOffset); }
/**
* This method strips whitespace throughout the string
*
* @return this
*/
void StripWhitespace();
/**
* swaps occurence of 1 string for another
*
* @return this
*/
void ReplaceChar(PRUnichar aOldChar,PRUnichar aNewChar);
void ReplaceChar(const char* aSet,PRUnichar aNewChar);
void ReplaceSubstring(const nsCString& aTarget,const nsCString& aNewValue);
void ReplaceSubstring(const char* aTarget,const char* aNewValue);
PRInt32 CountChar(PRUnichar aChar);
/**
* This method trims characters found in aTrimSet from
* either end of the underlying string.
*
* @param aTrimSet -- contains chars to be trimmed from
* both ends
* @param aEliminateLeading
* @param aEliminateTrailing
* @param aIgnoreQuotes
* @return this
*/
void Trim(const char* aSet,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE,PRBool aIgnoreQuotes=PR_FALSE);
/**
* This method strips whitespace from string.
* You can control whether whitespace is yanked from
* start and end of string as well.
*
* @param aEliminateLeading controls stripping of leading ws
* @param aEliminateTrailing controls stripping of trailing ws
* @return this
*/
void CompressSet(const char* aSet, PRUnichar aChar,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
/**
* This method strips whitespace from string.
* You can control whether whitespace is yanked from
* start and end of string as well.
*
* @param aEliminateLeading controls stripping of leading ws
* @param aEliminateTrailing controls stripping of trailing ws
* @return this
*/
void CompressWhitespace( PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
/**********************************************************************
string conversion methods...
*********************************************************************/
//#ifndef STANDALONE_STRING_TESTS
operator char*() {return mStr;}
operator const char*() const {return (const char*)mStr;}
//#endif
/**
* This method constructs a new nsCString that is a clone
* of this string.
*
*/
nsCString* ToNewString() const;
/**
* Creates an ISOLatin1 clone of this string
* Note that calls to this method should be matched with calls to Recycle().
* @return ptr to new isolatin1 string
*/
char* ToNewCString() const;
/**
* Creates a unicode clone of this string
* Note that calls to this method should be matched with calls to Recycle().
* @return ptr to new unicode string
*/
PRUnichar* ToNewUnicode() const;
/**
* Copies data from internal buffer onto given char* buffer
* NOTE: This only copies as many chars as will fit in given buffer (clips)
* @param aBuf is the buffer where data is stored
* @param aBuflength is the max # of chars to move to buffer
* @return ptr to given buffer
*/
char* ToCString(char* aBuf,PRUint32 aBufLength,PRUint32 anOffset=0) const;
/**
* Perform string to float conversion.
* @param aErrorCode will contain error if one occurs
* @return float rep of string value
*/
float ToFloat(PRInt32* aErrorCode) const;
/**
* Perform string to int conversion.
* @param aErrorCode will contain error if one occurs
* @param aRadix tells us which radix to assume; kAutoDetect tells us to determine the radix for you.
* @return int rep of string value, and possible (out) error code
*/
PRInt32 ToInteger(PRInt32* aErrorCode,PRUint32 aRadix=kRadix10) const;
/**********************************************************************
String manipulation methods...
*********************************************************************/
/**
* assign given string to this string
* @param aStr: buffer to be assigned to this
* @param aCount is the length of the given str (or -1) if you want me to determine its length
* NOTE: IFF you pass -1 as aCount, then your buffer must be null terminated.
*
* @return this
*/
nsCString& operator=( const nsCString& aString ) { Assign(aString); return *this; }
nsCString& operator=( const nsAReadableCString& aReadable ) { Assign(aReadable); return *this; }
nsCString& operator=( const nsPromiseReadable<char>& aReadable ) { Assign(aReadable); return *this; }
nsCString& operator=( const char* aPtr ) { Assign(aPtr); return *this; }
nsCString& operator=( char aChar ) { Assign(aChar); return *this; }
void AssignWithConversion(const PRUnichar*,PRInt32=-1);
void AssignWithConversion( const nsString& aString );
void AssignWithConversion( const nsAReadableString& aString );
void AssignWithConversion(PRUnichar);
/*
* Appends n characters from given string to this,
*
* @param aString is the source to be appended to this
* @param aCount -- number of chars to copy; -1 tells us to compute the strlen for you
* NOTE: IFF you pass -1 as aCount, then your buffer must be null terminated.
*
* @return number of chars copied
*/
void AppendWithConversion(const nsString&, PRInt32=-1);
void AppendWithConversion(PRUnichar aChar);
void AppendWithConversion( const nsAReadableString& aString );
void AppendWithConversion(const PRUnichar*, PRInt32=-1);
// Why no |AppendWithConversion(const PRUnichar*, PRInt32)|? --- now I know, because implicit construction hid the need for this routine
void AppendInt(PRInt32 aInteger,PRInt32 aRadix=10); //radix=8,10 or 16
void AppendFloat( double aFloat );
virtual void do_AppendFromReadable( const nsAReadableCString& );
/*
* Copies n characters from this string to given string,
* starting at the leftmost offset.
*
*
* @param aCopy -- Receiving string
* @param aCount -- number of chars to copy
* @return number of chars copied
*/
PRUint32 Left(nsCString& aCopy,PRInt32 aCount) const;
/*
* Copies n characters from this string to given string,
* starting at the given offset.
*
*
* @param aCopy -- Receiving string
* @param aCount -- number of chars to copy
* @param anOffset -- position where copying begins
* @return number of chars copied
*/
PRUint32 Mid(nsCString& aCopy,PRUint32 anOffset,PRInt32 aCount) const;
/*
* Copies n characters from this string to given string,
* starting at rightmost char.
*
*
* @param aCopy -- Receiving string
* @param aCount -- number of chars to copy
* @return number of chars copied
*/
PRUint32 Right(nsCString& aCopy,PRInt32 aCount) const;
void InsertWithConversion(PRUnichar aChar,PRUint32 anOffset);
// Why no |InsertWithConversion(PRUnichar*)|?
virtual void do_InsertFromReadable( const nsAReadableCString&, PRUint32 );
/**********************************************************************
Searching methods...
*********************************************************************/
/**
* Search for given substring within this string
*
* @param aString is substring to be sought in this
* @param aIgnoreCase selects case sensitivity
* @param anOffset tells us where in this strig to start searching
* @param aCount tells us how many iterations to make starting at the given offset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 Find(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
/**
* Search for given char within this string
*
* @param aString is substring to be sought in this
* @param anOffset tells us where in this strig to start searching
* @param aIgnoreCase selects case sensitivity
* @param aCount tells us how many iterations to make starting at the given offset
* @return find pos in string, or -1 (kNotFound)
*/
PRInt32 FindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
/**
* This method searches this string for the first character
* found in the given charset
* @param aString contains set of chars to be found
* @param anOffset tells us where to start searching in this
* @return -1 if not found, else the offset in this
*/
PRInt32 FindCharInSet(const char* aString,PRInt32 anOffset=0) const;
PRInt32 FindCharInSet(const PRUnichar* aString,PRInt32 anOffset=0) const;
PRInt32 FindCharInSet(const nsStr& aString,PRInt32 anOffset=0) const;
/**
* This methods scans the string backwards, looking for the given string
* @param aString is substring to be sought in this
* @param aIgnoreCase tells us whether or not to do caseless compare
* @param aCount tells us how many iterations to make starting at the given offset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 RFind(const char* aCString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
/**
* Search for given char within this string
*
* @param aString is substring to be sought in this
* @param anOffset tells us where in this strig to start searching
* @param aIgnoreCase selects case sensitivity
* @return find pos in string, or -1 (kNotFound)
*/
PRInt32 RFindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
/**
* This method searches this string for the last character
* found in the given string
* @param aString contains set of chars to be found
* @param anOffset tells us where to start searching in this
* @return -1 if not found, else the offset in this
*/
PRInt32 RFindCharInSet(const char* aString,PRInt32 anOffset=-1) const;
PRInt32 RFindCharInSet(const PRUnichar* aString,PRInt32 anOffset=-1) const;
PRInt32 RFindCharInSet(const nsStr& aString,PRInt32 anOffset=-1) const;
/**********************************************************************
Comparison methods...
*********************************************************************/
/**
* Compares a given string type to this string.
* @update gess 7/27/98
* @param S is the string to be compared
* @param aIgnoreCase tells us how to treat case
* @param aCount tells us how many chars to compare
* @return -1,0,1
*/
PRInt32 CompareWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRInt32 CompareWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const nsString &aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsIgnoreCase(const char* aString,PRInt32 aCount=-1) const;
PRBool EqualsIgnoreCase(const PRUnichar* aString,PRInt32 aCount=-1) const;
void DebugDump(void) const;
static void Recycle(nsCString* aString);
static nsCString* CreateString(void);
private:
// NOT TO BE IMPLEMENTED
// these signatures help clients not accidentally call the wrong thing helped by C++ automatic integral promotion
void operator=( PRUnichar );
void AssignWithConversion( char );
void AssignWithConversion( const char*, PRInt32=-1 );
void AppendWithConversion( char );
void InsertWithConversion( char, PRUint32 );
};
// NS_DEF_STRING_COMPARISON_OPERATORS(nsCString, char)
NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsCString, char)
extern NS_COM int fputs(const nsCString& aString, FILE* out);
//ostream& operator<<(ostream& aStream,const nsCString& aString);
//virtual void DebugDump(ostream& aStream) const;
/**************************************************************
Here comes the AutoString class which uses internal memory
(typically found on the stack) for its default buffer.
If the buffer needs to grow, it gets reallocated on the heap.
**************************************************************/
class NS_COM nsCAutoString : public nsCString {
public:
virtual ~nsCAutoString();
nsCAutoString();
explicit nsCAutoString(const nsCString& );
explicit nsCAutoString(const nsAReadableCString& aString);
explicit nsCAutoString(const char* aString);
nsCAutoString(const char* aString,PRInt32 aLength);
explicit nsCAutoString(const CBufDescriptor& aBuffer);
#if defined(AIX) || defined(XP_OS2_VACPP)
explicit nsCAutoString(const nsSubsumeCStr& aSubsumeStr); // AIX and VAC++ require a const
#else
explicit nsCAutoString(nsSubsumeCStr& aSubsumeStr);
#endif // AIX || XP_OS2_VACPP
nsCAutoString& operator=( const nsCAutoString& aString ) { Assign(aString); return *this; }
private:
void operator=( PRUnichar ); // NOT TO BE IMPLEMENTED
public:
nsCAutoString& operator=( const nsAReadableCString& aReadable ) { Assign(aReadable); return *this; }
nsCAutoString& operator=( const nsPromiseReadable<char>& aReadable ) { Assign(aReadable); return *this; }
nsCAutoString& operator=( const char* aPtr ) { Assign(aPtr); return *this; }
nsCAutoString& operator=( char aChar ) { Assign(aChar); return *this; }
/**
* Retrieve the size of this string
* @return string length
*/
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
char mBuffer[kDefaultStringSize];
};
NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsCAutoString, char)
/**
* A helper class that converts a UCS2 string to UTF8
*/
class NS_COM NS_ConvertUCS2toUTF8
: public nsCAutoString
/*
...
*/
{
public:
explicit
NS_ConvertUCS2toUTF8( const PRUnichar* aString )
{
Append( aString, ~PRUint32(0) /* MAXINT */);
}
NS_ConvertUCS2toUTF8( const PRUnichar* aString, PRUint32 aLength )
{
Append( aString, aLength );
}
explicit
NS_ConvertUCS2toUTF8( PRUnichar aChar )
{
Append( &aChar, 1 );
}
explicit NS_ConvertUCS2toUTF8( const nsAReadableString& aString );
const char* get() const
{
return mStr;
}
operator const char*() const // to be deprecated, prefer |get()|
{
return get();
}
protected:
void Append( const PRUnichar* aString, PRUint32 aLength );
private:
// NOT TO BE IMPLEMENTED
NS_ConvertUCS2toUTF8( char );
};
/***************************************************************
The subsumestr class is very unusual.
It differs from a normal string in that it doesn't use normal
copy semantics when another string is assign to this.
Instead, it "steals" the contents of the source string.
This is very handy for returning nsString classes as part of
an operator+(...) for example, in that it cuts down the number
of copy operations that must occur.
You should probably not use this class unless you really know
what you're doing.
***************************************************************/
class NS_COM nsSubsumeCStr : public nsCString {
public:
explicit nsSubsumeCStr(nsStr& aString);
nsSubsumeCStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
nsSubsumeCStr(char* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
nsSubsumeCStr& operator=( const nsSubsumeCStr& aString ) { Assign(aString); return *this; }
nsSubsumeCStr& operator=( const nsAReadableCString& aReadable ) { Assign(aReadable); return *this; }
nsSubsumeCStr& operator=( const nsPromiseReadable<char>& aReadable ) { Assign(aReadable); return *this; }
nsSubsumeCStr& operator=( const char* aPtr ) { Assign(aPtr); return *this; }
nsSubsumeCStr& operator=( char aChar ) { Assign(aChar); return *this; }
private:
void operator=( PRUnichar ); // NOT TO BE IMPLEMENTED
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,743 @@
/* -*- 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):
* Rick Gessner <rickg@netscape.com> (original author)
* Scott Collins <scc@mozilla.org>
*/
/***********************************************************************
MODULE NOTES:
See nsStr.h for a more general description of string classes.
This version of the nsString class offers many improvements over the
original version:
1. Wide and narrow chars
2. Allocators
3. Much smarter autostrings
4. Subsumable strings
***********************************************************************/
#ifndef _nsString_
#define _nsString_
#include "prtypes.h"
#include "nscore.h"
#include <stdio.h>
#include "nsString.h"
#include "nsIAtom.h"
#include "nsStr.h"
#include "nsCRT.h"
#include "nsAWritableString.h"
#ifdef STANDALONE_MI_STRING_TESTS
class nsAReadableString { public: virtual ~nsAReadableString() { } };
class nsAWritableString : public nsAReadableString { public: virtual ~nsAWritableString() { } };
#endif
class nsISizeOfHandler;
#define nsString2 nsString
#define nsAutoString2 nsAutoString
class NS_COM nsSubsumeStr;
class NS_COM nsString :
public nsAWritableString,
public nsStr {
protected:
virtual const void* Implementation() const { return "nsString"; }
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 );
public:
/**
* Default constructor.
*/
nsString();
/**
* This is our copy constructor
* @param reference to another nsString
*/
nsString(const nsString& aString);
explicit nsString(const nsAReadableString&);
explicit nsString(const PRUnichar*);
nsString(const PRUnichar*, PRInt32);
/**
* This constructor takes a subsumestr
* @param reference to subsumestr
*/
#if defined(AIX) || defined(XP_OS2_VACPP)
explicit nsString(const nsSubsumeStr& aSubsumeStr); // AIX and VAC++ require a const here
#else
explicit nsString(nsSubsumeStr& aSubsumeStr);
#endif
/**
* Destructor
*
*/
virtual ~nsString();
/**
* Retrieve the length of this string
* @return string length
*/
virtual PRUint32 Length() const { return mLength; }
/**
* Retrieve the size of this string
* @return string length
*/
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
/**
* Call this method if you want to force a different string length
* @update gess7/30/98
* @param aLength -- contains new length for mStr
* @return
*/
void SetLength(PRUint32 aLength);
/**
* Sets the new length of the string.
* @param aLength is new string length.
* @return nada
*/
void SetCapacity(PRUint32 aLength);
/**
* This method truncates this string to given length.
*
* @param anIndex -- new length of string
* @return nada
*/
void Truncate(PRUint32 anIndex=0) {
NS_ASSERTION(anIndex<=mLength, "Can't use |Truncate()| to make a string longer.");
if ( anIndex < mLength )
SetLength(anIndex);
}
/**
* Determine whether or not the characters in this
* string are in store as 1 or 2 byte (unicode) strings.
*
* @return TRUE if ordered.
*/
PRBool IsUnicode(void) const {
PRBool result=PRBool(mCharSize==eTwoByte);
return result;
}
/**********************************************************************
Getters/Setters...
*********************************************************************/
/**
* Retrieve const ptr to internal buffer; DO NOT TRY TO FREE IT!
*/
const char* GetBuffer(void) const;
const PRUnichar* GetUnicode(void) const;
/**
* Set nth character.
*/
PRBool SetCharAt(PRUnichar aChar,PRUint32 anIndex);
/**********************************************************************
Lexomorphic transforms...
*********************************************************************/
/**
* Converts chars in this to lowercase
* @update gess 7/27/98
*/
void ToLowerCase();
/**
* Converts chars in this to lowercase, and
* stores them in aOut
* @update gess 7/27/98
* @param aOut is a string to contain result
*/
void ToLowerCase(nsString& aString) const;
/**
* Converts chars in this to uppercase
* @update gess 7/27/98
*/
void ToUpperCase();
/**
* Converts chars in this to lowercase, and
* stores them in a given output string
* @update gess 7/27/98
* @param aOut is a string to contain result
*/
void ToUpperCase(nsString& aString) const;
/**
* This method is used to remove all occurances of the
* characters found in aSet from this string.
*
* @param aSet -- characters to be cut from this
* @return *this
*/
void StripChars( const char* aSet );
void StripChar( PRUnichar aChar, PRInt32 anOffset=0 );
void StripChar( char aChar, PRInt32 anOffset=0 ) { StripChar((PRUnichar) (unsigned char)aChar,anOffset); }
void StripChar( PRInt32 anInt, PRInt32 anOffset=0 ) { StripChar((PRUnichar)anInt,anOffset); }
/**
* This method strips whitespace throughout the string
*
* @return this
*/
void StripWhitespace();
/**
* swaps occurence of 1 string for another
*
* @return this
*/
void ReplaceChar( PRUnichar anOldChar, PRUnichar aNewChar );
void ReplaceChar( const char* aSet, PRUnichar aNewChar );
void ReplaceSubstring( const nsString& aTarget, const nsString& aNewValue );
void ReplaceSubstring( const PRUnichar* aTarget, const PRUnichar* aNewValue );
PRInt32 CountChar( PRUnichar aChar );
/**
* This method trims characters found in aTrimSet from
* either end of the underlying string.
*
* @param aTrimSet -- contains chars to be trimmed from
* both ends
* @param aEliminateLeading
* @param aEliminateTrailing
* @param aIgnoreQuotes
* @return this
*/
void Trim(const char* aSet,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE,PRBool aIgnoreQuotes=PR_FALSE);
/**
* This method strips whitespace from string.
* You can control whether whitespace is yanked from
* start and end of string as well.
*
* @param aEliminateLeading controls stripping of leading ws
* @param aEliminateTrailing controls stripping of trailing ws
* @return this
*/
void CompressSet(const char* aSet, PRUnichar aChar,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
/**
* This method strips whitespace from string.
* You can control whether whitespace is yanked from
* start and end of string as well.
*
* @param aEliminateLeading controls stripping of leading ws
* @param aEliminateTrailing controls stripping of trailing ws
* @return this
*/
void CompressWhitespace( PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
/**********************************************************************
string conversion methods...
*********************************************************************/
/**
* This method constructs a new nsString is a clone of this string.
*
*/
nsString* ToNewString() const;
/**
* Creates an ISOLatin1 clone of this string
* Note that calls to this method should be matched with calls to Recycle().
* @return ptr to new isolatin1 string
*/
char* ToNewCString() const;
/**
* Creates an UTF8 clone of this string
* Note that calls to this method should be matched with calls to Recycle().
* @return ptr to new null-terminated UTF8 string
*/
char* ToNewUTF8String() const;
/**
* Creates a unicode clone of this string
* Note that calls to this method should be matched with calls to Recycle().
* @return ptr to new unicode string
*/
PRUnichar* ToNewUnicode() const;
/**
* Copies data from internal buffer onto given char* buffer
* NOTE: This only copies as many chars as will fit in given buffer (clips)
* @param aBuf is the buffer where data is stored
* @param aBuflength is the max # of chars to move to buffer
* @return ptr to given buffer
*/
char* ToCString(char* aBuf,PRUint32 aBufLength,PRUint32 anOffset=0) const;
/**
* Perform string to float conversion.
* @param aErrorCode will contain error if one occurs
* @return float rep of string value
*/
float ToFloat(PRInt32* aErrorCode) const;
/**
* Perform string to int conversion.
* @param aErrorCode will contain error if one occurs
* @param aRadix tells us which radix to assume; kAutoDetect tells us to determine the radix for you.
* @return int rep of string value, and possible (out) error code
*/
PRInt32 ToInteger(PRInt32* aErrorCode,PRUint32 aRadix=kRadix10) const;
/**********************************************************************
String manipulation methods...
*********************************************************************/
/**
* assign given string to this string
* @param aStr: buffer to be assigned to this
* @param aCount is the length of the given str (or -1) if you want me to determine its length
* NOTE: IFF you pass -1 as aCount, then your buffer must be null terminated.
* @return this
*/
nsString& operator=( const nsString& aString ) { Assign(aString); return *this; }
nsString& operator=( const nsAReadableString& aReadable ) { Assign(aReadable); return *this; }
nsString& operator=( const nsPromiseReadable<PRUnichar>& aReadable ) { Assign(aReadable); return *this; }
nsString& operator=( const PRUnichar* aPtr ) { Assign(aPtr); return *this; }
nsString& operator=( PRUnichar aChar ) { Assign(aChar); return *this; }
void AssignWithConversion(char);
void AssignWithConversion(const char*);
void AssignWithConversion(const char*, PRInt32);
/*
* Appends n characters from given string to this,
* This version computes the length of your given string
*
* @param aString is the source to be appended to this
* @return number of chars copied
*/
void AppendInt(PRInt32, PRInt32=10); //radix=8,10 or 16
void AppendFloat(double);
void AppendWithConversion(const char*, PRInt32=-1);
void AppendWithConversion(char);
virtual void do_AppendFromElement( PRUnichar );
/*
* Copies n characters from this string to given string,
* starting at the leftmost offset.
*
*
* @param aCopy -- Receiving string
* @param aCount -- number of chars to copy
* @return number of chars copied
*/
PRUint32 Left(nsString& aCopy,PRInt32 aCount) const;
/*
* Copies n characters from this string to given string,
* starting at the given offset.
*
*
* @param aCopy -- Receiving string
* @param aCount -- number of chars to copy
* @param anOffset -- position where copying begins
* @return number of chars copied
*/
PRUint32 Mid(nsString& aCopy,PRUint32 anOffset,PRInt32 aCount) const;
/*
* Copies n characters from this string to given string,
* starting at rightmost char.
*
*
* @param aCopy -- Receiving string
* @param aCount -- number of chars to copy
* @return number of chars copied
*/
PRUint32 Right(nsString& aCopy,PRInt32 aCount) const;
//void InsertWithConversion(char);
void InsertWithConversion(const char*, PRUint32, PRInt32=-1);
/**********************************************************************
Searching methods...
*********************************************************************/
/**
* Search for given substring within this string
*
* @param aString is substring to be sought in this
* @param aIgnoreCase selects case sensitivity
* @param anOffset tells us where in this strig to start searching
* @param aCount tells us how many iterations to make starting at the given offset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 Find(const nsString& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
/**
* Search for given char within this string
*
* @param aString is substring to be sought in this
* @param anOffset tells us where in this strig to start searching
* @param aIgnoreCase selects case sensitivity
* @param aCount tells us how many iterations to make starting at the given offset
* @return find pos in string, or -1 (kNotFound)
*/
//PRInt32 Find(PRUnichar aChar,PRInt32 offset=-1,PRBool aIgnoreCase=PR_FALSE) const;
PRInt32 FindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
/**
* This method searches this string for the first character
* found in the given charset
* @param aString contains set of chars to be found
* @param anOffset tells us where to start searching in this
* @return -1 if not found, else the offset in this
*/
PRInt32 FindCharInSet(const char* aString,PRInt32 anOffset=0) const;
PRInt32 FindCharInSet(const PRUnichar* aString,PRInt32 anOffset=0) const;
PRInt32 FindCharInSet(const nsStr& aString,PRInt32 anOffset=0) const;
/**
* This methods scans the string backwards, looking for the given string
* @param aString is substring to be sought in this
* @param aIgnoreCase tells us whether or not to do caseless compare
* @param anOffset tells us where in this strig to start searching (counting from left)
* @param aCount tells us how many iterations to make starting at the given offset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 RFind(const char* aCString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const nsString& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
/**
* Search for given char within this string
*
* @param aString is substring to be sought in this
* @param anOffset tells us where in this strig to start searching (counting from left)
* @param aIgnoreCase selects case sensitivity
* @param aCount tells us how many iterations to make starting at the given offset
* @return find pos in string, or -1 (kNotFound)
*/
//PRInt32 RFind(PRUnichar aChar,PRInt32 offset=-1,PRBool aIgnoreCase=PR_FALSE) const;
PRInt32 RFindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
/**
* This method searches this string for the last character
* found in the given string
* @param aString contains set of chars to be found
* @param anOffset tells us where in this strig to start searching (counting from left)
* @return -1 if not found, else the offset in this
*/
PRInt32 RFindCharInSet(const char* aString,PRInt32 anOffset=-1) const;
PRInt32 RFindCharInSet(const PRUnichar* aString,PRInt32 anOffset=-1) const;
PRInt32 RFindCharInSet(const nsStr& aString,PRInt32 anOffset=-1) const;
/**********************************************************************
Comparison methods...
*********************************************************************/
/**
* Compares a given string type to this string.
* @update gess 7/27/98
* @param S is the string to be compared
* @param aIgnoreCase tells us how to treat case
* @param aCount tells us how many chars to compare
* @return -1,0,1
*/
PRInt32 CompareWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRInt32 CompareWithConversion(const nsString& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRInt32 CompareWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const nsString &aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsAtom(/*FIX: const */nsIAtom* anAtom,PRBool aIgnoreCase) const;
PRBool EqualsIgnoreCase(const nsString& aString) const;
PRBool EqualsIgnoreCase(const char* aString,PRInt32 aCount=-1) const;
PRBool EqualsIgnoreCase(/*FIX: const */nsIAtom *aAtom) const;
/**
* Determine if given buffer is plain ascii
*
* @param aBuffer -- if null, then we test *this, otherwise we test given buffer
* @return TRUE if is all ascii chars or if strlen==0
*/
PRBool IsASCII(const PRUnichar* aBuffer=0);
void DebugDump(void) const;
/**
* Determine if given char is a valid space character
*
* @param aChar is character to be tested
* @return TRUE if is valid space char
*/
static PRBool IsSpace(PRUnichar ch);
/**
* Determine if given char in valid alpha range
*
* @param aChar is character to be tested
* @return TRUE if in alpha range
*/
static PRBool IsAlpha(PRUnichar ch);
/**
* Determine if given char is valid digit
*
* @param aChar is character to be tested
* @return TRUE if char is a valid digit
*/
static PRBool IsDigit(PRUnichar ch);
static void Recycle(nsString* aString);
static nsString* CreateString(void);
private:
// NOT TO BE IMPLEMENTED
// these signatures help clients not accidentally call the wrong thing helped by C++ automatic integral promotion
void operator=( char );
void AssignWithConversion( PRUnichar );
void AssignWithConversion( const PRUnichar*, PRInt32=-1 );
void AppendWithConversion( PRUnichar );
void AppendWithConversion( const PRUnichar*, PRInt32=-1 );
void InsertWithConversion( const PRUnichar*, PRUint32, PRInt32=-1 );
};
// NS_DEF_STRING_COMPARISON_OPERATORS(nsString, PRUnichar)
NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsString, PRUnichar)
extern NS_COM int fputs(const nsString& aString, FILE* out);
//ostream& operator<<(ostream& aStream,const nsString& aString);
//virtual void DebugDump(ostream& aStream) const;
/**************************************************************
Here comes the AutoString class which uses internal memory
(typically found on the stack) for its default buffer.
If the buffer needs to grow, it gets reallocated on the heap.
**************************************************************/
class NS_COM nsAutoString : public nsString {
public:
virtual ~nsAutoString();
nsAutoString();
nsAutoString(const nsAutoString& aString);
explicit nsAutoString(const nsAReadableString& aString);
explicit nsAutoString(const nsString& aString);
explicit nsAutoString(const PRUnichar* aString);
nsAutoString(const PRUnichar* aString,PRInt32 aLength);
explicit nsAutoString(PRUnichar aChar);
explicit nsAutoString(const CBufDescriptor& aBuffer);
#if defined(AIX) || defined(XP_OS2_VACPP)
explicit nsAutoString(const nsSubsumeStr& aSubsumeStr); // AIX and VAC++ requires a const
#else
explicit nsAutoString(nsSubsumeStr& aSubsumeStr);
#endif // AIX || XP_OS2_VACPP
nsAutoString& operator=( const nsAutoString& aString ) { Assign(aString); return *this; }
private:
void operator=( char ); // NOT TO BE IMPLEMENTED
public:
nsAutoString& operator=( const nsAReadableString& aReadable ) { Assign(aReadable); return *this; }
nsAutoString& operator=( const nsPromiseReadable<PRUnichar>& aReadable ) { Assign(aReadable); return *this; }
nsAutoString& operator=( const PRUnichar* aPtr ) { Assign(aPtr); return *this; }
nsAutoString& operator=( PRUnichar aChar ) { Assign(aChar); return *this; }
/**
* Retrieve the size of this string
* @return string length
*/
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
char mBuffer[kDefaultStringSize<<eTwoByte];
};
NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsAutoString, PRUnichar)
class NS_COM NS_ConvertASCIItoUCS2
: public nsAutoString
/*
...
*/
{
public:
explicit NS_ConvertASCIItoUCS2( const char* );
NS_ConvertASCIItoUCS2( const char*, PRUint32 );
explicit NS_ConvertASCIItoUCS2( char );
const PRUnichar* get() const { return GetUnicode(); }
operator const PRUnichar*() const
{
return GetUnicode();
}
operator nsLiteralString() const
{
return nsLiteralString(mUStr, mLength);
}
private:
// NOT TO BE IMPLEMENTED
NS_ConvertASCIItoUCS2( PRUnichar );
};
#define NS_ConvertToString NS_ConvertASCIItoUCS2
#if 0
inline
nsAutoString
NS_ConvertToString( const char* aCString )
{
nsAutoString result;
result.AssignWithConversion(aCString);
return result;
}
inline
nsAutoString
NS_ConvertToString( const char* aCString, PRUint32 aLength )
{
nsAutoString result;
result.AssignWithConversion(aCString, aLength);
return result;
}
#endif
class NS_COM NS_ConvertUTF8toUCS2
: public nsAutoString
{
public:
explicit
NS_ConvertUTF8toUCS2( const char* aCString )
{
Init( aCString, ~PRUint32(0) /* MAXINT */ );
}
NS_ConvertUTF8toUCS2( const char* aCString, PRUint32 aLength )
{
Init( aCString, aLength );
}
explicit
NS_ConvertUTF8toUCS2( char aChar )
{
Init( &aChar, 1 );
}
operator const PRUnichar*() const
{
return GetUnicode();
}
protected:
void Init( const char* aCString, PRUint32 aLength );
private:
NS_ConvertUTF8toUCS2( PRUnichar );
};
/***************************************************************
The subsumestr class is very unusual.
It differs from a normal string in that it doesn't use normal
copy semantics when another string is assign to this.
Instead, it "steals" the contents of the source string.
This is very handy for returning nsString classes as part of
an operator+(...) for example, in that it cuts down the number
of copy operations that must occur.
You should probably not use this class unless you really know
what you're doing.
***************************************************************/
class NS_COM nsSubsumeStr : public nsString {
public:
nsSubsumeStr();
explicit nsSubsumeStr(nsStr& aString);
nsSubsumeStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
nsSubsumeStr(char* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
int Subsume(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
nsSubsumeStr& operator=( const nsSubsumeStr& aReadable ) { Assign(aReadable); return *this; }
nsSubsumeStr& operator=( const nsAReadableString& aReadable ) { Assign(aReadable); return *this; }
nsSubsumeStr& operator=( const nsPromiseReadable<PRUnichar>& aReadable ) { Assign(aReadable); return *this; }
nsSubsumeStr& operator=( const PRUnichar* aPtr ) { Assign(aPtr); return *this; }
nsSubsumeStr& operator=( PRUnichar aChar ) { Assign(aChar); return *this; }
private:
void operator=( char ); // NOT TO BE IMPLEMENTED
};
#endif

View 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 "nsDebug.h"
#include "nsMemory.h"
#include "nsXPIDLString.h"
#include "plstr.h"
// If the allocator changes, fix it here.
#define XPIDL_STRING_ALLOC(__len) ((PRUnichar*) nsMemory::Alloc((__len) * sizeof(PRUnichar)))
#define XPIDL_CSTRING_ALLOC(__len) ((char*) nsMemory::Alloc((__len) * sizeof(char)))
#define XPIDL_FREE(__ptr) (nsMemory::Free(__ptr))
////////////////////////////////////////////////////////////////////////
// nsXPIDLString
nsXPIDLString::~nsXPIDLString()
{
if (mBufOwner && mBuf)
XPIDL_FREE(mBuf);
}
PRUnichar*
nsXPIDLString::Copy(const PRUnichar* aString)
{
NS_ASSERTION(aString, "null ptr");
if (! aString)
return 0;
PRInt32 len = 0;
{
const PRUnichar* p = aString;
while (*p++)
len++;
}
PRUnichar* result = XPIDL_STRING_ALLOC(len + 1);
if (result) {
PRUnichar* q = result;
while (*aString) {
*q = *aString;
q++;
aString++;
}
*q = '\0';
}
return result;
}
PRUnichar**
nsXPIDLString::StartAssignmentByValue()
{
if (mBufOwner && mBuf)
XPIDL_FREE(mBuf);
mBuf = 0;
mBufOwner = PR_TRUE;
return &mBuf;
}
const PRUnichar**
nsXPIDLString::StartAssignmentByReference()
{
if (mBufOwner && mBuf)
XPIDL_FREE(mBuf);
mBuf = 0;
mBufOwner = PR_FALSE;
return (const PRUnichar**) &mBuf;
}
////////////////////////////////////////////////////////////////////////
// nsXPIDLCString
nsXPIDLCString::~nsXPIDLCString()
{
if (mBufOwner && mBuf)
XPIDL_FREE(mBuf);
}
nsXPIDLCString& nsXPIDLCString::operator =(const char* aCString)
{
if (mBufOwner && mBuf)
XPIDL_FREE(mBuf);
if (aCString) {
mBuf = Copy(aCString);
mBufOwner = PR_TRUE;
}
else {
mBuf = 0;
mBufOwner = PR_FALSE;
}
return *this;
}
char*
nsXPIDLCString::Copy(const char* aCString)
{
NS_ASSERTION(aCString, "null ptr");
if (! aCString)
return 0;
PRInt32 len = PL_strlen(aCString);
char* result = XPIDL_CSTRING_ALLOC(len + 1);
if (result)
PL_strcpy(result, aCString);
return result;
}
char**
nsXPIDLCString::StartAssignmentByValue()
{
if (mBufOwner && mBuf)
XPIDL_FREE(mBuf);
mBuf = 0;
mBufOwner = PR_TRUE;
return &mBuf;
}
const char**
nsXPIDLCString::StartAssignmentByReference()
{
if (mBufOwner && mBuf)
XPIDL_FREE(mBuf);
mBuf = 0;
mBufOwner = PR_FALSE;
return (const char**) &mBuf;
}

View File

@@ -0,0 +1,382 @@
/* -*- 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):
*/
/*
A set of string wrapper classes that ease transition to use of XPIDL
interfaces. nsXPIDLString and nsXPIDLCString are to XPIDL `wstring'
and `string' out params as nsCOMPtr is to generic XPCOM interface
pointers. They help you deal with object ownership.
Consider the following interface:
interface nsIFoo {
attribute string Bar;
};
This will generate the following C++ header file:
class nsIFoo {
NS_IMETHOD SetBar(const PRUnichar* aValue);
NS_IMETHOD GetBar(PRUnichar* *aValue);
};
The GetBar() method will allocate a copy of the nsIFoo object's
"bar" attribute, and leave you to deal with freeing it:
nsIFoo* aFoo; // assume we get this somehow
PRUnichar* bar;
aFoo->GetFoo(&bar);
// Use bar here...
printf("bar is %s!\n", bar);
nsMemory::Free(bar);
This makes your life harder, because you need to convolute your code
to ensure that you don't leak `bar'.
Enter nsXPIDLString, which manages the ownership of the allocated
string, and automatically destroys it when the nsXPIDLString goes
out of scope:
nsIFoo* aFoo;
nsXPIDLString bar;
aFoo->GetFoo( getter_Copies(bar) );
// Use bar here...
printf("bar is %s!\n", (const char*) bar);
// no need to remember to nsMemory::Free().
Like nsCOMPtr, nsXPIDLString uses some syntactic sugar to make it
painfully clear exactly what the code expects. You need to wrap an
nsXPIDLString object with either `getter_Copies()' or
`getter_Shares()' before passing it to a getter: these tell the
nsXPIDLString how ownership is being handled.
In the case of `getter_Copies()', the callee is allocating a copy
(which is usually the case). In the case of `getter_Shares()', the
callee is returning a const reference to `the real deal' (this can
be done using the [shared] attribute in XPIDL).
*/
#ifndef nsXPIDLString_h__
#define nsXPIDLString_h__
#include "nscore.h"
#include "nsCom.h"
#include "prtypes.h"
#ifndef __PRUNICHAR__
#define __PRUNICHAR__
typedef PRUint16 PRUnichar;
#endif /* __PRUNICHAR__ */
////////////////////////////////////////////////////////////////////////
// nsXPIDLString
//
// A wrapper for Unicode strings. With the |getter_Copies()| and
// |getter_Shares()| helper functions, this can be used instead of
// the "naked" |PRUnichar*| interface for |wstring| parameters in
// XPIDL interfaces.
//
class NS_COM nsXPIDLString {
private:
PRUnichar* mBuf;
PRBool mBufOwner;
PRUnichar** StartAssignmentByValue();
const PRUnichar** StartAssignmentByReference();
public:
/**
* Construct a new, uninitialized wrapper for a Unicode string.
*/
nsXPIDLString() : mBuf(0), mBufOwner(PR_FALSE) {}
virtual ~nsXPIDLString();
/**
* Return a reference to the immutable Unicode string.
*/
operator const PRUnichar*() const { return get(); }
/**
* Return a reference to the immutable Unicode string.
*/
const PRUnichar* get() const { return mBuf; }
/**
* Make a copy of the Unicode string. Use this function in the
* callee to ensure that the correct memory allocator is used.
*/
static PRUnichar* Copy(const PRUnichar* aString);
// A helper class for assignment-by-value. This class is an
// implementation detail and should not be considered part of the
// public interface.
class NS_COM GetterCopies {
private:
nsXPIDLString& mXPIDLString;
public:
GetterCopies(nsXPIDLString& aXPIDLString)
: mXPIDLString(aXPIDLString) {}
operator PRUnichar**() {
return mXPIDLString.StartAssignmentByValue();
}
friend GetterCopies getter_Copies(nsXPIDLString& aXPIDLString);
};
friend class GetterCopies;
// A helper class for assignment-by-reference. This class is an
// implementation detail and should not be considered part of the
// public interface.
class NS_COM GetterShares {
private:
nsXPIDLString& mXPIDLString;
public:
GetterShares(nsXPIDLString& aXPIDLString)
: mXPIDLString(aXPIDLString) {}
operator const PRUnichar**() {
return mXPIDLString.StartAssignmentByReference();
}
friend GetterShares getter_Shares(nsXPIDLString& aXPIDLString);
};
friend class GetterShares;
private:
// not to be implemented
nsXPIDLString(nsXPIDLString& /* aXPIDLString */) {}
void operator=(nsXPIDLString& /* aXPIDLString */) {}
};
/**
* Use this function to "wrap" the nsXPIDLString object that is to
* receive an |out| value.
*/
inline nsXPIDLString::GetterCopies
getter_Copies(nsXPIDLString& aXPIDLString)
{
return nsXPIDLString::GetterCopies(aXPIDLString);
}
/**
* Use this function to "wrap" the nsXPIDLString object that is to
* receive a |[shared] out| value.
*/
inline nsXPIDLString::GetterShares
getter_Shares(nsXPIDLString& aXPIDLString)
{
return nsXPIDLString::GetterShares(aXPIDLString);
}
// XXX THESE ARE NOT strcmp()! DON'T TRY TO USE THEM AS SUCH!
inline
PRBool
operator==(const PRUnichar* lhs, const nsXPIDLString& rhs)
{
return lhs == NS_STATIC_CAST(const PRUnichar*, rhs);
}
inline
PRBool
operator==(const nsXPIDLString& lhs, const PRUnichar* rhs)
{
return NS_STATIC_CAST(const PRUnichar*, lhs) == rhs;
}
#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
inline
PRBool
operator==(int lhs, const nsXPIDLString& rhs)
{
return NS_REINTERPRET_CAST(PRUnichar*, lhs) == NS_STATIC_CAST(const PRUnichar*, rhs);
}
inline
PRBool
operator==(const nsXPIDLString& lhs, int rhs)
{
return NS_STATIC_CAST(const PRUnichar*, lhs) == NS_REINTERPRET_CAST(PRUnichar*, rhs);
}
#endif
////////////////////////////////////////////////////////////////////////
// nsXPIDLCString
//
// A wrapper for Unicode strings. With the |getter_Copies()| and
// |getter_Shares()| helper functions, this can be used instead of
// the "naked" |char*| interface for |string| parameters in XPIDL
// interfaces.
//
class NS_COM nsXPIDLCString {
private:
char* mBuf;
PRBool mBufOwner;
char** StartAssignmentByValue();
const char** StartAssignmentByReference();
public:
/**
* Construct a new, uninitialized wrapper for a single-byte string.
*/
nsXPIDLCString() : mBuf(0), mBufOwner(PR_FALSE) {}
virtual ~nsXPIDLCString();
/**
* Assign a single-byte string to this wrapper. Copies
* and owns the result.
*/
nsXPIDLCString& operator=(const char* aString);
/**
* Return a reference to the immutable single-byte string.
*/
operator const char*() const { return get(); }
/**
* Return a reference to the immutable single-byte string.
*/
const char* get() const { return mBuf; }
/**
* Make a copy of the single-byte string. Use this function in the
* callee to ensure that the correct memory allocator is used.
*/
static char* Copy(const char* aString);
// A helper class for assignment-by-value. This class is an
// implementation detail and should not be considered part of the
// public interface.
class NS_COM GetterCopies {
private:
nsXPIDLCString& mXPIDLString;
public:
GetterCopies(nsXPIDLCString& aXPIDLString)
: mXPIDLString(aXPIDLString) {}
operator char**() {
return mXPIDLString.StartAssignmentByValue();
}
friend GetterCopies getter_Copies(nsXPIDLCString& aXPIDLString);
};
friend class GetterCopies;
// A helper class for assignment-by-reference. This class is an
// implementation detail and should not be considered part of the
// public interface.
class NS_COM GetterShares {
private:
nsXPIDLCString& mXPIDLString;
public:
GetterShares(nsXPIDLCString& aXPIDLString)
: mXPIDLString(aXPIDLString) {}
operator const char**() {
return mXPIDLString.StartAssignmentByReference();
}
friend GetterShares getter_Shares(nsXPIDLCString& aXPIDLString);
};
friend class GetterShares;
private:
// not to be implemented
nsXPIDLCString(nsXPIDLCString& /* aXPIDLString */) {}
void operator=(nsXPIDLCString& /* aXPIDLCString */) {}
};
/**
* Use this function to "wrap" the nsXPIDLCString object that is to
* receive an |out| value.
*/
inline nsXPIDLCString::GetterCopies
getter_Copies(nsXPIDLCString& aXPIDLString)
{
return nsXPIDLCString::GetterCopies(aXPIDLString);
}
/**
* Use this function to "wrap" the nsXPIDLCString object that is to
* receive a |[shared] out| value.
*/
inline nsXPIDLCString::GetterShares
getter_Shares(nsXPIDLCString& aXPIDLString)
{
return nsXPIDLCString::GetterShares(aXPIDLString);
}
// XXX THESE ARE NOT strcmp()! DON'T TRY TO USE THEM AS SUCH!
inline
PRBool
operator==(const char* lhs, const nsXPIDLCString& rhs)
{
return lhs == NS_STATIC_CAST(const char*, rhs);
}
inline
PRBool
operator==(const nsXPIDLCString& lhs, const char* rhs)
{
return NS_STATIC_CAST(const char*, lhs) == rhs;
}
#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
inline
PRBool
operator==(int lhs, const nsXPIDLCString& rhs)
{
return NS_REINTERPRET_CAST(char*, lhs) == NS_STATIC_CAST(const char*, rhs);
}
inline
PRBool
operator==(const nsXPIDLCString& lhs, int rhs)
{
return NS_STATIC_CAST(const char*, lhs) == NS_REINTERPRET_CAST(char*, rhs);
}
#endif
#endif // nsXPIDLString_h__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,882 @@
/* -*- 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) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#ifndef nsAWritableString_h___
#define nsAWritableString_h___
// See also...
#ifndef nsAReadableString_h___
#include "nsAReadableString.h"
#endif
template <class CharT>
struct nsWritableFragment
{
CharT* mStart;
CharT* mEnd;
void* mFragmentIdentifier;
nsWritableFragment()
: mStart(0), mEnd(0), mFragmentIdentifier(0)
{
// nothing else to do here
}
};
template <class CharT> class basic_nsAWritableString;
template <class CharT>
class nsWritingIterator
// : public bidirectional_iterator_tag
{
public:
typedef ptrdiff_t difference_type;
typedef CharT value_type;
typedef CharT* pointer;
typedef CharT& reference;
// typedef bidirectional_iterator_tag iterator_category;
private:
friend class basic_nsAWritableString<CharT>;
nsWritableFragment<CharT> mFragment;
CharT* mPosition;
basic_nsAWritableString<CharT>* mOwningString;
nsWritingIterator( nsWritableFragment<CharT>& aFragment,
CharT* aStartingPosition,
basic_nsAWritableString<CharT>& aOwningString )
: mFragment(aFragment),
mPosition(aStartingPosition),
mOwningString(&aOwningString)
{
// nothing else to do here
}
public:
nsWritingIterator() { }
// nsWritingIterator( const nsWritingIterator<CharT>& ); // auto-generated copy-constructor OK
// nsWritingIterator<CharT>& operator=( const nsWritingIterator<CharT>& ); // auto-generated copy-assignment operator OK
inline void normalize_forward();
inline void normalize_backward();
pointer
get() const
{
return mPosition;
}
reference
operator*() const
{
return *get();
}
#if 0
// An iterator really deserves this, but some compilers (notably IBM VisualAge for OS/2)
// don't like this when |CharT| is a type without members.
pointer
operator->() const
{
return get();
}
#endif
nsWritingIterator<CharT>&
operator++()
{
++mPosition;
normalize_forward();
return *this;
}
nsWritingIterator<CharT>
operator++( int )
{
nsWritingIterator<CharT> result(*this);
++mPosition;
normalize_forward();
return result;
}
nsWritingIterator<CharT>&
operator--()
{
normalize_backward();
--mPosition;
return *this;
}
nsWritingIterator<CharT>
operator--( int )
{
nsWritingIterator<CharT> result(*this);
normalize_backward();
--mPosition;
return result;
}
const nsWritableFragment<CharT>&
fragment() const
{
return mFragment;
}
difference_type
size_forward() const
{
return mFragment.mEnd - mPosition;
}
difference_type
size_backward() const
{
return mPosition - mFragment.mStart;
}
nsWritingIterator<CharT>&
advance( difference_type n )
{
while ( n > 0 )
{
difference_type one_hop = NS_MIN(n, size_forward());
NS_ASSERTION(one_hop>0, "Infinite loop: can't advance a writing iterator beyond the end of a string");
// perhaps I should |break| if |!one_hop|?
mPosition += one_hop;
normalize_forward();
n -= one_hop;
}
while ( n < 0 )
{
normalize_backward();
difference_type one_hop = NS_MAX(n, -size_backward());
NS_ASSERTION(one_hop<0, "Infinite loop: can't advance (backward) a writing iterator beyond the end of a string");
// perhaps I should |break| if |!one_hop|?
mPosition += one_hop;
n -= one_hop;
}
return *this;
}
/**
* Really don't want to call these two operations |+=| and |-=|.
* Would prefer a single function, e.g., |advance|, which doesn't imply a constant time operation.
*
* We'll get rid of these as soon as we can.
*/
nsWritingIterator<CharT>&
operator+=( difference_type n ) // deprecated
{
return advance(n);
}
nsWritingIterator<CharT>&
operator-=( difference_type n ) // deprecated
{
return advance(-n);
}
PRUint32
write( const value_type* s, PRUint32 n )
{
NS_ASSERTION(size_forward() > 0, "You can't |write| into an |nsWritingIterator| with no space!");
n = NS_MIN(n, PRUint32(size_forward()));
nsCharTraits<value_type>::move(mPosition, s, n);
advance( difference_type(n) );
return n;
}
};
#if 0
template <class CharT>
nsWritingIterator<CharT>&
nsWritingIterator<CharT>::advance( difference_type n )
{
while ( n > 0 )
{
difference_type one_hop = NS_MIN(n, size_forward());
NS_ASSERTION(one_hop>0, "Infinite loop: can't advance a writing iterator beyond the end of a string");
// perhaps I should |break| if |!one_hop|?
mPosition += one_hop;
normalize_forward();
n -= one_hop;
}
while ( n < 0 )
{
normalize_backward();
difference_type one_hop = NS_MAX(n, -size_backward());
NS_ASSERTION(one_hop<0, "Infinite loop: can't advance (backward) a writing iterator beyond the end of a string");
// perhaps I should |break| if |!one_hop|?
mPosition += one_hop;
n -= one_hop;
}
return *this;
}
#endif
/*
This file defines the abstract interfaces |nsAWritableString| and
|nsAWritableCString|.
|nsAWritableString| is a string of |PRUnichar|s. |nsAWritableCString| (note the
'C') is a string of |char|s.
*/
template <class CharT>
class basic_nsAWritableString
: public basic_nsAReadableString<CharT>
/*
...
*/
{
// friend class nsWritingIterator<CharT>;
public:
typedef CharT char_type;
typedef PRUint32 size_type;
typedef PRUint32 index_type;
typedef nsWritingIterator<CharT> iterator;
// basic_nsAWritableString(); // auto-generated default constructor OK (we're abstract anyway)
// basic_nsAWritableString( const basic_nsAWritableString<CharT>& ); // auto-generated copy-constructor OK (again, only because we're abstract)
// ~basic_nsAWritableString(); // auto-generated destructor OK
// see below for copy-assignment operator
virtual CharT* GetWritableFragment( nsWritableFragment<CharT>&, nsFragmentRequest, PRUint32 = 0 ) = 0;
/**
* Note: measure -- should the |BeginWriting| and |EndWriting| be |inline|?
*/
nsWritingIterator<CharT>&
BeginWriting( nsWritingIterator<CharT>& aResult )
{
aResult.mOwningString = this;
GetWritableFragment(aResult.mFragment, kFirstFragment);
aResult.mPosition = aResult.mFragment.mStart;
aResult.normalize_forward();
return aResult;
}
// deprecated
nsWritingIterator<CharT>
BeginWriting()
{
nsWritingIterator<CharT> result;
return BeginWriting(result); // copies (since I return a value, not a reference)
}
nsWritingIterator<CharT>&
EndWriting( nsWritingIterator<CharT>& aResult )
{
aResult.mOwningString = this;
GetWritableFragment(aResult.mFragment, kLastFragment);
aResult.mPosition = aResult.mFragment.mEnd;
// must not |normalize_backward| as that would likely invalidate tests like |while ( first != last )|
return aResult;
}
// deprecated
nsWritingIterator<CharT>
EndWriting()
{
nsWritingIterator<CharT> result;
return EndWriting(result); // copies (since I return a value, not a reference)
}
/**
* |SetCapacity| is not required to do anything; however, it can be used
* as a hint to the implementation to reduce allocations.
* |SetCapacity(0)| is a suggestion to discard all associated storage.
*/
virtual void SetCapacity( PRUint32 ) { }
/**
* |SetLength| is used in two ways:
* 1) to |Cut| a suffix of the string;
* 2) to prepare to |Append| or move characters around.
*
* External callers are not allowed to use |SetLength| is this latter capacity.
* Should this really be a public operation?
* Additionally, your implementation of |SetLength| need not satisfy (2) if and only if you
* override the |do_...| routines to not need this facility.
*
* This distinction makes me think the two different uses should be split into
* two distinct functions.
*/
virtual void SetLength( PRUint32 ) = 0;
void
Truncate( PRUint32 aNewLength=0 )
{
NS_ASSERTION(aNewLength<=this->Length(), "Can't use |Truncate()| to make a string longer.");
if ( aNewLength < this->Length() )
SetLength(aNewLength);
}
// PRBool SetCharAt( char_type, index_type ) = 0;
// void ToLowerCase();
// void ToUpperCase();
// void StripChars( const CharT* aSet );
// void StripChar( ... );
// void StripWhitespace();
// void ReplaceChar( ... );
// void ReplaceSubstring( ... );
// void Trim( ... );
// void CompressSet( ... );
// void CompressWhitespace( ... );
//
// |Assign()|, |operator=()|
//
void Assign( const basic_nsAReadableString<CharT>& aReadable ) { AssignFromReadable(aReadable); }
void Assign( const nsPromiseReadable<CharT>& aReadable ) { AssignFromPromise(aReadable); }
void Assign( const CharT* aPtr ) { aPtr ? do_AssignFromElementPtr(aPtr) : SetLength(0); }
void Assign( const CharT* aPtr, PRUint32 aLength ) { do_AssignFromElementPtrLength(aPtr, aLength); }
void Assign( CharT aChar ) { do_AssignFromElement(aChar); }
// copy-assignment operator. I must define my own if I don't want the compiler to make me one
basic_nsAWritableString<CharT>& operator=( const basic_nsAWritableString<CharT>& aWritable ) { Assign(aWritable); return *this; }
basic_nsAWritableString<CharT>& operator=( const basic_nsAReadableString<CharT>& aReadable ) { Assign(aReadable); return *this; }
basic_nsAWritableString<CharT>& operator=( const nsPromiseReadable<CharT>& aReadable ) { Assign(aReadable); return *this; }
basic_nsAWritableString<CharT>& operator=( const CharT* aPtr ) { Assign(aPtr); return *this; }
basic_nsAWritableString<CharT>& operator=( CharT aChar ) { Assign(aChar); return *this; }
//
// |Append()|, |operator+=()|
//
void Append( const basic_nsAReadableString<CharT>& aReadable ) { AppendFromReadable(aReadable); }
void Append( const nsPromiseReadable<CharT>& aReadable ) { AppendFromPromise(aReadable); }
void Append( const CharT* aPtr ) { if (aPtr) do_AppendFromElementPtr(aPtr); }
void Append( const CharT* aPtr, PRUint32 aLength ) { do_AppendFromElementPtrLength(aPtr, aLength); }
void Append( CharT aChar ) { do_AppendFromElement(aChar); }
basic_nsAWritableString<CharT>& operator+=( const basic_nsAReadableString<CharT>& aReadable ) { Append(aReadable); return *this; }
basic_nsAWritableString<CharT>& operator+=( const nsPromiseReadable<CharT>& aReadable ) { Append(aReadable); return *this; }
basic_nsAWritableString<CharT>& operator+=( const CharT* aPtr ) { Append(aPtr); return *this; }
basic_nsAWritableString<CharT>& operator+=( CharT aChar ) { Append(aChar); return *this; }
/**
* The following index based routines need to be recast with iterators.
*/
//
// |Insert()|
// Note: I would really like to move the |atPosition| parameter to the front of the argument list
//
void Insert( const basic_nsAReadableString<CharT>& aReadable, PRUint32 atPosition ) { InsertFromReadable(aReadable, atPosition); }
void Insert( const nsPromiseReadable<CharT>& aReadable, PRUint32 atPosition ) { InsertFromPromise(aReadable, atPosition); }
void Insert( const CharT* aPtr, PRUint32 atPosition ) { if (aPtr) do_InsertFromElementPtr(aPtr, atPosition); }
void Insert( const CharT* aPtr, PRUint32 atPosition, PRUint32 aLength ) { do_InsertFromElementPtrLength(aPtr, atPosition, aLength); }
void Insert( CharT aChar, PRUint32 atPosition ) { do_InsertFromElement(aChar, atPosition); }
virtual void Cut( PRUint32 cutStart, PRUint32 cutLength );
void Replace( PRUint32 cutStart, PRUint32 cutLength, const basic_nsAReadableString<CharT>& aReadable ) { ReplaceFromReadable(cutStart, cutLength, aReadable); }
void Replace( PRUint32 cutStart, PRUint32 cutLength, const nsPromiseReadable<CharT>& aReadable ) { ReplaceFromPromise(cutStart, cutLength, aReadable); }
private:
typedef typename nsCharTraits<CharT>::incompatible_char_type incompatible_char_type;
// NOT TO BE IMPLEMENTED
void operator= ( incompatible_char_type );
void Assign ( incompatible_char_type );
void operator+= ( incompatible_char_type );
void Append ( incompatible_char_type );
void Insert ( incompatible_char_type, PRUint32 );
protected:
void AssignFromReadable( const basic_nsAReadableString<CharT>& );
void AssignFromPromise( const basic_nsAReadableString<CharT>& );
virtual void do_AssignFromReadable( const basic_nsAReadableString<CharT>& );
virtual void do_AssignFromElementPtr( const CharT* );
virtual void do_AssignFromElementPtrLength( const CharT*, PRUint32 );
virtual void do_AssignFromElement( CharT );
void AppendFromReadable( const basic_nsAReadableString<CharT>& );
void AppendFromPromise( const basic_nsAReadableString<CharT>& );
virtual void do_AppendFromReadable( const basic_nsAReadableString<CharT>& );
virtual void do_AppendFromElementPtr( const CharT* );
virtual void do_AppendFromElementPtrLength( const CharT*, PRUint32 );
virtual void do_AppendFromElement( CharT );
void InsertFromReadable( const basic_nsAReadableString<CharT>&, PRUint32 );
void InsertFromPromise( const basic_nsAReadableString<CharT>&, PRUint32 );
virtual void do_InsertFromReadable( const basic_nsAReadableString<CharT>&, PRUint32 );
virtual void do_InsertFromElementPtr( const CharT*, PRUint32 );
virtual void do_InsertFromElementPtrLength( const CharT*, PRUint32, PRUint32 );
virtual void do_InsertFromElement( CharT, PRUint32 );
void ReplaceFromReadable( PRUint32, PRUint32, const basic_nsAReadableString<CharT>& );
void ReplaceFromPromise( PRUint32, PRUint32, const basic_nsAReadableString<CharT>& );
virtual void do_ReplaceFromReadable( PRUint32, PRUint32, const basic_nsAReadableString<CharT>& );
};
//
// |nsWritingIterator|s
//
template <class CharT>
inline
void
nsWritingIterator<CharT>::normalize_forward()
{
while ( mPosition == mFragment.mEnd
&& mOwningString->GetWritableFragment(mFragment, kNextFragment) )
mPosition = mFragment.mStart;
}
template <class CharT>
inline
void
nsWritingIterator<CharT>::normalize_backward()
{
while ( mPosition == mFragment.mStart
&& mOwningString->GetWritableFragment(mFragment, kPrevFragment) )
mPosition = mFragment.mEnd;
}
template <class CharT>
inline
PRBool
operator==( const nsWritingIterator<CharT>& lhs, const nsWritingIterator<CharT>& rhs )
{
return lhs.get() == rhs.get();
}
template <class CharT>
inline
PRBool
operator!=( const nsWritingIterator<CharT>& lhs, const nsWritingIterator<CharT>& rhs )
{
return lhs.get() != rhs.get();
}
//
// |Assign()|
//
template <class CharT>
void
basic_nsAWritableString<CharT>::AssignFromReadable( const basic_nsAReadableString<CharT>& rhs )
{
if ( NS_STATIC_CAST(const basic_nsAReadableString<CharT>*, this) != &rhs )
do_AssignFromReadable(rhs);
// else, self-assign is a no-op
}
template <class CharT>
void
basic_nsAWritableString<CharT>::AssignFromPromise( const basic_nsAReadableString<CharT>& aReadable )
/*
...this function is only called when a promise that somehow references |this| is assigned _into_ |this|.
E.g.,
... writable& w ...
... readable& r ...
w = r + w;
In this example, you can see that unless the characters promised by |w| in |r+w| are resolved before
anything starts getting copied into |w|, there will be trouble. They will be overritten by the contents
of |r| before being retrieved to be appended.
We could have a really tricky solution where we tell the promise to resolve _just_ the data promised
by |this|, but this should be a rare case, since clients with more local knowledge will know that, e.g.,
in the case above, |Insert| could have special behavior with significantly better performance. Since
it's a rare case anyway, we should just do the simplest thing that could possibly work, resolve the
entire promise. If we measure and this turns out to show up on performance radar, we then have the
option to fix either the callers or this mechanism.
*/
{
if ( !aReadable.Promises(*this) )
do_AssignFromReadable(aReadable);
else
{
PRUint32 length = aReadable.Length();
CharT* buffer = new CharT[length];
if ( buffer )
{
// Note: not exception safe. We need something to manage temporary buffers like this
nsReadingIterator<CharT> fromBegin, fromEnd;
CharT* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_AssignFromElementPtrLength(buffer, length);
delete buffer;
}
// else assert?
}
}
template <class CharT>
void
basic_nsAWritableString<CharT>::do_AssignFromReadable( const basic_nsAReadableString<CharT>& aReadable )
{
SetLength(0);
SetLength(aReadable.Length());
// first setting the length to |0| avoids copying characters only to be overwritten later
// in the case where the implementation decides to re-allocate
nsReadingIterator<CharT> fromBegin, fromEnd;
nsWritingIterator<CharT> toBegin;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin));
}
template <class CharT>
void
basic_nsAWritableString<CharT>::do_AssignFromElementPtr( const CharT* aPtr )
{
do_AssignFromReadable(basic_nsLiteralString<CharT>(aPtr));
}
template <class CharT>
void
basic_nsAWritableString<CharT>::do_AssignFromElementPtrLength( const CharT* aPtr, PRUint32 aLength )
{
do_AssignFromReadable(basic_nsLiteralString<CharT>(aPtr, aLength));
}
template <class CharT>
void
basic_nsAWritableString<CharT>::do_AssignFromElement( CharT aChar )
{
do_AssignFromReadable(basic_nsLiteralChar<CharT>(aChar));
}
//
// |Append()|
//
template <class CharT>
void
basic_nsAWritableString<CharT>::AppendFromReadable( const basic_nsAReadableString<CharT>& aReadable )
{
if ( NS_STATIC_CAST(const basic_nsAReadableString<CharT>*, this) != &aReadable )
do_AppendFromReadable(aReadable);
else
AppendFromPromise(aReadable);
}
template <class CharT>
void
basic_nsAWritableString<CharT>::AppendFromPromise( const basic_nsAReadableString<CharT>& aReadable )
{
if ( !aReadable.Promises(*this) )
do_AppendFromReadable(aReadable);
else
{
PRUint32 length = aReadable.Length();
CharT* buffer = new CharT[length];
if ( buffer )
{
nsReadingIterator<CharT> fromBegin, fromEnd;
CharT* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_AppendFromElementPtrLength(buffer, length);
delete buffer;
}
// else assert?
}
}
template <class CharT>
void
basic_nsAWritableString<CharT>::do_AppendFromReadable( const basic_nsAReadableString<CharT>& aReadable )
{
PRUint32 oldLength = this->Length();
SetLength(oldLength + aReadable.Length());
nsReadingIterator<CharT> fromBegin, fromEnd;
nsWritingIterator<CharT> toBegin;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin).advance( PRInt32(oldLength) ) );
}
template <class CharT>
void
basic_nsAWritableString<CharT>::do_AppendFromElementPtr( const CharT* aChar )
{
do_AppendFromReadable(basic_nsLiteralString<CharT>(aChar));
}
template <class CharT>
void
basic_nsAWritableString<CharT>::do_AppendFromElementPtrLength( const CharT* aChar, PRUint32 aLength )
{
do_AppendFromReadable(basic_nsLiteralString<CharT>(aChar, aLength));
}
template <class CharT>
void
basic_nsAWritableString<CharT>::do_AppendFromElement( CharT aChar )
{
do_AppendFromReadable(basic_nsLiteralChar<CharT>(aChar));
}
//
// |Insert()|
//
template <class CharT>
void
basic_nsAWritableString<CharT>::InsertFromReadable( const basic_nsAReadableString<CharT>& aReadable, PRUint32 atPosition )
{
if ( NS_STATIC_CAST(const basic_nsAReadableString<CharT>*, this) != &aReadable )
do_InsertFromReadable(aReadable, atPosition);
else
InsertFromPromise(aReadable, atPosition);
}
template <class CharT>
void
basic_nsAWritableString<CharT>::InsertFromPromise( const basic_nsAReadableString<CharT>& aReadable, PRUint32 atPosition )
{
if ( !aReadable.Promises(*this) )
do_InsertFromReadable(aReadable, atPosition);
else
{
PRUint32 length = aReadable.Length();
CharT* buffer = new CharT[length];
if ( buffer )
{
nsReadingIterator<CharT> fromBegin, fromEnd;
CharT* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_InsertFromElementPtrLength(buffer, atPosition, length);
delete buffer;
}
// else assert
}
}
template <class CharT>
void
basic_nsAWritableString<CharT>::do_InsertFromReadable( const basic_nsAReadableString<CharT>& aReadable, PRUint32 atPosition )
{
PRUint32 oldLength = this->Length();
SetLength(oldLength + aReadable.Length());
nsReadingIterator<CharT> fromBegin, fromEnd;
nsWritingIterator<CharT> toBegin;
if ( atPosition < oldLength )
copy_string_backward(this->BeginReading(fromBegin).advance(PRInt32(atPosition)), this->BeginReading(fromEnd).advance(PRInt32(oldLength)), EndWriting(toBegin));
else
atPosition = oldLength;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(atPosition)));
}
template <class CharT>
void
basic_nsAWritableString<CharT>::do_InsertFromElementPtr( const CharT* aPtr, PRUint32 atPosition )
{
do_InsertFromReadable(basic_nsLiteralString<CharT>(aPtr), atPosition);
}
template <class CharT>
void
basic_nsAWritableString<CharT>::do_InsertFromElementPtrLength( const CharT* aPtr, PRUint32 atPosition, PRUint32 aLength )
{
do_InsertFromReadable(basic_nsLiteralString<CharT>(aPtr, aLength), atPosition);
}
template <class CharT>
void
basic_nsAWritableString<CharT>::do_InsertFromElement( CharT aChar, PRUint32 atPosition )
{
do_InsertFromReadable(basic_nsLiteralChar<CharT>(aChar), atPosition);
}
//
// |Cut()|
//
template <class CharT>
void
basic_nsAWritableString<CharT>::Cut( PRUint32 cutStart, PRUint32 cutLength )
{
PRUint32 myLength = this->Length();
cutLength = NS_MIN(cutLength, myLength-cutStart);
PRUint32 cutEnd = cutStart + cutLength;
nsReadingIterator<CharT> fromBegin, fromEnd;
nsWritingIterator<CharT> toBegin;
if ( cutEnd < myLength )
copy_string(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(cutStart)));
SetLength(myLength-cutLength);
}
//
// |Replace()|
//
template <class CharT>
void
basic_nsAWritableString<CharT>::ReplaceFromReadable( PRUint32 cutStart, PRUint32 cutLength, const basic_nsAReadableString<CharT>& aReplacement )
{
if ( NS_STATIC_CAST(const basic_nsAReadableString<CharT>*, this) != &aReplacement )
do_ReplaceFromReadable(cutStart, cutLength, aReplacement);
else
ReplaceFromPromise(cutStart, cutLength, aReplacement);
}
template <class CharT>
void
basic_nsAWritableString<CharT>::ReplaceFromPromise( PRUint32 cutStart, PRUint32 cutLength, const basic_nsAReadableString<CharT>& aReadable )
{
if ( !aReadable.Promises(*this) )
do_ReplaceFromReadable(cutStart, cutLength, aReadable);
else
{
PRUint32 length = aReadable.Length();
CharT* buffer = new CharT[length];
if ( buffer )
{
nsReadingIterator<CharT> fromBegin, fromEnd;
CharT* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_ReplaceFromReadable(cutStart, cutLength, basic_nsLiteralString<CharT>(buffer, length));
delete buffer;
}
// else assert?
}
}
template <class CharT>
void
basic_nsAWritableString<CharT>::do_ReplaceFromReadable( PRUint32 cutStart, PRUint32 cutLength, const basic_nsAReadableString<CharT>& aReplacement )
{
PRUint32 oldLength = this->Length();
cutStart = NS_MIN(cutStart, oldLength);
cutLength = NS_MIN(cutLength, oldLength-cutStart);
PRUint32 cutEnd = cutStart + cutLength;
PRUint32 replacementLength = aReplacement.Length();
PRUint32 replacementEnd = cutStart + replacementLength;
PRUint32 newLength = oldLength - cutLength + replacementLength;
nsReadingIterator<CharT> fromBegin, fromEnd;
nsWritingIterator<CharT> toBegin;
if ( cutLength > replacementLength )
copy_string(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(replacementEnd)));
SetLength(newLength);
if ( cutLength < replacementLength )
copy_string_backward(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->BeginReading(fromEnd).advance(PRInt32(oldLength)), BeginWriting(toBegin).advance(PRInt32(replacementEnd)));
copy_string(aReplacement.BeginReading(fromBegin), aReplacement.EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(cutStart)));
}
template <class CharT>
PRUint32
basic_nsAReadableString<CharT>::Mid( basic_nsAWritableString<CharT>& aResult, PRUint32 aStartPos, PRUint32 aLengthToCopy ) const
{
// If we're just assigning our entire self, give |aResult| the opportunity to share
if ( aStartPos == 0 && aLengthToCopy >= Length() )
aResult = *this;
else
aResult = Substring(*this, aStartPos, aLengthToCopy);
return aResult.Length();
}
template <class CharT>
inline
PRUint32
basic_nsAReadableString<CharT>::Left( basic_nsAWritableString<CharT>& aResult, PRUint32 aLengthToCopy ) const
{
return Mid(aResult, 0, aLengthToCopy);
}
template <class CharT>
PRUint32
basic_nsAReadableString<CharT>::Right( basic_nsAWritableString<CharT>& aResult, PRUint32 aLengthToCopy ) const
{
PRUint32 myLength = Length();
aLengthToCopy = NS_MIN(myLength, aLengthToCopy);
return Mid(aResult, myLength-aLengthToCopy, aLengthToCopy);
}
//
// Types
//
typedef basic_nsAWritableString<PRUnichar> nsAWritableString;
typedef basic_nsAWritableString<char> nsAWritableCString;
#endif // !defined(nsAWritableString_h___)

View File

@@ -0,0 +1,113 @@
/* -*- 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):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#ifndef nsAlgorithm_h___
#define nsAlgorithm_h___
#ifndef nsCharTraits_h___
#include "nsCharTraits.h"
// for |nsCharSourceTraits|, |nsCharSinkTraits|
#endif
#ifndef prtypes_h___
#include "prtypes.h"
// for |PRUint32|...
#endif
template <class T>
inline
const T&
NS_MIN( const T& a, const T& b )
{
return b < a ? b : a;
}
template <class T>
inline
const T&
NS_MAX( const T& a, const T& b )
{
return a > b ? a : b;
}
template <class InputIterator, class T>
inline
PRUint32
NS_COUNT( InputIterator& first, const InputIterator& last, const T& value )
{
PRUint32 result = 0;
for ( ; first != last; ++first )
if ( *first == value )
++result;
return result;
}
template <class InputIterator, class OutputIterator>
inline
OutputIterator&
copy_string( InputIterator& first, const InputIterator& last, OutputIterator& result )
{
typedef nsCharSourceTraits<InputIterator> source_traits;
typedef nsCharSinkTraits<OutputIterator> sink_traits;
while ( first != last )
{
PRInt32 count_copied = PRInt32(sink_traits::write(result, source_traits::read(first), source_traits::readable_distance(first, last)));
NS_ASSERTION(count_copied > 0, "|copy_string| will never terminate");
source_traits::advance(first, count_copied);
}
return result;
}
template <class InputIterator, class OutputIterator>
OutputIterator&
copy_string_backward( const InputIterator& first, InputIterator& last, OutputIterator& result )
{
while ( first != last )
{
last.normalize_backward();
result.normalize_backward();
PRUint32 lengthToCopy = PRUint32( NS_MIN(last.size_backward(), result.size_backward()) );
if ( first.fragment().mStart == last.fragment().mStart )
lengthToCopy = NS_MIN(lengthToCopy, PRUint32(last.get() - first.get()));
NS_ASSERTION(lengthToCopy, "|copy_string_backward| will never terminate");
#ifdef _MSC_VER
// XXX Visual C++ can't stomach 'typename' where it rightfully should
nsCharTraits<OutputIterator::value_type>::move(result.get()-lengthToCopy, last.get()-lengthToCopy, lengthToCopy);
#else
nsCharTraits<typename OutputIterator::value_type>::move(result.get()-lengthToCopy, last.get()-lengthToCopy, lengthToCopy);
#endif
last.advance( -PRInt32(lengthToCopy) );
result.advance( -PRInt32(lengthToCopy) );
}
return result;
}
#endif // !defined(nsAlgorithm_h___)

View File

@@ -0,0 +1,181 @@
/* -*- 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 strings.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#ifndef nsBufferHandle_h___
#define nsBufferHandle_h___
#include <stddef.h>
// for |ptrdiff_t|
#include "prtypes.h"
// for |PRBool|
#include "nsDebug.h"
// for |NS_ASSERTION|
#include "nsMemory.h"
// for |nsMemory::Free|
/**
*
*/
template <class CharT>
class nsBufferHandle
{
public:
nsBufferHandle( CharT* aDataStart, CharT* aDataEnd ) : mDataStart(aDataStart), mDataEnd(aDataEnd) { }
void DataStart( CharT* aNewDataStart ) { mDataStart = aNewDataStart; }
CharT* DataStart() { return mDataStart; }
const CharT* DataStart() const { return mDataStart; }
void DataEnd( CharT* aNewDataEnd ) { mDataEnd = aNewDataEnd; }
CharT* DataEnd() { return mDataEnd; }
const CharT* DataEnd() const { return mDataEnd; }
// void DataLength( ptrdiff_t aNewDataLength ) { mDataEnd = mDataStart+aNewDataLength; }
ptrdiff_t DataLength() const { return mDataEnd - mDataStart; }
protected:
CharT* mDataStart;
CharT* mDataEnd;
};
/**
*
*/
template <class CharT>
class nsSharedBufferHandle
: public nsBufferHandle<CharT>
{
protected:
enum
{
kIsShared = 1<<31,
kIsSingleAllocationWithBuffer = 1<<30,
kIsStorageDefinedSeparately = 1<<29,
kFlagsMask = kIsShared | kIsSingleAllocationWithBuffer | kIsStorageDefinedSeparately,
kRefCountMask = ~kFlagsMask
};
public:
nsSharedBufferHandle( CharT* aDataStart, CharT* aDataEnd )
: nsBufferHandle<CharT>(aDataStart, aDataEnd)
{
mFlags |= kIsShared;
}
~nsSharedBufferHandle();
void
AcquireReference() const
{
nsSharedBufferHandle<CharT>* mutable_this = NS_CONST_CAST(nsSharedBufferHandle<CharT>*, this);
mutable_this->set_refcount( get_refcount()+1 );
}
void
ReleaseReference() const
{
nsSharedBufferHandle<CharT>* mutable_this = NS_CONST_CAST(nsSharedBufferHandle<CharT>*, this);
if ( !mutable_this->set_refcount( get_refcount()-1 ) )
delete mutable_this;
}
PRBool
IsReferenced() const
{
return get_refcount() != 0;
}
protected:
PRUint32 mFlags;
PRUint32
get_refcount() const
{
return mFlags & kRefCountMask;
}
PRUint32
set_refcount( PRUint32 aNewRefCount )
{
NS_ASSERTION(aNewRefCount <= kRefCountMask, "aNewRefCount <= kRefCountMask");
mFlags = (mFlags & kFlagsMask) | aNewRefCount;
return aNewRefCount;
}
};
// need a name for this
template <class CharT>
class nsFlexBufferHandle
: public nsSharedBufferHandle<CharT>
{
public:
nsFlexBufferHandle( CharT* aDataStart, CharT* aDataEnd, CharT* aStorageStart, CharT* aStorageEnd )
: nsSharedBufferHandle<CharT>(aDataStart, aDataEnd),
mStorageStart(aStorageStart),
mStorageEnd(aStorageEnd)
{
this->mFlags |= this->kIsStorageDefinedSeparately;
}
void StorageStart( CharT* aNewStorageStart ) { mStorageStart = aNewStorageStart; }
CharT* StorageStart() { return mStorageStart; }
const CharT* StorageStart() const { return mStorageStart; }
void StorageEnd( CharT* aNewStorageEnd ) { mStorageEnd = aNewStorageEnd; }
CharT* StorageEnd() { return mStorageEnd; }
const CharT* StorageEnd() const { return mStorageEnd; }
// void StorageLength( ptrdiff_t aNewStorageLength ) { mStorageEnd = mStorageStart+aNewStorageLength; }
ptrdiff_t StorageLength() const { return mStorageEnd - mStorageStart; }
protected:
CharT* mStorageStart;
CharT* mStorageEnd;
};
template <class CharT>
nsSharedBufferHandle<CharT>::~nsSharedBufferHandle()
// really don't want this to be |inline|
{
NS_ASSERTION(!IsReferenced(), "!IsReferenced()");
if ( !(mFlags & kIsSingleAllocationWithBuffer) )
{
CharT* string_storage = this->mDataStart;
if ( mFlags & kIsStorageDefinedSeparately )
string_storage = NS_REINTERPRET_CAST(nsFlexBufferHandle<CharT>*, this)->StorageStart();
nsMemory::Free(string_storage);
}
}
#endif // !defined(nsBufferHandle_h___)

View File

@@ -0,0 +1,703 @@
/* -*- 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) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#ifndef nsCharTraits_h___
#define nsCharTraits_h___
#include <ctype.h>
// for |EOF|, |WEOF|
#include <string.h>
// for |memcpy|, et al
#ifndef nscore_h___
#include "nscore.h"
// for |PRUnichar|
#endif
#ifdef HAVE_CPP_BOOL
typedef bool nsCharTraits_bool;
#else
typedef PRBool nsCharTraits_bool;
#endif
template <class CharT>
struct nsCharTraits
{
typedef CharT char_type;
typedef char incompatible_char_type;
static
void
assign( char_type& lhs, const char_type& rhs )
{
lhs = rhs;
}
// integer representation of characters:
typedef int int_type;
static
char_type
to_char_type( const int_type& c )
{
return char_type(c);
}
static
int_type
to_int_type( const char_type& c )
{
return int_type(c);
}
static
nsCharTraits_bool
eq_int_type( const int_type& lhs, const int_type& rhs )
{
return lhs == rhs;
}
// |char_type| comparisons:
static
nsCharTraits_bool
eq( const char_type& lhs, const char_type& rhs )
{
return lhs == rhs;
}
static
nsCharTraits_bool
lt( const char_type& lhs, const char_type& rhs )
{
return lhs < rhs;
}
// operations on s[n] arrays:
static
char_type*
copy( char_type* s1, const char_type* s2, size_t n )
{
char_type* result = s1;
while ( n-- )
assign(*s1++, *s2++);
return result;
}
static
char_type*
move( char_type* s1, const char_type* s2, size_t n )
{
char_type* result = s1;
if ( n )
{
if ( s2 > s1 )
copy(s1, s2, n);
else
{
s1 += n;
s2 += n;
while ( n-- )
assign(*--s1, *--s2);
}
}
return result;
}
static
char_type*
assign( char_type* s, size_t n, const char_type& c )
{
char_type* result = s;
while ( n-- )
assign(*s++, c);
return result;
}
static
int
compare( const char_type* s1, const char_type* s2, size_t n )
{
for ( ; n--; ++s1, ++s2 )
{
if ( lt(*s1, *s2) )
return -1;
if ( lt(*s2, *s1) )
return 1;
}
return 0;
}
static
size_t
length( const char_type* s )
{
size_t result = 0;
while ( !eq(*s++, CharT(0)) )
++result;
return result;
}
static
const char_type*
find( const char_type* s, size_t n, const char_type& c )
{
while ( n-- )
{
if ( eq(*s, c) )
return s;
++s;
}
return 0;
}
#if 0
// I/O related:
typedef streamoff off_type;
typedef streampos pos_type;
typedef mbstate_t state_type;
static
int_type
eof()
{
return EOF;
}
static
int_type
not_eof( const int_type& c )
{
return eq_int_type(c, eof()) ? ~eof() : c;
}
// static state_type get_state( pos_type );
#endif
};
NS_SPECIALIZE_TEMPLATE
struct nsCharTraits<char>
{
typedef char char_type;
typedef PRUnichar incompatible_char_type;
static
void
assign( char& lhs, char rhs )
{
lhs = rhs;
}
// integer representation of characters:
typedef int int_type;
static
char
to_char_type( int c )
{
return char(c);
}
static
int
to_int_type( char c )
{
return int( NS_STATIC_CAST(unsigned char, c) );
}
static
nsCharTraits_bool
eq_int_type( int lhs, int rhs )
{
return lhs == rhs;
}
// |char_type| comparisons:
static
nsCharTraits_bool
eq( char lhs, char rhs )
{
return lhs == rhs;
}
static
nsCharTraits_bool
lt( char lhs, char rhs )
{
return lhs < rhs;
}
// operations on s[n] arrays:
static
char*
move( char* s1, const char* s2, size_t n )
{
return NS_STATIC_CAST(char*, memmove(s1, s2, n));
}
static
char*
copy( char* s1, const char* s2, size_t n )
{
return NS_STATIC_CAST(char*, memcpy(s1, s2, n));
}
static
char*
assign( char* s, size_t n, char c )
{
return NS_STATIC_CAST(char*, memset(s, to_int_type(c), n));
}
static
int
compare( const char* s1, const char* s2, size_t n )
{
return memcmp(s1, s2, n);
}
static
size_t
length( const char* s )
{
return strlen(s);
}
static
const char*
find( const char* s, size_t n, char c )
{
return NS_REINTERPRET_CAST(const char*, memchr(s, to_int_type(c), n));
}
#if 0
// I/O related:
typedef streamoff off_type;
typedef streampos pos_type;
typedef mbstate_t state_type;
static
int_type
eof()
{
return EOF;
}
static
int
not_eof( int c )
{
return c==eof() ? ~eof() : c;
}
// static state_type get_state( pos_type );
#endif
};
#if 0
NS_SPECIALIZE_TEMPLATE
struct nsCharTraits<wchar_t>
{
typedef wchar_t char_type;
static
void
assign( wchar_t& lhs, wchar_t rhs )
{
lhs = rhs;
}
// integer representation of characters:
typedef wint_t int_type;
static
wchar_t
to_char_type( int_type c )
{
return wchar_t(c);
}
static
int_type
to_int_type( wchar_t c )
{
return int_type(c);
}
static
nsCharTraits_bool
eq_int_type( int_type lhs, int_type rhs )
{
return lhs == rhs;
}
// |char_type| comparisons:
static
nsCharTraits_bool
eq( wchar_t lhs, wchar_t rhs )
{
return lhs == rhs;
}
static
nsCharTraits_bool
lt( wchar_t lhs, wchar_t rhs )
{
return lhs < rhs;
}
// operations on s[n] arrays:
static
wchar_t*
move( wchar_t* s1, const wchar_t* s2, size_t n )
{
return NS_STATIC_CAST(wchar_t*, wmemmove(s1, s2, n));
}
static
wchar_t*
copy( wchar_t* s1, const wchar_t* s2, size_t n )
{
return NS_STATIC_CAST(wchar_t*, wmemcpy(s1, s2, n));
}
static
wchar_t*
assign( wchar_t* s, size_t n, wchar_t c )
{
return NS_STATIC_CAST(wchar_t*, wmemset(s, to_int_type(c), n));
}
static
int
compare( const wchar_t* s1, const wchar_t* s2, size_t n )
{
return wmemcmp(s1, s2, n);
}
static
size_t
length( const wchar_t* s )
{
return wcslen(s);
}
static
const wchar_t*
find( const wchar_t* s, size_t n, wchar_t c )
{
return NS_REINTERPRET_CAST(const wchar_t*, wmemchr(s, to_int_type(c), n));
}
#if 0
// I/O related:
typedef streamoff off_type;
typedef streampos pos_type;
typedef mbstate_t state_type;
static
int_type
eof()
{
return WEOF;
}
static
int_type
not_eof( int_type c )
{
return c==eof() ? ~eof() : c;
}
// static state_type get_state( pos_type );
#endif
};
#endif
template <class InputIterator>
struct nsCharSourceTraits
{
typedef typename InputIterator::difference_type difference_type;
#if 0
static
PRUint32
distance( const InputIterator& first, const InputIterator& last )
{
// ...
}
#endif
static
PRUint32
readable_distance( const InputIterator& iter )
{
return iter.size_forward();
}
static
PRUint32
readable_distance( const InputIterator& first, const InputIterator& last )
{
return PRUint32(SameFragment(first, last) ? last.get()-first.get() : first.size_forward());
}
static
const typename InputIterator::value_type*
read( const InputIterator& iter )
{
return iter.get();
}
static
void
advance( InputIterator& s, difference_type n )
{
s.advance(n);
}
};
#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
template <class CharT>
struct nsCharSourceTraits<CharT*>
{
typedef ptrdiff_t difference_type;
#if 0
static
PRUint32
distance( CharT* first, CharT* last )
{
return PRUint32(last-first);
}
#endif
static
PRUint32
readable_distance( CharT* s )
{
return PRUint32(nsCharTraits<CharT>::length(s));
// return numeric_limits<PRUint32>::max();
}
static
PRUint32
readable_distance( CharT* first, CharT* last )
{
return PRUint32(last-first);
}
static
const CharT*
read( CharT* s )
{
return s;
}
static
void
advance( CharT*& s, difference_type n )
{
s += n;
}
};
#else
NS_SPECIALIZE_TEMPLATE
struct nsCharSourceTraits<const char*>
{
typedef ptrdiff_t difference_type;
#if 0
static
PRUint32
distance( const char* first, const char* last )
{
return PRUint32(last-first);
}
#endif
static
PRUint32
readable_distance( const char* s )
{
return PRUint32(nsCharTraits<char>::length(s));
// return numeric_limits<PRUint32>::max();
}
static
PRUint32
readable_distance( const char* first, const char* last )
{
return PRUint32(last-first);
}
static
const char*
read( const char* s )
{
return s;
}
static
void
advance( const char*& s, difference_type n )
{
s += n;
}
};
NS_SPECIALIZE_TEMPLATE
struct nsCharSourceTraits<const PRUnichar*>
{
typedef ptrdiff_t difference_type;
#if 0
static
PRUint32
distance( const PRUnichar* first, const PRUnichar* last )
{
return PRUint32(last-first);
}
#endif
static
PRUint32
readable_distance( const PRUnichar* s )
{
return PRUint32(nsCharTraits<PRUnichar>::length(s));
// return numeric_limits<PRUint32>::max();
}
static
PRUint32
readable_distance( const PRUnichar* first, const PRUnichar* last )
{
return PRUint32(last-first);
}
static
const PRUnichar*
read( const PRUnichar* s )
{
return s;
}
static
void
advance( const PRUnichar*& s, difference_type n )
{
s += n;
}
};
#endif
template <class OutputIterator>
struct nsCharSinkTraits
{
static
PRUint32
write( OutputIterator& iter, const typename OutputIterator::value_type* s, PRUint32 n )
{
return iter.write(s, n);
}
};
#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
template <class CharT>
struct nsCharSinkTraits<CharT*>
{
static
PRUint32
write( CharT*& iter, const CharT* s, PRUint32 n )
{
nsCharTraits<CharT>::move(iter, s, n);
iter += n;
return n;
}
};
#else
NS_SPECIALIZE_TEMPLATE
struct nsCharSinkTraits<char*>
{
static
PRUint32
write( char*& iter, const char* s, PRUint32 n )
{
nsCharTraits<char>::move(iter, s, n);
iter += n;
return n;
}
};
NS_SPECIALIZE_TEMPLATE
struct nsCharSinkTraits<PRUnichar*>
{
static
PRUint32
write( PRUnichar*& iter, const PRUnichar* s, PRUint32 n )
{
nsCharTraits<PRUnichar>::move(iter, s, n);
iter += n;
return n;
}
};
#endif
#endif // !defined(nsCharTraits_h___)

View File

@@ -0,0 +1,69 @@
/* -*- 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 XPCOM.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#ifndef nsFragmentedString_h___
#define nsFragmentedString_h___
// WORK IN PROGRESS
#ifndef nsAWritableString_h___
#include "nsAWritableString.h"
#endif
#ifndef nsSharedBufferList_h___
#include "nsSharedBufferList.h"
#endif
class nsFragmentedString
: public basic_nsAWritableString<PRUnichar>
/*
...
*/
{
protected:
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 );
public:
nsFragmentedString() { }
virtual PRUint32 Length() const;
virtual void SetLength( PRUint32 aNewLength );
// virtual void SetCapacity( PRUint32 aNewCapacity );
// virtual void Cut( PRUint32 cutStart, PRUint32 cutLength );
protected:
// virtual void do_AssignFromReadable( const basic_nsAReadableString<PRUnichar>& );
// virtual void do_AppendFromReadable( const basic_nsAReadableString<PRUnichar>& );
// virtual void do_InsertFromReadable( const basic_nsAReadableString<PRUnichar>&, PRUint32 );
// virtual void do_ReplaceFromReadable( PRUint32, PRUint32, const basic_nsAReadableString<PRUnichar>& );
private:
nsSharedBufferList mBufferList;
};
#endif // !defined(nsFragmentedString_h___)

View 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author:
* Scott Collins <scc@mozilla.org>
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef nsPrintfCString_h___
#define nsPrintfCString_h___
#include "nsAWritableString.h"
/**
* |nsPrintfCString| lets you use a formated |printf| string as an |nsAReadableCString|.
*
* myCStr += nsPrintfCString("%f", 13.917);
* // ...a general purpose substitute for |AppendFloat|
*
* For longer patterns, you'll want to use the constructor that takes a length
*
* nsPrintfCString(128, "%f, %f, %f, %f, %f, %f, %f, %i, %f", x, y, z, 3.2, j, k, l, 3, 3.1);
*
* Exceding the default size (which you must specify in the constructor, it is not determined)
* causes an allocation, so avoid that. If your formatted string exceeds the allocated space, it is
* cut off at the size of the buffer, no error is reported (and no out-of-bounds writing occurs).
* This class is intended to be useful for numbers and short
* strings, not arbitrary formatting of other strings (e.g., with %s). There is currently no
* wide version of this class, since wide |printf| is not generally available. That means
* to get a wide version of your formatted data, you must, e.g.,
*
* CopyASCIItoUCS2(nsPrintfCString("%f", 13.917"), myStr);
*
* That's another good reason to avoid this class for anything but numbers ... as strings can be
* much more efficiently handled with |NS_LITERAL_[C]STRING| and |nsLiteral[C]String|.
*/
class nsPrintfCString
: public nsAReadableCString
{
enum { kLocalBufferSize=15 };
// ought to be large enough for most things ... a |long long| needs at most 20 (so you'd better ask)
// pinkerton suggests 7. We should measure and decide what's appropriate
public:
explicit nsPrintfCString( const char* format, ... );
nsPrintfCString( size_t n, const char* format, ...);
~nsPrintfCString();
virtual PRUint32 Length() const;
protected:
virtual const char* GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const;
// virtual PRBool GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest ) const;
private:
char* mStart;
PRUint32 mLength;
char mLocalBuffer[ kLocalBufferSize + 1 ];
};
#endif // !defined(nsPrintfCString_h___)

View 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 strings.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#ifndef nsPrivateSharableString_h___
#define nsPrivateSharableString_h___
#ifndef nsBufferHandle_h___
#include "nsBufferHandle.h"
#endif
/**
* This class is (will be) part of the machinery that makes
* most string implementations in this family share their underlying buffers
* when convenient. It is _not_ part of the abstract string interface,
* though other machinery interested in sharing buffers will know about it.
*/
template <class CharT>
class nsPrivateSharableString
{
public:
virtual const nsBufferHandle<CharT>* GetBufferHandle() const;
virtual const nsSharedBufferHandle<CharT>* GetSharedBufferHandle() const;
};
template <class CharT>
const nsSharedBufferHandle<CharT>*
nsPrivateSharableString<CharT>::GetSharedBufferHandle() const
{
return 0;
}
template <class CharT>
const nsBufferHandle<CharT>*
nsPrivateSharableString<CharT>::GetBufferHandle() const
{
return GetSharedBufferHandle();
}
#endif // !defined(nsPrivateSharableString_h___)

View File

@@ -0,0 +1,145 @@
/* -*- 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
* Johnny Stenbeck <jst@netscape.com>
*
*/
#ifndef nsReadableUtils_h___
#define nsReadableUtils_h___
/**
* I guess all the routines in this file are all mis-named.
* According to our conventions, they should be |NS_xxx|.
*/
#ifndef nsAWritableString_h___
#include "nsAWritableString.h"
#endif
#if 0
NS_COM size_t Distance( const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& );
NS_COM size_t Distance( const nsReadingIterator<char>&, const nsReadingIterator<char>& );
#endif
NS_COM void CopyUCS2toASCII( const nsAReadableString& aSource, nsAWritableCString& aDest );
NS_COM void CopyASCIItoUCS2( const nsAReadableCString& aSource, nsAWritableString& aDest );
/**
* Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
*
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
* Performs a lossy encoding conversion by chopping 16-bit wide characters down to 8-bits wide while copying |aSource| to your new buffer.
* This conversion is not well defined; but it reproduces legacy string behavior.
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
*
* @param aSource a 16-bit wide string
* @return a new |char| buffer you must free with |nsMemory::Free|.
*/
NS_COM char* ToNewCString( const nsAReadableString& aSource );
/**
* Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
*
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
*
* @param aSource an 8-bit wide string
* @return a new |char| buffer you must free with |nsMemory::Free|.
*/
NS_COM char* ToNewCString( const nsAReadableCString& aSource );
/**
* Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
*
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
* Performs a encoding conversion by converting 16-bit wide characters down to UTF8 encoded 8-bits wide string copying |aSource| to your new buffer.
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
*
* @param aSource a 16-bit wide string
* @return a new |char| buffer you must free with |nsMemory::Free|.
*/
NS_COM char* ToNewUTF8String( const nsAReadableString& aSource );
/**
* Returns a new |PRUnichar| buffer containing a zero-terminated copy of |aSource|.
*
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
*
* @param aSource a 16-bit wide string
* @return a new |PRUnichar| buffer you must free with |nsMemory::Free|.
*/
NS_COM PRUnichar* ToNewUnicode( const nsAReadableString& aSource );
/**
* Returns a new |PRUnichar| buffer containing a zero-terminated copy of |aSource|.
*
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
* Performs an encoding conversion by 0-padding 8-bit wide characters up to 16-bits wide while copying |aSource| to your new buffer.
* This conversion is not well defined; but it reproduces legacy string behavior.
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
*
* @param aSource an 8-bit wide string
* @return a new |PRUnichar| buffer you must free with |nsMemory::Free|.
*/
NS_COM PRUnichar* ToNewUnicode( const nsAReadableCString& aSource );
/**
* Copies |aLength| 16-bit characters from the start of |aSource| to the
* |PRUnichar| buffer |aDest|.
*
* After this operation |aDest| is not null terminated.
*
* @param aSource a 16-bit wide string
* @param aDest a |PRUnichar| buffer
* @param aLength the number of 16-bit characters to copy
* @return pointer to destination buffer - identical to |aDest|
*/
NS_COM PRUnichar* CopyUnicodeTo( const nsAReadableString& aSource,
PRUnichar* aDest,
PRUint32 aLength );
/**
* Returns |PR_TRUE| if |aString| contains only ASCII characters, that is, characters in the range (0x00, 0x7F).
*
* @param aString a 16-bit wide string to scan
*/
NS_COM PRBool IsASCII( const nsAReadableString& aString );
/**
* Converts case in place in the argument string.
*/
NS_COM void ToUpperCase( nsAWritableString& );
NS_COM void ToUpperCase( nsAWritableCString& );
NS_COM void ToLowerCase( nsAWritableString& );
NS_COM void ToLowerCase( nsAWritableCString& );
#endif // !defined(nsReadableUtils_h___)

View File

@@ -0,0 +1,163 @@
/* -*- 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 strings.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#ifndef nsSharedBufferList_h___
#define nsSharedBufferList_h___
#ifndef nsBufferHandle_h___
#include "nsBufferHandle.h"
// for |nsSharedBufferHandle|
#endif
#ifndef nscore_h___
#include "nscore.h"
// for |PRUnichar|
#endif
#ifndef nsAReadableString_h___
#include "nsAReadableString.h"
// for |nsReadingIterator|
#endif
/**
* This class forms the basis for several multi-fragment string classes, in
* particular: |nsFragmentedString| (though not yet), and |nsSlidingString|/|nsSlidingSubstring|.
*
* This class is not templated. It is provided only for |PRUnichar|-based strings.
* If we turn out to have a need for multi-fragment ASCII strings, then perhaps we'll templatize
* or else duplicate this class.
*/
class nsSharedBufferList
{
public:
class Buffer
: public nsFlexBufferHandle<PRUnichar>
{
public:
Buffer( PRUnichar* aDataStart, PRUnichar* aDataEnd, PRUnichar* aStorageStart, PRUnichar* aStorageEnd, PRBool aIsSingleAllocation=PR_FALSE )
: nsFlexBufferHandle<PRUnichar>(aDataStart, aDataEnd, aStorageStart, aStorageEnd)
{
if ( aIsSingleAllocation )
this->mFlags |= this->kIsSingleAllocationWithBuffer;
}
Buffer* mPrev;
Buffer* mNext;
private:
// pass-by-value is explicitly denied
Buffer( const Buffer& ); // NOT TO BE IMPLEMENTED
void operator=( const Buffer& ); // NOT TO BE IMPLEMENTED
};
struct Position
{
Buffer* mBuffer;
PRUnichar* mPosInBuffer;
Position() { }
Position( Buffer* aBuffer, PRUnichar* aPosInBuffer ) : mBuffer(aBuffer), mPosInBuffer(aPosInBuffer) { }
// Position( const Position& ); -- auto-generated copy-constructor OK
// Position& operator=( const Position& ); -- auto-generated copy-assignment OK
// ~Position(); -- auto-generated destructor OK
// iff |aIter| is a valid iterator into a |nsSharedBufferList|
explicit
Position( const nsReadingIterator<PRUnichar>& aIter )
: mBuffer( NS_CONST_CAST(Buffer*, NS_REINTERPRET_CAST(const Buffer*, aIter.fragment().mFragmentIdentifier)) ),
mPosInBuffer( NS_CONST_CAST(PRUnichar*, aIter.get()) )
{
// nothing else to do here
}
// iff |aIter| is a valid iterator into a |nsSharedBufferList|
Position&
operator=( const nsReadingIterator<PRUnichar>& aIter )
{
mBuffer = NS_CONST_CAST(Buffer*, NS_REINTERPRET_CAST(const Buffer*, aIter.fragment().mFragmentIdentifier));
mPosInBuffer = NS_CONST_CAST(PRUnichar*, aIter.get());
return *this;
}
void PointTo( Buffer* aBuffer, PRUnichar* aPosInBuffer ) { mBuffer=aBuffer; mPosInBuffer=aPosInBuffer; }
void PointBefore( Buffer* aBuffer ) { PointTo(aBuffer, aBuffer->DataStart()); }
void PointAfter( Buffer* aBuffer ) { PointTo(aBuffer, aBuffer->DataEnd()); }
// Position( const Position& ); -- automatically generated copy-constructor is OK
// Position& operator=( const Position& ); -- automatically generated copy-assignment operator is OK
};
public:
nsSharedBufferList( Buffer* aBuffer = 0 )
: mFirstBuffer(aBuffer),
mLastBuffer(aBuffer),
mTotalDataLength(0)
{
if ( aBuffer )
{
aBuffer->mPrev = aBuffer->mNext = 0;
mTotalDataLength = aBuffer->DataLength();
}
}
virtual ~nsSharedBufferList();
private:
// pass-by-value is explicitly denied
nsSharedBufferList( const nsSharedBufferList& ); // NOT TO BE IMPLEMENTED
void operator=( const nsSharedBufferList& ); // NOT TO BE IMPLEMENTED
public:
void LinkBuffer( Buffer*, Buffer*, Buffer* );
Buffer* UnlinkBuffer( Buffer* );
void SplitBuffer( const Position& );
static Buffer* NewSingleAllocationBuffer( const PRUnichar*, PRUint32, PRUint32 = 0 );
static Buffer* NewWrappingBuffer( PRUnichar*, PRUnichar*, PRUnichar* );
void DiscardSuffix( PRUint32 );
// need other discards: prefix, and by iterator or pointer or something
Buffer* GetFirstBuffer() { return mFirstBuffer; }
const Buffer* GetFirstBuffer() const { return mFirstBuffer; }
Buffer* GetLastBuffer() { return mLastBuffer; }
const Buffer* GetLastBuffer() const { return mLastBuffer; }
ptrdiff_t GetDataLength() const { return mTotalDataLength; }
protected:
void DestroyBuffers();
protected:
Buffer* mFirstBuffer;
Buffer* mLastBuffer;
ptrdiff_t mTotalDataLength;
};
#endif // !defined(nsSharedBufferList_h___)

View File

@@ -0,0 +1,203 @@
/* -*- 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.
*
* Original Author:
* Scott Collins <scc@mozilla.org>
*
* Contributor(s):
*/
#ifndef nsSharedString_h___
#define nsSharedString_h___
#ifndef nsAReadableString_h___
#include "nsAReadableString.h"
#endif
template <class CharT>
class basic_nsSharedString
: public basic_nsAReadableString<CharT>
/*
...
*/
{
public:
basic_nsSharedString( const CharT* data, size_t length )
: mRefCount(0), mData(data), mLength(length)
{
// nothing else to do here
}
private:
~basic_nsSharedString() { } // You can't sub-class me, or make an instance of me on the stack
// NOT TO BE IMPLEMENTED
// we're reference counted, remember. copying and passing by value are wrong
// basic_nsSharedString(); // we define at least one constructor, so the default constructor will not be auto-generated. It's wrong to create me with no data anyway
basic_nsSharedString( const basic_nsSharedString<CharT>& ); // copy-constructor, the auto generated one would reference somebody elses data
void operator=( const basic_nsSharedString<CharT>& ); // copy-assignment operator
// operator delete?
public:
virtual const CharT* GetReadableFragment( nsReadableFragment<CharT>&, nsFragmentRequest, PRUint32 ) const;
virtual
PRUint32
Length() const
{
return mLength;
}
nsrefcnt
AddRef() const
{
return ++mRefCount;
}
nsrefcnt
Release() const
{
nsrefcnt result = --mRefCount;
if ( !mRefCount )
{
// would have to call my destructor by hand here, if there was anything to destruct
operator delete(this); // form of |delete| should always match the |new|
}
return result;
}
private:
mutable nsrefcnt mRefCount;
const CharT* mData;
size_t mLength;
};
NS_DEF_TEMPLATE_STRING_COMPARISON_OPERATORS(basic_nsSharedString<CharT>, CharT)
template <class CharT>
const CharT*
basic_nsSharedString<CharT>::GetReadableFragment( nsReadableFragment<CharT>& aFragment, nsFragmentRequest aRequest, PRUint32 anOffset ) const
{
switch ( aRequest )
{
case kFirstFragment:
case kLastFragment:
case kFragmentAt:
aFragment.mEnd = (aFragment.mStart = mData) + mLength;
return aFragment.mStart + anOffset;
case kPrevFragment:
case kNextFragment:
default:
return 0;
}
}
template <class CharT>
class basic_nsSharedStringPtr
{
public:
// default constructor
basic_nsSharedStringPtr() : mRawPtr(0) { }
// copy-constructor
basic_nsSharedStringPtr( const basic_nsSharedStringPtr<CharT>& rhs )
: mRawPtr(rhs.mRawPtr)
{
mRawPtr->AddRef();
}
~basic_nsSharedStringPtr()
{
if ( mRawPtr )
mRawPtr->Release();
}
// copy-assignment operator
basic_nsSharedStringPtr<CharT>&
operator=( const basic_nsSharedStringPtr<CharT>& );
basic_nsSharedString<CharT>*
operator->() const
{
NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL string pointer with operator->().");
return mRawPtr;
}
basic_nsSharedString<CharT>&
operator*() const
{
NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL string pointer with operator->().");
return *mRawPtr;
}
private:
const basic_nsSharedString<CharT>* mRawPtr;
};
template <class CharT>
basic_nsSharedStringPtr<CharT>&
basic_nsSharedStringPtr<CharT>::operator=( const basic_nsSharedStringPtr<CharT>& rhs )
// Not |inline|
{
if ( rhs.mRawPtr )
rhs.mRawPtr->AddRef();
basic_nsSharedString<CharT>* oldPtr = mRawPtr;
mRawPtr = rhs.mRawPtr;
if ( oldPtr )
oldPtr->Release();
}
template <class CharT>
basic_nsSharedString<CharT>*
new_nsSharedString( const basic_nsAReadableString<CharT>& aReadable )
{
size_t object_size = ((sizeof(basic_nsSharedString<CharT>) + sizeof(CharT) - 1) / sizeof(CharT)) * sizeof(CharT);
size_t string_length = aReadable.Length();
size_t string_size = string_length * sizeof(CharT);
void* object_ptr = operator new(object_size + string_size);
if ( object_ptr )
{
typedef CharT* CharT_ptr;
CharT* string_ptr = CharT_ptr(NS_STATIC_CAST(unsigned char*, object_ptr) + object_size);
nsReadingIterator<CharT> fromBegin, fromEnd;
CharT* toBegin = string_ptr;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
return new (object_ptr) basic_nsSharedString<CharT>(string_ptr, string_length);
}
return 0;
}
typedef basic_nsSharedString<PRUnichar> nsSharedString;
typedef basic_nsSharedString<char> nsSharedCString;
typedef basic_nsSharedStringPtr<PRUnichar> nsSharedStringPtr;
typedef basic_nsSharedStringPtr<char> nsSharedCStringPtr;
#endif // !defined(nsSharedString_h___)

View File

@@ -0,0 +1,135 @@
/* -*- 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 strings.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#ifndef nsSlidingString_h___
#define nsSlidingString_h___
#include "nsAReadableString.h"
#include "nsSharedBufferList.h"
/**
* Maintains the sequence from the prev-most referenced buffer to the last buffer.
* As prev-most buffers become un-referenced, they are unlinked from the list
* and destroyed.
*
* One or more |nsSlidingSubstring|s may reference into the list. Each |nsSlidingSubstring|
* holds a reference into the prev-most buffer intersecting the
* substring it describes. The destructor of a |nsSlidingSubstring| releases this
* reference, allowing the buffer list to destroy the contiguous prefix of
* unreferenced buffers.
*
* A single instance of |nsSlidingString| may reference this list.
* Through that interface, new data can be appended onto the next-most end
* of the list. |nsSlidingString| also the client to advance its starting point.
*
*/
class nsSlidingSharedBufferList
: public nsSharedBufferList
{
public:
nsSlidingSharedBufferList( Buffer* aBuffer ) : nsSharedBufferList(aBuffer), mRefCount(0) { }
void AcquireReference() { ++mRefCount; }
void ReleaseReference() { if ( !--mRefCount ) delete this; }
void DiscardUnreferencedPrefix( Buffer* );
private:
PRUint32 mRefCount;
};
/**
* a substring over a buffer list, this
*/
class nsSlidingSubstring
: public nsPromiseReadable<PRUnichar>
{
public:
typedef nsSlidingSharedBufferList::Buffer Buffer;
typedef nsSlidingSharedBufferList::Position Position;
nsSlidingSubstring( const nsSlidingSubstring& ); // copy-constructor
nsSlidingSubstring( const nsSlidingSubstring& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd );
~nsSlidingSubstring();
virtual PRUint32 Length() const { return mLength; }
protected:
nsSlidingSubstring( nsSlidingSharedBufferList& aBufferList );
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
private:
// can't assign into me, I'm a read-only reference
void operator=( const nsSlidingSubstring& ); // NOT TO BE IMPLEMENTED
protected:
Position mStart;
Position mEnd;
nsSlidingSharedBufferList& mBufferList;
PRUint32 mLength;
};
/**
* An |nsSlidingSharedBufferList| may be modified by zero or one instances of this class.
*
*/
class nsSlidingString
: public nsSlidingSubstring
{
public:
nsSlidingString( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd );
// ...created by consuming ownership of a buffer ... |aStorageStart| must point to something
// that it will be OK for the slidking string to call |nsMemory::Free| on
// you are giving ownership to the string, it takes and keeps your buffer, deleting it (with |nsMemory::Free|) when done
void AppendBuffer( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd );
// void Append( ... ); do you want some |Append|s that copy the supplied data?
void DiscardPrefix( const nsReadingIterator<PRUnichar>& );
// any other way you want to do this?
private:
nsSlidingString( const nsSlidingString& ); // NOT TO BE IMPLEMENTED
void operator=( const nsSlidingString& ); // NOT TO BE IMPLEMENTED
};
#if 0
// this (or something similar) is what should appear in the parser, I think
#include "nsSlidingString.h"
typedef nsSlidingString nsParserString;
typedef nsSlidingSubstring nsParserToken;
#endif
#endif // !defined(nsSlidingString_h___)

View File

@@ -0,0 +1,162 @@
/* -*- 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 XPCOM.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author:
* Scott Collins <scc@mozilla.org>
*
* Contributor(s):
*/
#include "nsFragmentedString.h"
const PRUnichar*
nsFragmentedString::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const
{
const nsSharedBufferList::Buffer* buffer = 0;
switch ( aRequest )
{
case kPrevFragment:
buffer = NS_STATIC_CAST(const nsSharedBufferList::Buffer*, aFragment.mFragmentIdentifier)->mPrev;
break;
case kFirstFragment:
buffer = mBufferList.GetFirstBuffer();
break;
case kLastFragment:
buffer = mBufferList.GetLastBuffer();
break;
case kNextFragment:
buffer = NS_STATIC_CAST(const nsSharedBufferList::Buffer*, aFragment.mFragmentIdentifier)->mNext;
break;
case kFragmentAt:
// ...work...
break;
}
if ( buffer )
{
aFragment.mStart = buffer->DataStart();
aFragment.mEnd = buffer->DataEnd();
aFragment.mFragmentIdentifier = buffer;
return aFragment.mStart + aOffset;
}
return 0;
}
PRUnichar*
nsFragmentedString::GetWritableFragment( nsWritableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset )
{
nsSharedBufferList::Buffer* buffer = 0;
switch ( aRequest )
{
case kPrevFragment:
buffer = NS_STATIC_CAST(nsSharedBufferList::Buffer*, aFragment.mFragmentIdentifier)->mPrev;
break;
case kFirstFragment:
buffer = mBufferList.GetFirstBuffer();
break;
case kLastFragment:
buffer = mBufferList.GetLastBuffer();
break;
case kNextFragment:
buffer = NS_STATIC_CAST(nsSharedBufferList::Buffer*, aFragment.mFragmentIdentifier)->mNext;
break;
case kFragmentAt:
// ...work...
break;
}
if ( buffer )
{
aFragment.mStart = buffer->DataStart();
aFragment.mEnd = buffer->DataEnd();
aFragment.mFragmentIdentifier = buffer;
return aFragment.mStart + aOffset;
}
return 0;
}
/**
* ...
*/
PRUint32
nsFragmentedString::Length() const
{
return PRUint32(mBufferList.GetDataLength());
}
/**
* |SetLength|
*/
void
nsFragmentedString::SetLength( PRUint32 aNewLength )
{
// according to the current interpretation of |SetLength|,
// cut off characters from the end, or else add unitialized space to fill
if ( aNewLength < mBufferList.GetDataLength() )
{
// if ( aNewLength )
mBufferList.DiscardSuffix(mBufferList.GetDataLength()-aNewLength);
// else
// mBufferList.DestroyBuffers();
}
// temporarily... eliminate as soon as our munging routines don't need this form of |SetLength|
else if ( aNewLength > mBufferList.GetDataLength() )
{
size_t empty_space_to_add = aNewLength - mBufferList.GetDataLength();
nsSharedBufferList::Buffer* new_buffer = nsSharedBufferList::NewSingleAllocationBuffer(0, 0, empty_space_to_add);
new_buffer->DataEnd(new_buffer->DataStart()+empty_space_to_add);
mBufferList.LinkBuffer(mBufferList.GetLastBuffer(), new_buffer, 0);
}
}
#if 0
/**
* |SetCapacity|.
*
* If a client tries to increase the capacity of multi-fragment string, perhaps a single
* empty fragment of the appropriate size should be appended.
*/
void
nsFragmentedString::SetCapacity( PRUint32 aNewCapacity )
{
if ( !aNewCapacity )
{
// |SetCapacity(0)| is special and means ``release all storage''.
}
else if ( aNewCapacity > ... )
{
}
}
#endif

View File

@@ -0,0 +1,135 @@
/* -*- 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author:
* Scott Collins <scc@mozilla.org>
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "nsPrintfCString.h"
#include <stdarg.h>
#include "prprf.h"
nsPrintfCString::nsPrintfCString( const char* format, ... )
: mStart(mLocalBuffer),
mLength(0)
{
va_list ap;
size_t logical_capacity = kLocalBufferSize;
size_t physical_capacity = logical_capacity + 1;
va_start(ap, format);
mLength = PR_vsnprintf(mStart, physical_capacity, format, ap);
va_end(ap);
}
nsPrintfCString::nsPrintfCString( size_t n, const char* format, ... )
: mStart(mLocalBuffer),
mLength(0)
{
va_list ap;
// make sure there's at least |n| space
size_t logical_capacity = kLocalBufferSize;
if ( n > logical_capacity )
{
char* nonlocal_buffer = new char[n];
// if we got something, use it
if ( nonlocal_buffer )
{
mStart = nonlocal_buffer;
logical_capacity = n;
}
// else, it's the error case ... we'll use what space we have
// (since we can't throw)
}
size_t physical_capacity = logical_capacity + 1;
va_start(ap, format);
mLength = PR_vsnprintf(mStart, physical_capacity, format, ap);
va_end(ap);
}
nsPrintfCString::~nsPrintfCString()
{
if ( mStart != mLocalBuffer )
delete [] mStart;
}
PRUint32
nsPrintfCString::Length() const
{
return mLength;
}
#if 0
PRBool
nsPrintfCString::GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest ) const
{
switch ( aRequest )
{
case kFirstFragment:
case kLastFragment:
aFragment.mFragmentIdentifier = this;
// fall through
case kThisFragment:
aFragment.mStart = mStart;
aFragment.mEnd = mStart + mLength;
return PR_TRUE;
default:
return PR_FALSE;
}
}
#else
const char*
nsPrintfCString::GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const
{
switch ( aRequest )
{
case kFirstFragment:
case kLastFragment:
case kFragmentAt:
aFragment.mEnd = (aFragment.mStart = mStart) + mLength;
return mStart + aOffset;
case kPrevFragment:
case kNextFragment:
default:
return 0;
}
}
#endif

View File

@@ -0,0 +1,343 @@
/* -*- 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#include "nsReadableUtils.h"
#include "nsMemory.h"
#include "nsString.h"
#include "nsCRT.h"
template <class CharT> class CalculateLength
{
public:
typedef CharT value_type;
CalculateLength() : mDistance(0) { }
size_t GetDistance() const { return mDistance; }
PRUint32 write( const CharT*, PRUint32 N )
{ mDistance += N; return N; }
private:
size_t mDistance;
};
template <class CharT>
inline
size_t
Distance_Impl( const nsReadingIterator<CharT>& aStart,
const nsReadingIterator<CharT>& aEnd )
{
CalculateLength<CharT> sink;
nsReadingIterator<CharT> fromBegin(aStart);
copy_string(fromBegin, aEnd, sink);
return sink.GetDistance();
}
NS_COM
size_t
Distance( const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd )
{
return Distance_Impl(aStart, aEnd);
}
NS_COM
size_t
Distance( const nsReadingIterator<char>& aStart, const nsReadingIterator<char>& aEnd )
{
return Distance_Impl(aStart, aEnd);
}
/**
* A character sink that performs a |reinterpret_cast| style conversion between character types.
*/
template <class FromCharT, class ToCharT>
class LossyConvertEncoding
{
public:
typedef FromCharT value_type;
typedef FromCharT input_type;
typedef ToCharT output_type;
public:
LossyConvertEncoding( output_type* aDestination ) : mDestination(aDestination) { }
PRUint32
write( const input_type* aSource, PRUint32 aSourceLength )
{
const input_type* done_writing = aSource + aSourceLength;
while ( aSource < done_writing )
*mDestination++ = (output_type)(*aSource++); // use old-style cast to mimic old |ns[C]String| behavior
return aSourceLength;
}
void
write_terminator()
{
*mDestination = output_type(0);
}
private:
output_type* mDestination;
};
NS_COM
void
CopyUCS2toASCII( const nsAReadableString& aSource, nsAWritableCString& aDest )
{
// right now, this won't work on multi-fragment destinations
aDest.SetLength(aSource.Length());
nsReadingIterator<PRUnichar> fromBegin, fromEnd;
nsWritingIterator<char> toBegin;
LossyConvertEncoding<PRUnichar, char> converter(aDest.BeginWriting(toBegin).get());
copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter);
}
NS_COM
void
CopyASCIItoUCS2( const nsAReadableCString& aSource, nsAWritableString& aDest )
{
// right now, this won't work on multi-fragment destinations
aDest.SetLength(aSource.Length());
nsReadingIterator<char> fromBegin, fromEnd;
nsWritingIterator<PRUnichar> toBegin;
LossyConvertEncoding<char, PRUnichar> converter(aDest.BeginWriting(toBegin).get());
copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter);
}
/**
* A helper function that allocates a buffer of the desired character type big enough to hold a copy of the supplied string (plus a zero terminator).
*
* @param aSource an string you will eventually be making a copy of
* @return a new buffer (of the type specified by the second parameter) which you must free with |nsMemory::Free|.
*
*/
template <class FromCharT, class ToCharT>
inline
ToCharT*
AllocateStringCopy( const basic_nsAReadableString<FromCharT>& aSource, ToCharT* )
{
return NS_STATIC_CAST(ToCharT*, nsMemory::Alloc((aSource.Length()+1) * sizeof(ToCharT)));
}
NS_COM
char*
ToNewCString( const nsAReadableString& aSource )
{
char* result = AllocateStringCopy(aSource, (char*)0);
nsReadingIterator<PRUnichar> fromBegin, fromEnd;
LossyConvertEncoding<PRUnichar, char> converter(result);
copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter).write_terminator();
return result;
}
NS_COM
char*
ToNewUTF8String( const nsAReadableString& aSource )
{
NS_ConvertUCS2toUTF8 temp(aSource);
char* result;
if (temp.mOwnsBuffer) {
// We allocated. Trick the string into not freeing its buffer to
// avoid an extra allocation.
result = temp.mStr;
temp.mStr=0;
temp.mOwnsBuffer = PR_FALSE;
}
else {
// We didn't allocate a buffer, so we need to copy it out of the
// nsCAutoString's storage.
result = nsCRT::strdup(temp.mStr);
}
return result;
}
NS_COM
char*
ToNewCString( const nsAReadableCString& aSource )
{
// no conversion needed, just allocate a buffer of the correct length and copy into it
char* result = AllocateStringCopy(aSource, (char*)0);
nsReadingIterator<char> fromBegin, fromEnd;
char* toBegin = result;
*copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), toBegin) = char(0);
return result;
}
NS_COM
PRUnichar*
ToNewUnicode( const nsAReadableString& aSource )
{
// no conversion needed, just allocate a buffer of the correct length and copy into it
PRUnichar* result = AllocateStringCopy(aSource, (PRUnichar*)0);
nsReadingIterator<PRUnichar> fromBegin, fromEnd;
PRUnichar* toBegin = result;
*copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), toBegin) = PRUnichar(0);
return result;
}
NS_COM
PRUnichar*
ToNewUnicode( const nsAReadableCString& aSource )
{
PRUnichar* result = AllocateStringCopy(aSource, (PRUnichar*)0);
nsReadingIterator<char> fromBegin, fromEnd;
LossyConvertEncoding<char, PRUnichar> converter(result);
copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter).write_terminator();
return result;
}
NS_COM
PRUnichar*
CopyUnicodeTo( const nsAReadableString& aSource, PRUnichar* aDest, PRUint32 aLength )
{
nsReadingIterator<PRUnichar> fromBegin, fromEnd;
PRUnichar* toBegin = aDest;
copy_string(aSource.BeginReading(fromBegin), aSource.BeginReading(fromEnd).advance( PRInt32(aLength) ), toBegin);
return aDest;
}
NS_COM
PRBool
IsASCII( const nsAReadableString& aString )
{
static const PRUnichar NOT_ASCII = PRUnichar(~0x007F);
// Don't want to use |copy_string| for this task, since we can stop at the first non-ASCII character
nsReadingIterator<PRUnichar> done_reading;
aString.EndReading(done_reading);
// for each chunk of |aString|...
PRUint32 fragmentLength = 0;
nsReadingIterator<PRUnichar> iter;
for ( aString.BeginReading(iter); iter != done_reading; iter.advance( PRInt32(fragmentLength) ) )
{
fragmentLength = PRUint32(iter.size_forward());
const PRUnichar* c = iter.get();
const PRUnichar* fragmentEnd = c + fragmentLength;
// for each character in this chunk...
while ( c < fragmentEnd )
if ( *c++ & NOT_ASCII )
return PR_FALSE;
}
return PR_TRUE;
}
/**
* A character sink for case conversion.
*/
template <class CharT>
class ConvertToUpperCase
{
public:
typedef CharT value_type;
PRUint32
write( const CharT* aSource, PRUint32 aSourceLength )
{
for ( int i=0; i<aSourceLength; ++i )
NS_CONST_CAST(CharT*, aSource)[i] = nsCRT::ToUpper(aSource[i]);
return aSourceLength;
}
};
NS_COM
void
ToUpperCase( nsAWritableString& aString )
{
nsAWritableString::iterator fromBegin, fromEnd;
ConvertToUpperCase<PRUnichar> converter;
copy_string(aString.BeginWriting(fromBegin), aString.EndWriting(fromEnd), converter);
}
NS_COM
void
ToUpperCase( nsAWritableCString& aCString )
{
nsAWritableCString::iterator fromBegin, fromEnd;
ConvertToUpperCase<char> converter;
copy_string(aCString.BeginWriting(fromBegin), aCString.EndWriting(fromEnd), converter);
}
/**
* A character sink for case conversion.
*/
template <class CharT>
class ConvertToLowerCase
{
public:
typedef CharT value_type;
PRUint32
write( const CharT* aSource, PRUint32 aSourceLength )
{
for ( int i=0; i<aSourceLength; ++i )
NS_CONST_CAST(CharT*, aSource)[i] = nsCRT::ToLower(aSource[i]);
return aSourceLength;
}
};
NS_COM
void
ToLowerCase( nsAWritableString& aString )
{
nsAWritableString::iterator fromBegin, fromEnd;
ConvertToLowerCase<PRUnichar> converter;
copy_string(aString.BeginWriting(fromBegin), aString.EndWriting(fromEnd), converter);
}
NS_COM
void
ToLowerCase( nsAWritableCString& aCString )
{
nsAWritableCString::iterator fromBegin, fromEnd;
ConvertToLowerCase<char> converter;
copy_string(aCString.BeginWriting(fromBegin), aCString.EndWriting(fromEnd), converter);
}

View File

@@ -0,0 +1,186 @@
/* -*- 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 strings.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#include "nsSharedBufferList.h"
#include "nsAlgorithm.h"
// for |copy_string|
#include <new.h>
void
nsSharedBufferList::DestroyBuffers()
{
// destroy the entire list of buffers, without bothering to manage their links
Buffer* next_buffer;
for ( Buffer* cur_buffer=mFirstBuffer; cur_buffer; cur_buffer=next_buffer )
{
next_buffer = cur_buffer->mNext;
operator delete(cur_buffer);
}
mFirstBuffer = mLastBuffer = 0;
mTotalDataLength = 0;
}
nsSharedBufferList::~nsSharedBufferList()
{
DestroyBuffers();
}
nsSharedBufferList::Buffer*
nsSharedBufferList::NewSingleAllocationBuffer( const PRUnichar* aData, PRUint32 aDataLength, PRUint32 aAdditionalSpace )
{
size_t object_size = ((sizeof(Buffer) + sizeof(PRUnichar) - 1) / sizeof(PRUnichar)) * sizeof(PRUnichar);
PRUint32 buffer_length = aDataLength + aAdditionalSpace;
size_t buffer_size = size_t(buffer_length) * sizeof(PRUnichar);
void* object_ptr = operator new(object_size + buffer_size);
if ( object_ptr )
{
typedef PRUnichar* PRUnichar_ptr;
PRUnichar* buffer_ptr = PRUnichar_ptr(NS_STATIC_CAST(unsigned char*, object_ptr) + object_size);
if ( aDataLength )
{
PRUnichar* toBegin = buffer_ptr;
copy_string(aData, aData+aDataLength, toBegin);
}
return new (object_ptr) Buffer(buffer_ptr, buffer_ptr+aDataLength, buffer_ptr, buffer_ptr+buffer_length, PR_TRUE);
}
return 0;
}
nsSharedBufferList::Buffer*
nsSharedBufferList::NewWrappingBuffer( PRUnichar* aDataStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd )
{
return new Buffer(aDataStart, aDataEnd, aDataStart, aStorageEnd);
}
void
nsSharedBufferList::LinkBuffer( Buffer* aPrevBuffer, Buffer* aNewBuffer, Buffer* aNextBuffer )
{
NS_ASSERTION(aNewBuffer, "aNewBuffer");
NS_ASSERTION(aPrevBuffer || mFirstBuffer == aNextBuffer, "aPrevBuffer || mFirstBuffer == aNextBuffer");
NS_ASSERTION(!aPrevBuffer || aPrevBuffer->mNext == aNextBuffer, "!aPrevBuffer || aPrevBuffer->mNext == aNextBuffer");
NS_ASSERTION(aNextBuffer || mLastBuffer == aPrevBuffer, "aNextBuffer || mLastBuffer == aPrevBuffer");
NS_ASSERTION(!aNextBuffer || aNextBuffer->mPrev == aPrevBuffer, "!aNextBuffer || aNextBuffer->mPrev == aPrevBuffer");
if ( (aNewBuffer->mPrev = aPrevBuffer) )
aPrevBuffer->mNext = aNewBuffer;
else
mFirstBuffer = aNewBuffer;
if ( (aNewBuffer->mNext = aNextBuffer) )
aNextBuffer->mPrev = aNewBuffer;
else
mLastBuffer = aNewBuffer;
mTotalDataLength += aNewBuffer->DataLength();
}
void
nsSharedBufferList::SplitBuffer( const Position& aSplitPosition )
{
Buffer* bufferToSplit = aSplitPosition.mBuffer;
NS_ASSERTION(bufferToSplit, "bufferToSplit");
ptrdiff_t splitOffset = aSplitPosition.mPosInBuffer - bufferToSplit->DataStart();
NS_ASSERTION(0 <= splitOffset && splitOffset <= bufferToSplit->DataLength(), "|splitOffset| within buffer");
if ( (bufferToSplit->DataLength() >> 1) > splitOffset )
{
Buffer* new_buffer = NewSingleAllocationBuffer(bufferToSplit->DataStart(), PRUint32(splitOffset));
LinkBuffer(bufferToSplit->mPrev, new_buffer, bufferToSplit);
bufferToSplit->DataStart(aSplitPosition.mPosInBuffer);
}
else
{
Buffer* new_buffer = NewSingleAllocationBuffer(bufferToSplit->DataStart()+splitOffset, PRUint32(bufferToSplit->DataLength()-splitOffset));
LinkBuffer(bufferToSplit, new_buffer, bufferToSplit->mNext);
bufferToSplit->DataEnd(aSplitPosition.mPosInBuffer);
}
}
nsSharedBufferList::Buffer*
nsSharedBufferList::UnlinkBuffer( Buffer* aBufferToUnlink )
{
NS_ASSERTION(aBufferToUnlink, "aBufferToUnlink");
Buffer* prev_buffer = aBufferToUnlink->mPrev;
Buffer* next_buffer = aBufferToUnlink->mNext;
if ( prev_buffer )
prev_buffer->mNext = next_buffer;
else
mFirstBuffer = next_buffer;
if ( next_buffer )
next_buffer->mPrev = prev_buffer;
else
mLastBuffer = prev_buffer;
mTotalDataLength -= aBufferToUnlink->DataLength();
return aBufferToUnlink;
}
void
nsSharedBufferList::DiscardSuffix( PRUint32 /* aLengthToDiscard */ )
{
// XXX
}
#if 0
template <class CharT>
void
nsChunkList<CharT>::CutTrailingData( PRUint32 aLengthToCut )
{
Chunk* chunk = mLastChunk;
while ( chunk && aLengthToCut )
{
Chunk* prev_chunk = chunk->mPrev;
if ( aLengthToCut < chunk->mDataLength )
{
chunk->mDataLength -= aLengthToCut;
aLengthToCut = 0;
}
else
{
RemoveChunk(chunk);
aLengthToCut -= chunk->mDataLength;
operator delete(chunk);
}
chunk = prev_chunk;
}
}
#endif

View File

@@ -0,0 +1,180 @@
/* -*- 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 strings.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#include "nsSlidingString.h"
void
nsSlidingSharedBufferList::DiscardUnreferencedPrefix( Buffer* aRecentlyReleasedBuffer )
{
if ( aRecentlyReleasedBuffer == mFirstBuffer )
{
while ( mFirstBuffer && !mFirstBuffer->IsReferenced() )
delete UnlinkBuffer(mFirstBuffer);
}
}
ptrdiff_t Distance( const nsSharedBufferList::Position&, const nsSharedBufferList::Position& );
ptrdiff_t
Distance( const nsSharedBufferList::Position& aStart, const nsSharedBufferList::Position& aEnd )
{
ptrdiff_t result = 0;
if ( aStart.mBuffer == aEnd.mBuffer )
result = aEnd.mPosInBuffer - aStart.mPosInBuffer;
else
{
result = aStart.mBuffer->DataEnd() - aStart.mPosInBuffer;
for ( nsSharedBufferList::Buffer* b = aStart.mBuffer->mNext; b != aEnd.mBuffer; b = b->mNext )
result += b->DataLength();
result += aEnd.mPosInBuffer - aEnd.mBuffer->DataStart();
}
return result;
}
nsSlidingSubstring::nsSlidingSubstring( const nsSlidingSubstring& aString )
: mStart(aString.mStart),
mEnd(aString.mEnd),
mBufferList(aString.mBufferList),
mLength(aString.mLength)
{
mBufferList.AcquireReference();
mStart.mBuffer->AcquireReference();
}
nsSlidingSubstring::nsSlidingSubstring( const nsSlidingSubstring& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd )
: mStart(aStart),
mEnd(aEnd),
mBufferList(aString.mBufferList),
mLength(PRUint32(Distance(mStart, mEnd)))
{
mBufferList.AcquireReference();
mStart.mBuffer->AcquireReference();
}
nsSlidingSubstring::nsSlidingSubstring( nsSlidingSharedBufferList& aBufferList )
: mBufferList(aBufferList)
{
mBufferList.AcquireReference();
mStart.PointBefore(mBufferList.GetFirstBuffer());
mStart.mBuffer->AcquireReference();
mEnd.PointAfter(mBufferList.GetLastBuffer());
mLength = PRUint32(Distance(mStart, mEnd));
}
nsSlidingSubstring::~nsSlidingSubstring()
{
mStart.mBuffer->ReleaseReference();
mBufferList.DiscardUnreferencedPrefix(mStart.mBuffer);
mBufferList.ReleaseReference();
}
const PRUnichar*
nsSlidingSubstring::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const
{
const Buffer* result_buffer = 0;
switch ( aRequest )
{
case kPrevFragment:
{
const Buffer* current_buffer = NS_STATIC_CAST(const Buffer*, aFragment.mFragmentIdentifier);
if ( current_buffer != mStart.mBuffer )
result_buffer = current_buffer->mPrev;
}
break;
case kFirstFragment:
result_buffer = mStart.mBuffer;
break;
case kLastFragment:
result_buffer = mEnd.mBuffer;
break;
case kNextFragment:
{
const Buffer* current_buffer = NS_STATIC_CAST(const Buffer*, aFragment.mFragmentIdentifier);
if ( current_buffer != mEnd.mBuffer )
result_buffer = current_buffer->mNext;
}
break;
case kFragmentAt:
// ...work...
break;
}
if ( result_buffer )
{
if ( result_buffer == mStart.mBuffer )
aFragment.mStart = mStart.mPosInBuffer;
else
aFragment.mStart = result_buffer->DataStart();
if ( result_buffer == mEnd.mBuffer )
aFragment.mEnd = mEnd.mPosInBuffer;
else
aFragment.mEnd = result_buffer->DataEnd();
aFragment.mFragmentIdentifier = result_buffer;
return aFragment.mStart + aOffset;
}
return 0;
}
nsSlidingString::nsSlidingString( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd )
: nsSlidingSubstring(*(new nsSlidingSharedBufferList(nsSlidingSharedBufferList::NewWrappingBuffer(aStorageStart, aDataEnd, aStorageEnd))))
{
// nothing else to do here
}
void
nsSlidingString::AppendBuffer( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd )
{
Buffer* new_buffer = new Buffer(aStorageStart, aDataEnd, aStorageStart, aStorageEnd);
Buffer* old_last_buffer = mBufferList.GetLastBuffer();
mBufferList.LinkBuffer(old_last_buffer, new_buffer, 0);
mLength += new_buffer->DataLength();
mEnd.PointAfter(new_buffer);
}
void
nsSlidingString::DiscardPrefix( const nsReadingIterator<PRUnichar>& aIter )
{
Position old_start(mStart);
mStart = aIter;
mLength -= Distance(old_start, mStart);
mStart.mBuffer->AcquireReference();
old_start.mBuffer->ReleaseReference();
mBufferList.DiscardUnreferencedPrefix(old_start.mBuffer);
}

View File

@@ -0,0 +1,746 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 oqr
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is nsTraceMalloc.c/bloatblame.c code, released
* April 19, 2000.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Brendan Eich, 14-April-2000
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the MPL or the GPL.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#else
extern int getopt(int argc, char *const *argv, const char *shortopts);
extern char *optarg;
extern int optind;
#endif
#include <math.h>
#include <time.h>
#include <sys/stat.h>
#include "prtypes.h"
#include "prlog.h"
#include "prprf.h"
#include "plhash.h"
#include "nsTraceMalloc.h"
#include "tmreader.h"
static char *program;
static int sort_by_direct = 0;
static int js_mode = 0;
static int do_tree_dump = 0;
static int unified_output = 0;
static char *function_dump = NULL;
static uint32 min_subtotal = 0;
static void compute_callsite_totals(tmcallsite *site)
{
tmcallsite *kid;
site->allocs.bytes.total += site->allocs.bytes.direct;
site->allocs.calls.total += site->allocs.calls.direct;
for (kid = site->kids; kid; kid = kid->siblings) {
compute_callsite_totals(kid);
site->allocs.bytes.total += kid->allocs.bytes.total;
site->allocs.calls.total += kid->allocs.calls.total;
}
}
static void walk_callsite_tree(tmcallsite *site, int level, int kidnum, FILE *fp)
{
tmcallsite *parent;
tmgraphnode *meth, *pmeth, *comp, *pcomp, *lib, *plib;
int old_meth_low, old_comp_low, old_lib_low, nkids;
tmcallsite *kid;
parent = site->parent;
meth = comp = lib = NULL;
if (parent) {
meth = site->method;
if (meth) {
pmeth = parent->method;
if (pmeth && pmeth != meth) {
if (!meth->low) {
meth->allocs.bytes.total += site->allocs.bytes.total;
meth->allocs.calls.total += site->allocs.calls.total;
}
if (!tmgraphnode_connect(pmeth, meth, site))
goto bad;
comp = meth->up;
if (comp) {
pcomp = pmeth->up;
if (pcomp && pcomp != comp) {
if (!comp->low) {
comp->allocs.bytes.total
+= site->allocs.bytes.total;
comp->allocs.calls.total
+= site->allocs.calls.total;
}
if (!tmgraphnode_connect(pcomp, comp, site))
goto bad;
lib = comp->up;
if (lib) {
plib = pcomp->up;
if (plib && plib != lib) {
if (!lib->low) {
lib->allocs.bytes.total
+= site->allocs.bytes.total;
lib->allocs.calls.total
+= site->allocs.calls.total;
}
if (!tmgraphnode_connect(plib, lib, site))
goto bad;
}
old_lib_low = lib->low;
if (!old_lib_low)
lib->low = level;
}
}
old_comp_low = comp->low;
if (!old_comp_low)
comp->low = level;
}
}
old_meth_low = meth->low;
if (!old_meth_low)
meth->low = level;
}
}
if (do_tree_dump) {
fprintf(fp, "%c%*s%3d %3d %s %lu %ld\n",
site->kids ? '+' : '-', level, "", level, kidnum,
meth ? tmgraphnode_name(meth) : "???",
(unsigned long)site->allocs.bytes.direct,
(long)site->allocs.bytes.total);
}
nkids = 0;
level++;
for (kid = site->kids; kid; kid = kid->siblings) {
walk_callsite_tree(kid, level, nkids, fp);
nkids++;
}
if (meth) {
if (!old_meth_low)
meth->low = 0;
if (comp) {
if (!old_comp_low)
comp->low = 0;
if (lib) {
if (!old_lib_low)
lib->low = 0;
}
}
}
return;
bad:
perror(program);
exit(1);
}
/*
* Linked list bubble-sort (waterson and brendan went bald hacking this).
*
* Sort the list in non-increasing order, using the expression passed as the
* 'lessthan' formal macro parameter. This expression should use 'curr' as
* the pointer to the current node (of type nodetype) and 'next' as the next
* node pointer. It should return true if curr is less than next, and false
* otherwise.
*/
#define BUBBLE_SORT_LINKED_LIST(listp, nodetype, lessthan) \
PR_BEGIN_MACRO \
nodetype *curr, **currp, *next, **nextp, *tmp; \
\
currp = listp; \
while ((curr = *currp) != NULL && curr->next) { \
nextp = &curr->next; \
while ((next = *nextp) != NULL) { \
if (lessthan) { \
tmp = curr->next; \
*currp = tmp; \
if (tmp == next) { \
PR_ASSERT(nextp == &curr->next); \
curr->next = next->next; \
next->next = curr; \
} else { \
*nextp = next->next; \
curr->next = next->next; \
next->next = tmp; \
*currp = next; \
*nextp = curr; \
nextp = &curr->next; \
} \
curr = next; \
continue; \
} \
nextp = &next->next; \
} \
currp = &curr->next; \
} \
PR_END_MACRO
static PRIntn tabulate_node(PLHashEntry *he, PRIntn i, void *arg)
{
tmgraphnode *node = (tmgraphnode*) he;
tmgraphnode **table = (tmgraphnode**) arg;
table[i] = node;
BUBBLE_SORT_LINKED_LIST(&node->down, tmgraphnode,
(curr->allocs.bytes.total < next->allocs.bytes.total));
return HT_ENUMERATE_NEXT;
}
/* Sort in reverse size order, so biggest node comes first. */
static int node_table_compare(const void *p1, const void *p2)
{
const tmgraphnode *node1, *node2;
uint32 key1, key2;
node1 = *(const tmgraphnode**) p1;
node2 = *(const tmgraphnode**) p2;
if (sort_by_direct) {
key1 = node1->allocs.bytes.direct;
key2 = node2->allocs.bytes.direct;
} else {
key1 = node1->allocs.bytes.total;
key2 = node2->allocs.bytes.total;
}
return (key2 < key1) ? -1 : (key2 > key1) ? 1 : 0;
}
static int mean_size_compare(const void *p1, const void *p2)
{
const tmgraphnode *node1, *node2;
double div1, div2, key1, key2;
node1 = *(const tmgraphnode**) p1;
node2 = *(const tmgraphnode**) p2;
div1 = (double)node1->allocs.calls.direct;
div2 = (double)node2->allocs.calls.direct;
if (div1 == 0 || div2 == 0)
return div2 - div1;
key1 = (double)node1->allocs.bytes.direct / div1;
key2 = (double)node2->allocs.bytes.direct / div2;
if (key1 < key2)
return 1;
if (key1 > key2)
return -1;
return 0;
}
static const char *prettybig(uint32 num, char *buf, size_t limit)
{
if (num >= 1000000000)
PR_snprintf(buf, limit, "%1.2fG", (double) num / 1e9);
else if (num >= 1000000)
PR_snprintf(buf, limit, "%1.2fM", (double) num / 1e6);
else if (num >= 1000)
PR_snprintf(buf, limit, "%1.2fK", (double) num / 1e3);
else
PR_snprintf(buf, limit, "%lu", (unsigned long) num);
return buf;
}
static double percent(uint32 num, uint32 total)
{
if (num == 0)
return 0.0;
return ((double) num * 100) / (double) total;
}
static void sort_graphlink_list(tmgraphlink **listp, int which)
{
BUBBLE_SORT_LINKED_LIST(listp, tmgraphlink,
(TM_LINK_TO_EDGE(curr, which)->allocs.bytes.total
< TM_LINK_TO_EDGE(next, which)->allocs.bytes.total));
}
static void dump_graphlink_list(tmgraphlink *list, int which, const char *name,
FILE *fp)
{
tmcounts bytes;
tmgraphlink *link;
tmgraphedge *edge;
char buf[16];
bytes.direct = bytes.total = 0;
for (link = list; link; link = link->next) {
edge = TM_LINK_TO_EDGE(link, which);
bytes.direct += edge->allocs.bytes.direct;
bytes.total += edge->allocs.bytes.total;
}
if (js_mode) {
fprintf(fp,
" %s:{dbytes:%ld, tbytes:%ld, edges:[\n",
name, (long) bytes.direct, (long) bytes.total);
for (link = list; link; link = link->next) {
edge = TM_LINK_TO_EDGE(link, which);
fprintf(fp,
" {node:%d, dbytes:%ld, tbytes:%ld},\n",
link->node->sort,
(long) edge->allocs.bytes.direct,
(long) edge->allocs.bytes.total);
}
fputs(" ]},\n", fp);
} else {
fputs("<td valign=top>", fp);
for (link = list; link; link = link->next) {
edge = TM_LINK_TO_EDGE(link, which);
fprintf(fp,
"<a href='#%s'>%s&nbsp;(%1.2f%%)</a>\n",
tmgraphnode_name(link->node),
prettybig(edge->allocs.bytes.total, buf, sizeof buf),
percent(edge->allocs.bytes.total, bytes.total));
}
fputs("</td>", fp);
}
}
static void dump_graph(tmreader *tmr, PLHashTable *hashtbl, const char *varname,
const char *title, FILE *fp)
{
uint32 i, count;
tmgraphnode **table, *node;
char *name;
size_t namelen;
char buf1[16], buf2[16], buf3[16], buf4[16];
static char NA[] = "N/A";
count = hashtbl->nentries;
table = (tmgraphnode**) malloc(count * sizeof(tmgraphnode*));
if (!table) {
perror(program);
exit(1);
}
PL_HashTableEnumerateEntries(hashtbl, tabulate_node, table);
qsort(table, count, sizeof(tmgraphnode*), node_table_compare);
for (i = 0; i < count; i++)
table[i]->sort = i;
if (js_mode) {
fprintf(fp,
"var %s = {\n name:'%s', title:'%s', nodes:[\n",
varname, varname, title);
} else {
fprintf(fp,
"<table border=1>\n"
"<tr>"
"<th>%s</th>"
"<th>Down</th>"
"<th>Next</th>"
"<th>Total/Direct (percents)</th>"
"<th>Allocations</th>"
"<th>Fan-in</th>"
"<th>Fan-out</th>"
"</tr>\n",
title);
}
for (i = 0; i < count; i++) {
/* Don't bother with truly puny nodes. */
node = table[i];
if (node->allocs.bytes.total < min_subtotal)
break;
name = tmgraphnode_name(node);
if (js_mode) {
fprintf(fp,
" {name:'%s', dbytes:%ld, tbytes:%ld,"
" dallocs:%ld, tallocs:%ld,\n",
name,
(long) node->allocs.bytes.direct,
(long) node->allocs.bytes.total,
(long) node->allocs.calls.direct,
(long) node->allocs.calls.total);
} else {
namelen = strlen(name);
fprintf(fp,
"<tr>"
"<td valign=top><a name='%s'>%.*s%s</a></td>",
name,
(namelen > 40) ? 40 : (int)namelen, name,
(namelen > 40) ? "<i>...</i>" : "");
if (node->down) {
fprintf(fp,
"<td valign=top><a href='#%s'><i>down</i></a></td>",
tmgraphnode_name(node->down));
} else {
fputs("<td></td>", fp);
}
if (node->next) {
fprintf(fp,
"<td valign=top><a href='#%s'><i>next</i></a></td>",
tmgraphnode_name(node->next));
} else {
fputs("<td></td>", fp);
}
fprintf(fp,
"<td valign=top>%s/%s (%1.2f%%/%1.2f%%)</td>"
"<td valign=top>%s/%s (%1.2f%%/%1.2f%%)</td>",
prettybig(node->allocs.bytes.total, buf1, sizeof buf1),
prettybig(node->allocs.bytes.direct, buf2, sizeof buf2),
percent(node->allocs.bytes.total,
tmr->calltree_root.allocs.bytes.total),
percent(node->allocs.bytes.direct,
tmr->calltree_root.allocs.bytes.total),
prettybig(node->allocs.calls.total, buf3, sizeof buf3),
prettybig(node->allocs.calls.direct, buf4, sizeof buf4),
percent(node->allocs.calls.total,
tmr->calltree_root.allocs.calls.total),
percent(node->allocs.calls.direct,
tmr->calltree_root.allocs.calls.total));
}
/* NB: we must use 'fin' because 'in' is a JS keyword! */
sort_graphlink_list(&node->in, TM_EDGE_IN_LINK);
dump_graphlink_list(node->in, TM_EDGE_IN_LINK, "fin", fp);
sort_graphlink_list(&node->out, TM_EDGE_OUT_LINK);
dump_graphlink_list(node->out, TM_EDGE_OUT_LINK, "out", fp);
if (js_mode)
fputs(" },\n", fp);
else
fputs("</tr>\n", fp);
}
if (js_mode) {
fputs("]};\n", fp);
} else {
fputs("</table>\n<hr>\n", fp);
qsort(table, count, sizeof(tmgraphnode*), mean_size_compare);
fprintf(fp,
"<table border=1>\n"
"<tr><th colspan=4>Direct Allocators</th></tr>\n"
"<tr>"
"<th>%s</th>"
"<th>Mean&nbsp;Size</th>"
"<th>StdDev</th>"
"<th>Allocations<th>"
"</tr>\n",
title);
for (i = 0; i < count; i++) {
double allocs, bytes, mean, variance, sigma;
node = table[i];
allocs = (double)node->allocs.calls.direct;
if (!allocs)
continue;
/* Compute direct-size mean and standard deviation. */
bytes = (double)node->allocs.bytes.direct;
mean = bytes / allocs;
variance = allocs * node->sqsum - bytes * bytes;
if (variance < 0 || allocs == 1)
variance = 0;
else
variance /= allocs * (allocs - 1);
sigma = sqrt(variance);
name = tmgraphnode_name(node);
namelen = strlen(name);
fprintf(fp,
"<tr>"
"<td valign=top>%.*s%s</td>"
"<td valign=top>%s</td>"
"<td valign=top>%s</td>"
"<td valign=top>%s</td>"
"</tr>\n",
(namelen > 65) ? 45 : (int)namelen, name,
(namelen > 65) ? "<i>...</i>" : "",
prettybig((uint32)mean, buf1, sizeof buf1),
prettybig((uint32)sigma, buf2, sizeof buf2),
prettybig(node->allocs.calls.direct, buf3, sizeof buf3));
}
fputs("</table>\n", fp);
}
free((void*) table);
}
static void my_tmevent_handler(tmreader *tmr, tmevent *event)
{
switch (event->type) {
case TM_EVENT_STATS:
if (js_mode)
break;
fprintf(stdout,
"<p><table border=1>"
"<tr><th>Counter</th><th>Value</th></tr>\n"
"<tr><td>maximum actual stack depth</td><td align=right>%lu</td></tr>\n"
"<tr><td>maximum callsite tree depth</td><td align=right>%lu</td></tr>\n"
"<tr><td>number of parent callsites</td><td align=right>%lu</td></tr>\n"
"<tr><td>maximum kids per parent</td><td align=right>%lu</td></tr>\n"
"<tr><td>hits looking for a kid</td><td align=right>%lu</td></tr>\n"
"<tr><td>misses looking for a kid</td><td align=right>%lu</td></tr>\n"
"<tr><td>steps over other kids</td><td align=right>%lu</td></tr>\n"
"<tr><td>callsite recurrences</td><td align=right>%lu</td></tr>\n"
"<tr><td>number of stack backtraces</td><td align=right>%lu</td></tr>\n"
"<tr><td>backtrace failures</td><td align=right>%lu</td></tr>\n"
"<tr><td>backtrace malloc failures</td><td align=right>%lu</td></tr>\n"
"<tr><td>backtrace dladdr failures</td><td align=right>%lu</td></tr>\n"
"<tr><td>malloc calls</td><td align=right>%lu</td></tr>\n"
"<tr><td>malloc failures</td><td align=right>%lu</td></tr>\n"
"<tr><td>calloc calls</td><td align=right>%lu</td></tr>\n"
"<tr><td>calloc failures</td><td align=right>%lu</td></tr>\n"
"<tr><td>realloc calls</td><td align=right>%lu</td></tr>\n"
"<tr><td>realloc failures</td><td align=right>%lu</td></tr>\n"
"<tr><td>free calls</td><td align=right>%lu</td></tr>\n"
"<tr><td>free(null) calls</td><td align=right>%lu</td></tr>\n"
"</table>",
(unsigned long) event->u.stats.tmstats.calltree_maxstack,
(unsigned long) event->u.stats.tmstats.calltree_maxdepth,
(unsigned long) event->u.stats.tmstats.calltree_parents,
(unsigned long) event->u.stats.tmstats.calltree_maxkids,
(unsigned long) event->u.stats.tmstats.calltree_kidhits,
(unsigned long) event->u.stats.tmstats.calltree_kidmisses,
(unsigned long) event->u.stats.tmstats.calltree_kidsteps,
(unsigned long) event->u.stats.tmstats.callsite_recurrences,
(unsigned long) event->u.stats.tmstats.backtrace_calls,
(unsigned long) event->u.stats.tmstats.backtrace_failures,
(unsigned long) event->u.stats.tmstats.btmalloc_failures,
(unsigned long) event->u.stats.tmstats.dladdr_failures,
(unsigned long) event->u.stats.tmstats.malloc_calls,
(unsigned long) event->u.stats.tmstats.malloc_failures,
(unsigned long) event->u.stats.tmstats.calloc_calls,
(unsigned long) event->u.stats.tmstats.calloc_failures,
(unsigned long) event->u.stats.tmstats.realloc_calls,
(unsigned long) event->u.stats.tmstats.realloc_failures,
(unsigned long) event->u.stats.tmstats.free_calls,
(unsigned long) event->u.stats.tmstats.null_free_calls);
if (event->u.stats.calltree_maxkids_parent) {
tmcallsite *site =
tmreader_callsite(tmr, event->u.stats.calltree_maxkids_parent);
if (site && site->method) {
fprintf(stdout, "<p>callsite with the most kids: %s</p>",
tmgraphnode_name(site->method));
}
}
if (event->u.stats.calltree_maxstack_top) {
tmcallsite *site =
tmreader_callsite(tmr, event->u.stats.calltree_maxstack_top);
fputs("<p>deepest callsite tree path:\n"
"<table border=1>\n"
"<tr><th>Method</th><th>Offset</th></tr>\n",
stdout);
while (site) {
fprintf(stdout,
"<tr><td>%s</td><td>0x%08lX</td></tr>\n",
site->method ? tmgraphnode_name(site->method) : "???",
(unsigned long) site->offset);
site = site->parent;
}
fputs("</table>\n<hr>\n", stdout);
}
break;
}
}
int main(int argc, char **argv)
{
int c, i, j, rv;
tmreader *tmr;
FILE *fp;
program = *argv;
tmr = tmreader_new(program, NULL);
if (!tmr) {
perror(program);
exit(1);
}
while ((c = getopt(argc, argv, "djtuf:m:")) != EOF) {
switch (c) {
case 'd':
sort_by_direct = 1;
break;
case 'j':
js_mode = 1;
break;
case 't':
do_tree_dump = 1;
break;
case 'u':
unified_output = 1;
break;
case 'f':
function_dump = optarg;
break;
case 'm':
min_subtotal = atoi(optarg);
break;
default:
fprintf(stderr,
"usage: %s [-dtu] [-f function-dump-filename] [-m min] [output.html]\n",
program);
exit(2);
}
}
if (!js_mode) {
time_t start = time(NULL);
fprintf(stdout,
"<script language=\"JavaScript\">\n"
"function onload() {\n"
" document.links[0].__proto__.onmouseover = new Function("
"\"window.status ="
" this.href.substring(this.href.lastIndexOf('#') + 1)\");\n"
"}\n"
"</script>\n");
fprintf(stdout, "%s starting at %s", program, ctime(&start));
fflush(stdout);
}
argc -= optind;
argv += optind;
if (argc == 0) {
if (tmreader_eventloop(tmr, "-", my_tmevent_handler) <= 0)
exit(1);
} else {
for (i = j = 0; i < argc; i++) {
fp = fopen(argv[i], "r");
if (!fp) {
fprintf(stderr, "%s: can't open %s: %s\n",
program, argv[i], strerror(errno));
exit(1);
}
rv = tmreader_eventloop(tmr, argv[i], my_tmevent_handler);
if (rv < 0)
exit(1);
if (rv > 0)
j++;
fclose(fp);
}
if (j == 0)
exit(1);
}
compute_callsite_totals(&tmr->calltree_root);
walk_callsite_tree(&tmr->calltree_root, 0, 0, stdout);
if (js_mode) {
fprintf(stdout,
"<script language='javascript'>\n"
"// direct and total byte and allocator-call counts\n"
"var dbytes = %ld, tbytes = %ld,"
" dallocs = %ld, tallocs = %ld;\n",
(long) tmr->calltree_root.allocs.bytes.direct,
(long) tmr->calltree_root.allocs.bytes.total,
(long) tmr->calltree_root.allocs.calls.direct,
(long) tmr->calltree_root.allocs.calls.total);
}
dump_graph(tmr, tmr->libraries, "libraries", "Library", stdout);
if (!js_mode)
fputs("<hr>\n", stdout);
dump_graph(tmr, tmr->components, "classes", "Class or Component", stdout);
if (js_mode || unified_output || function_dump) {
if (js_mode || unified_output || strcmp(function_dump, "-") == 0) {
fp = stdout;
if (!js_mode)
fputs("<hr>\n", fp);
} else {
struct stat sb, fsb;
fstat(fileno(stdout), &sb);
if (stat(function_dump, &fsb) == 0 &&
fsb.st_dev == sb.st_dev && fsb.st_ino == sb.st_ino) {
fp = stdout;
fputs("<hr>\n", fp);
} else {
fp = fopen(function_dump, "w");
if (!fp) {
fprintf(stderr, "%s: can't open %s: %s\n",
program, function_dump, strerror(errno));
exit(1);
}
}
}
dump_graph(tmr, tmr->methods, "methods", "Function or Method", fp);
if (fp != stdout)
fclose(fp);
if (js_mode) {
fputs("function viewnode(graph, index) {\n"
" view.location = viewsrc();\n"
"}\n"
"function viewnodelink(graph, index) {\n"
" var node = graph.nodes[index];\n"
" return '<a href=\"javascript:viewnode('"
" + graph.name.quote() + ', ' + node.sort"
" + ')\" onmouseover=' + node.name.quote() + '>'"
" + node.name + '</a>';\n"
"}\n"
"function search(expr) {\n"
" var re = new RegExp(expr);\n"
" var src = '';\n"
" var graphs = [libraries, classes, methods]\n"
" var nodes;\n"
" for (var n = 0; n < (nodes = graphs[n].nodes).length; n++) {\n"
" for (var i = 0; i < nodes.length; i++) {\n"
" if (re.test(nodes[i].name))\n"
" src += viewnodelink(graph, i) + '\\n';\n"
" }\n"
" }\n"
" view.location = viewsrc();\n"
"}\n"
"function ctrlsrc() {\n"
" return \"<form>\\n"
"search: <input size=40 onchange='search(this.value)'>\\n"
"</form>\\n\";\n"
"}\n"
"function viewsrc() {\n"
" return 'hiiiii'\n"
"}\n"
"</script>\n"
"<frameset rows='10%,*'>\n"
" <frame name='ctrl' src='javascript:top.ctrlsrc()'>\n"
" <frame name='view' src='javascript:top.viewsrc()'>\n"
"</frameset>\n",
stdout);
}
}
exit(0);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,173 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 oqr
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is nsTraceMalloc.c/bloatblame.c code, released
* April 19, 2000.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Brendan Eich, 14-April-2000
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the MPL or the GPL.
*/
#ifndef nsTraceMalloc_h___
#define nsTraceMalloc_h___
#include "prtypes.h"
PR_BEGIN_EXTERN_C
/**
* Magic "number" at start of a trace-malloc log file. Inspired by the PNG
* magic string, which inspired XPCOM's typelib (.xpt) file magic. See the
* NS_TraceMallocStartup comment (below) for magic number differences in log
* file structure.
*/
#define NS_TRACE_MALLOC_MAGIC "XPCOM\nTMLog03\r\n\032"
#define NS_TRACE_MALLOC_MAGIC_SIZE 16
/**
* Trace-malloc stats, traced via the 'Z' event at the end of a log file.
*/
typedef struct nsTMStats {
uint32 calltree_maxstack;
uint32 calltree_maxdepth;
uint32 calltree_parents;
uint32 calltree_maxkids;
uint32 calltree_kidhits;
uint32 calltree_kidmisses;
uint32 calltree_kidsteps;
uint32 callsite_recurrences;
uint32 backtrace_calls;
uint32 backtrace_failures;
uint32 btmalloc_failures;
uint32 dladdr_failures;
uint32 malloc_calls;
uint32 malloc_failures;
uint32 calloc_calls;
uint32 calloc_failures;
uint32 realloc_calls;
uint32 realloc_failures;
uint32 free_calls;
uint32 null_free_calls;
} nsTMStats;
#define NS_TMSTATS_STATIC_INITIALIZER {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
/**
* Call NS_TraceMallocStartup with a valid file descriptor to enable logging
* of compressed malloc traces, including callsite chains. Integers may be
* unsigned serial numbers, sizes, or offsets, and require at most 32 bits.
* They're encoded as follows:
* 0-127 0xxxxxxx (binary, one byte)
* 128-16383 10xxxxxx xxxxxxxx
* 16384-0x1fffff 110xxxxx xxxxxxxx xxxxxxxx
* 0x200000-0xfffffff 1110xxxx xxxxxxxx xxxxxxxx xxxxxxxx
* 0x10000000-0xffffffff 11110000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
* Strings are NUL-terminated ASCII.
*
* Event Operands (magic TMLog01)
* 'L' library serial, shared object filename string
* 'N' method serial, library serial, demangled name string
* 'S' site serial, parent serial, method serial, calling pc offset
* 'M' site serial, malloc size
* 'C' site serial, calloc size
* 'R' site serial, realloc oldsize, realloc size
* 'F' site serial, free size
*
* Event Operands (magic TMLog02)
* 'Z' serialized struct tmstats (20 unsigned integers),
* maxkids parent callsite serial,
* maxstack top callsite serial
*
* Event Operands (magic TMLog03)
* 'T' seconds, microseconds, caption
*
* See xpcom/base/bloatblame.c for an example log-file reader.
*/
#define TM_EVENT_LIBRARY 'L'
#define TM_EVENT_METHOD 'N'
#define TM_EVENT_CALLSITE 'S'
#define TM_EVENT_MALLOC 'M'
#define TM_EVENT_CALLOC 'C'
#define TM_EVENT_REALLOC 'R'
#define TM_EVENT_FREE 'F'
#define TM_EVENT_STATS 'Z'
#define TM_EVENT_TIMESTAMP 'T'
PR_EXTERN(void) NS_TraceMallocStartup(int logfd);
/**
* Initialize malloc tracing, using the ``standard'' startup arguments.
*/
PR_EXTERN(int) NS_TraceMallocStartupArgs(int argc, char* argv[]);
/**
* Stop all malloc tracing, flushing any buffered events to the logfile.
*/
PR_EXTERN(void) NS_TraceMallocShutdown(void);
/**
* Disable malloc tracing.
*/
PR_EXTERN(void) NS_TraceMallocDisable(void);
/**
* Enable malloc tracing.
*/
PR_EXTERN(void) NS_TraceMallocEnable(void);
/**
* Change the log file descriptor, flushing any buffered output to the old
* fd, and writing NS_TRACE_MALLOC_MAGIC to the new file if it is zero length.
* Return the old fd, so the caller can swap open fds. Return -2 on failure,
* which means malloc failure.
*/
PR_EXTERN(int) NS_TraceMallocChangeLogFD(int fd);
/**
* Close the file descriptor fd and forget any bookkeeping associated with it.
* Do nothing if fd is -1.
*/
PR_EXTERN(void) NS_TraceMallocCloseLogFD(int fd);
/**
* Emit a timestamp event with the given caption to the current log file.
*/
PR_EXTERN(void) NS_TraceMallocLogTimestamp(const char *caption);
/**
* Dump a human-readable listing of current allocations and their compressed
* stack backtraces to the file named by pathname. Beware this file may have
* very long lines.
*
* Return -1 on error with errno set by the system, 0 on success.
*/
PR_EXTERN(int)
NS_TraceMallocDumpAllocations(const char *pathname);
PR_END_EXTERN_C
#endif /* nsTraceMalloc_h___ */

View File

@@ -0,0 +1,700 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 oqr
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is tmreader.h/tmreader.c code, released
* July 7, 2000.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Brendan Eich, 7-July-2000
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the MPL or the GPL.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h> /* XXX push error reporting out to clients? */
#include <unistd.h>
#include "prlog.h"
#include "plhash.h"
#include "nsTraceMalloc.h"
#include "tmreader.h"
static int accum_byte(FILE *fp, uint32 *uip)
{
int c = getc(fp);
if (c == EOF)
return 0;
*uip = (*uip << 8) | c;
return 1;
}
static int get_uint32(FILE *fp, uint32 *uip)
{
int c;
uint32 ui;
c = getc(fp);
if (c == EOF)
return 0;
ui = 0;
if (c & 0x80) {
c &= 0x7f;
if (c & 0x40) {
c &= 0x3f;
if (c & 0x20) {
c &= 0x1f;
if (c & 0x10) {
if (!accum_byte(fp, &ui))
return 0;
} else {
ui = (uint32) c;
}
if (!accum_byte(fp, &ui))
return 0;
} else {
ui = (uint32) c;
}
if (!accum_byte(fp, &ui))
return 0;
} else {
ui = (uint32) c;
}
if (!accum_byte(fp, &ui))
return 0;
} else {
ui = (uint32) c;
}
*uip = ui;
return 1;
}
static char *get_string(FILE *fp)
{
char *cp;
int c;
static char buf[256];
static char *bp = buf, *ep = buf + sizeof buf;
static size_t bsize = sizeof buf;
cp = bp;
do {
c = getc(fp);
if (c == EOF)
return 0;
if (cp == ep) {
if (bp == buf) {
bp = malloc(2 * bsize);
if (bp)
memcpy(bp, buf, bsize);
} else {
bp = realloc(bp, 2 * bsize);
}
if (!bp)
return 0;
cp = bp + bsize;
bsize *= 2;
ep = bp + bsize;
}
*cp++ = c;
} while (c != '\0');
return strdup(bp);
}
static int get_tmevent(FILE *fp, tmevent *event)
{
int c;
char *s;
c = getc(fp);
if (c == EOF)
return 0;
event->type = (char) c;
if (!get_uint32(fp, &event->serial))
return 0;
switch (c) {
case TM_EVENT_LIBRARY:
s = get_string(fp);
if (!s)
return 0;
event->u.libname = s;
break;
case TM_EVENT_METHOD:
if (!get_uint32(fp, &event->u.method.library))
return 0;
s = get_string(fp);
if (!s)
return 0;
event->u.method.name = s;
break;
case TM_EVENT_CALLSITE:
if (!get_uint32(fp, &event->u.site.parent))
return 0;
if (!get_uint32(fp, &event->u.site.method))
return 0;
if (!get_uint32(fp, &event->u.site.offset))
return 0;
break;
case TM_EVENT_MALLOC:
case TM_EVENT_CALLOC:
case TM_EVENT_FREE:
event->u.alloc.oldsize = 0;
if (!get_uint32(fp, &event->u.alloc.size))
return 0;
break;
case TM_EVENT_REALLOC:
if (!get_uint32(fp, &event->u.alloc.oldsize))
return 0;
if (!get_uint32(fp, &event->u.alloc.size))
return 0;
break;
case TM_EVENT_STATS:
if (!get_uint32(fp, &event->u.stats.tmstats.calltree_maxstack))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.calltree_maxdepth))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.calltree_parents))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.calltree_maxkids))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.calltree_kidhits))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.calltree_kidmisses))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.calltree_kidsteps))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.callsite_recurrences))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.backtrace_calls))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.backtrace_failures))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.btmalloc_failures))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.dladdr_failures))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.malloc_calls))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.malloc_failures))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.calloc_calls))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.calloc_failures))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.realloc_calls))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.realloc_failures))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.free_calls))
return 0;
if (!get_uint32(fp, &event->u.stats.tmstats.null_free_calls))
return 0;
if (!get_uint32(fp, &event->u.stats.calltree_maxkids_parent))
return 0;
if (!get_uint32(fp, &event->u.stats.calltree_maxstack_top))
return 0;
break;
}
return 1;
}
static void *generic_alloctable(void *pool, PRSize size)
{
return malloc(size);
}
static void generic_freetable(void *pool, void *item)
{
free(item);
}
static PLHashEntry *callsite_allocentry(void *pool, const void *key)
{
return malloc(sizeof(tmcallsite));
}
static PLHashEntry *graphnode_allocentry(void *pool, const void *key)
{
tmgraphnode *node = (tmgraphnode*) malloc(sizeof(tmgraphnode));
if (!node)
return NULL;
node->in = node->out = NULL;
node->up = node->down = node->next = NULL;
node->low = 0;
node->allocs.bytes.direct = node->allocs.bytes.total = 0;
node->allocs.calls.direct = node->allocs.calls.total = 0;
node->frees.bytes.direct = node->frees.bytes.total = 0;
node->frees.calls.direct = node->frees.calls.total = 0;
node->sqsum = 0;
node->sort = -1;
return &node->entry;
}
static void graphnode_freeentry(void *pool, PLHashEntry *he, PRUintn flag)
{
/* Always free the value, which points to a strdup'd string. */
free(he->value);
/* Free the whole thing if we're told to. */
if (flag == HT_FREE_ENTRY)
free((void*) he);
}
static void component_freeentry(void *pool, PLHashEntry *he, PRUintn flag)
{
if (flag == HT_FREE_ENTRY) {
tmgraphnode *comp = (tmgraphnode*) he;
/* Free the key, which was strdup'd (N.B. value also points to it). */
free((void*) tmcomponent_name(comp));
free((void*) comp);
}
}
static PLHashAllocOps callsite_hashallocops = {
generic_alloctable, generic_freetable,
callsite_allocentry, graphnode_freeentry
};
static PLHashAllocOps graphnode_hashallocops = {
generic_alloctable, generic_freetable,
graphnode_allocentry, graphnode_freeentry
};
static PLHashAllocOps component_hashallocops = {
generic_alloctable, generic_freetable,
graphnode_allocentry, component_freeentry
};
static PLHashNumber hash_serial(const void *key)
{
return (PLHashNumber) key;
}
tmreader *tmreader_new(const char *program, void *data)
{
tmreader *tmr;
tmr = calloc(1, sizeof *tmr);
if (!tmr)
return NULL;
tmr->program = program;
tmr->data = data;
tmr->libraries = PL_NewHashTable(100, hash_serial, PL_CompareValues,
PL_CompareStrings, &graphnode_hashallocops,
NULL);
tmr->components = PL_NewHashTable(10000, PL_HashString, PL_CompareStrings,
PL_CompareValues, &component_hashallocops,
NULL);
tmr->methods = PL_NewHashTable(10000, hash_serial, PL_CompareValues,
PL_CompareStrings, &graphnode_hashallocops,
NULL);
tmr->callsites = PL_NewHashTable(200000, hash_serial, PL_CompareValues,
PL_CompareValues, &callsite_hashallocops,
NULL);
tmr->calltree_root.entry.value = (void*) strdup("root");
if (!tmr->libraries || !tmr->components || !tmr->methods ||
!tmr->callsites || !tmr->calltree_root.entry.value) {
tmreader_destroy(tmr);
return NULL;
}
return tmr;
}
void tmreader_destroy(tmreader *tmr)
{
if (tmr->libraries)
PL_HashTableDestroy(tmr->libraries);
if (tmr->components)
PL_HashTableDestroy(tmr->components);
if (tmr->methods)
PL_HashTableDestroy(tmr->methods);
if (tmr->callsites)
PL_HashTableDestroy(tmr->callsites);
free(tmr);
}
int tmreader_eventloop(tmreader *tmr, const char *filename,
tmeventhandler eventhandler)
{
FILE *fp;
char buf[NS_TRACE_MALLOC_MAGIC_SIZE];
tmevent event;
static const char magic[] = NS_TRACE_MALLOC_MAGIC;
if (strcmp(filename, "-") == 0) {
fp = stdin;
} else {
fp = fopen(filename, "r");
if (!fp) {
fprintf(stderr, "%s: can't open %s: %s.\n",
tmr->program, filename, strerror(errno));
return 0;
}
}
if (read(fileno(fp), buf, sizeof buf) != sizeof buf ||
strncmp(buf, magic, sizeof buf) != 0) {
fprintf(stderr, "%s: bad magic string %s at start of %s.\n",
tmr->program, buf, filename);
return 0;
}
while (get_tmevent(fp, &event)) {
switch (event.type) {
case TM_EVENT_LIBRARY: {
const void *key;
PLHashNumber hash;
PLHashEntry **hep, *he;
key = (const void*) event.serial;
hash = hash_serial(key);
hep = PL_HashTableRawLookup(tmr->libraries, hash, key);
he = *hep;
PR_ASSERT(!he);
if (he) exit(2);
he = PL_HashTableRawAdd(tmr->libraries, hep, hash, key,
event.u.libname);
if (!he) {
perror(tmr->program);
return -1;
}
break;
}
case TM_EVENT_METHOD: {
const void *key;
PLHashNumber hash;
PLHashEntry **hep, *he;
char *name, *head, *mark, save;
tmgraphnode *meth, *comp, *lib;
key = (const void*) event.serial;
hash = hash_serial(key);
hep = PL_HashTableRawLookup(tmr->methods, hash, key);
he = *hep;
PR_ASSERT(!he);
if (he) exit(2);
name = event.u.method.name;
he = PL_HashTableRawAdd(tmr->methods, hep, hash, key, name);
if (!he) {
perror(tmr->program);
return -1;
}
meth = (tmgraphnode*) he;
head = name;
mark = strchr(name, ':');
if (!mark) {
mark = name;
while (*mark != '\0' && *mark == '_')
mark++;
head = mark;
mark = strchr(head, '_');
if (!mark) {
mark = strchr(head, '+');
if (!mark)
mark = head + strlen(head);
}
}
save = *mark;
*mark = '\0';
hash = PL_HashString(head);
hep = PL_HashTableRawLookup(tmr->components, hash, head);
he = *hep;
if (he) {
comp = (tmgraphnode*) he;
} else {
head = strdup(head);
if (head) {
he = PL_HashTableRawAdd(tmr->components, hep, hash, head,
head);
}
if (!he) {
perror(tmr->program);
return -1;
}
comp = (tmgraphnode*) he;
key = (const void*) event.u.method.library;
hash = hash_serial(key);
lib = (tmgraphnode*)
*PL_HashTableRawLookup(tmr->libraries, hash, key);
if (lib) {
comp->up = lib;
comp->next = lib->down;
lib->down = comp;
}
}
*mark = save;
meth->up = comp;
meth->next = comp->down;
comp->down = meth;
break;
}
case TM_EVENT_CALLSITE: {
const void *key, *mkey;
PLHashNumber hash, mhash;
PLHashEntry **hep, *he;
tmcallsite *site, *parent;
tmgraphnode *meth;
key = (const void*) event.serial;
hash = hash_serial(key);
hep = PL_HashTableRawLookup(tmr->callsites, hash, key);
he = *hep;
PR_ASSERT(!he);
if (he) exit(2);
if (event.u.site.parent == 0) {
parent = &tmr->calltree_root;
} else {
parent = tmreader_callsite(tmr, event.u.site.parent);
if (!parent) {
fprintf(stderr, "%s: no parent for %lu (%lu)!\n",
tmr->program, (unsigned long) event.serial,
(unsigned long) event.u.site.parent);
continue;
}
}
he = PL_HashTableRawAdd(tmr->callsites, hep, hash, key, NULL);
if (!he) {
perror(tmr->program);
return -1;
}
site = (tmcallsite*) he;
site->parent = parent;
site->siblings = parent->kids;
parent->kids = site;
site->kids = NULL;
mkey = (const void*) event.u.site.method;
mhash = hash_serial(mkey);
meth = (tmgraphnode*)
*PL_HashTableRawLookup(tmr->methods, mhash, mkey);
site->method = meth;
site->offset = event.u.site.offset;
site->allocs.bytes.direct = site->allocs.bytes.total = 0;
site->allocs.calls.direct = site->allocs.calls.total = 0;
site->frees.bytes.direct = site->frees.bytes.total = 0;
site->frees.calls.direct = site->frees.calls.total = 0;
break;
}
case TM_EVENT_MALLOC:
case TM_EVENT_CALLOC:
case TM_EVENT_REALLOC: {
tmcallsite *site;
uint32 size, oldsize;
double delta, sqdelta, sqszdelta;
tmgraphnode *meth, *comp, *lib;
site = tmreader_callsite(tmr, event.serial);
if (!site) {
fprintf(stderr, "%s: no callsite for '%c' (%lu)!\n",
tmr->program, event.type, (unsigned long) event.serial);
continue;
}
size = event.u.alloc.size;
oldsize = event.u.alloc.oldsize;
delta = (double)size - (double)oldsize;
site->allocs.bytes.direct += delta;
if (event.type != TM_EVENT_REALLOC)
site->allocs.calls.direct++;
meth = site->method;
if (meth) {
meth->allocs.bytes.direct += delta;
sqdelta = delta * delta;
if (event.type == TM_EVENT_REALLOC) {
sqszdelta = ((double)size * size)
- ((double)oldsize * oldsize);
meth->sqsum += sqszdelta;
} else {
meth->sqsum += sqdelta;
meth->allocs.calls.direct++;
}
comp = meth->up;
if (comp) {
comp->allocs.bytes.direct += delta;
if (event.type == TM_EVENT_REALLOC) {
comp->sqsum += sqszdelta;
} else {
comp->sqsum += sqdelta;
comp->allocs.calls.direct++;
}
lib = comp->up;
if (lib) {
lib->allocs.bytes.direct += delta;
if (event.type == TM_EVENT_REALLOC) {
lib->sqsum += sqszdelta;
} else {
lib->sqsum += sqdelta;
lib->allocs.calls.direct++;
}
}
}
}
break;
}
case TM_EVENT_FREE: {
tmcallsite *site;
uint32 size;
tmgraphnode *meth, *comp, *lib;
site = tmreader_callsite(tmr, event.serial);
if (!site) {
fprintf(stderr, "%s: no callsite for '%c' (%lu)!\n",
tmr->program, event.type, (unsigned long) event.serial);
continue;
}
size = event.u.alloc.size;
site->frees.bytes.direct += size;
site->frees.calls.direct++;
meth = site->method;
if (meth) {
meth->frees.bytes.direct += size;
meth->frees.calls.direct++;
comp = meth->up;
if (comp) {
comp->frees.bytes.direct += size;
comp->frees.calls.direct++;
lib = comp->up;
if (lib) {
lib->frees.bytes.direct += size;
lib->frees.calls.direct++;
}
}
}
break;
}
case TM_EVENT_STATS:
break;
}
eventhandler(tmr, &event);
}
return 1;
}
tmgraphnode *tmreader_library(tmreader *tmr, uint32 serial)
{
const void *key;
PLHashNumber hash;
key = (const void*) serial;
hash = hash_serial(key);
return (tmgraphnode*) *PL_HashTableRawLookup(tmr->libraries, hash, key);
}
tmgraphnode *tmreader_component(tmreader *tmr, const char *name)
{
PLHashNumber hash;
hash = PL_HashString(name);
return (tmgraphnode*) *PL_HashTableRawLookup(tmr->components, hash, name);
}
tmgraphnode *tmreader_method(tmreader *tmr, uint32 serial)
{
const void *key;
PLHashNumber hash;
key = (const void*) serial;
hash = hash_serial(key);
return (tmgraphnode*) *PL_HashTableRawLookup(tmr->methods, hash, key);
}
tmcallsite *tmreader_callsite(tmreader *tmr, uint32 serial)
{
const void *key;
PLHashNumber hash;
key = (const void*) serial;
hash = hash_serial(key);
return (tmcallsite*) *PL_HashTableRawLookup(tmr->callsites, hash, key);
}
int tmgraphnode_connect(tmgraphnode *from, tmgraphnode *to, tmcallsite *site)
{
tmgraphlink *outlink;
tmgraphedge *edge;
for (outlink = from->out; outlink; outlink = outlink->next) {
if (outlink->node == to) {
/*
* Say the stack looks like this: ... => JS => js => JS => js.
* We must avoid overcounting JS=>js because the first edge total
* includes the second JS=>js edge's total (which is because the
* lower site's total includes all its kids' totals).
*/
edge = TM_LINK_TO_EDGE(outlink, TM_EDGE_OUT_LINK);
if (!to->low || to->low < from->low) {
/* Add the direct and total counts to edge->allocs. */
edge->allocs.bytes.direct += site->allocs.bytes.direct;
edge->allocs.bytes.total += site->allocs.bytes.total;
edge->allocs.calls.direct += site->allocs.calls.direct;
edge->allocs.calls.total += site->allocs.calls.total;
/* Now update the free counts. */
edge->frees.bytes.direct += site->frees.bytes.direct;
edge->frees.bytes.total += site->frees.bytes.total;
edge->frees.calls.direct += site->frees.calls.direct;
edge->frees.calls.total += site->frees.calls.total;
}
return 1;
}
}
edge = (tmgraphedge*) malloc(sizeof(tmgraphedge));
if (!edge)
return 0;
edge->links[TM_EDGE_OUT_LINK].node = to;
edge->links[TM_EDGE_OUT_LINK].next = from->out;
from->out = &edge->links[TM_EDGE_OUT_LINK];
edge->links[TM_EDGE_IN_LINK].node = from;
edge->links[TM_EDGE_IN_LINK].next = to->in;
to->in = &edge->links[TM_EDGE_IN_LINK];
edge->allocs = site->allocs;
edge->frees = site->frees;
return 1;
}

View File

@@ -0,0 +1,192 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 oqr
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is tmreader.h/tmreader.c code, released
* July 7, 2000.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Brendan Eich, 7-July-2000
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the MPL or the GPL.
*/
#ifndef tmreader_h___
#define tmreader_h___
#include "prtypes.h"
#include "plhash.h"
#include "nsTraceMalloc.h"
PR_BEGIN_EXTERN_C
typedef struct tmreader tmreader;
typedef struct tmevent tmevent;
typedef struct tmcounts tmcounts;
typedef struct tmallcounts tmallcounts;
typedef struct tmgraphlink tmgraphlink;
typedef struct tmgraphedge tmgraphedge;
typedef struct tmgraphnode tmgraphnode;
typedef struct tmcallsite tmcallsite;
struct tmevent {
char type;
uint32 serial;
union {
char *libname;
struct {
uint32 library;
char *name;
} method;
struct {
uint32 parent;
uint32 method;
uint32 offset;
} site;
struct {
uint32 oldsize;
uint32 size;
} alloc;
struct {
nsTMStats tmstats;
uint32 calltree_maxkids_parent;
uint32 calltree_maxstack_top;
} stats;
} u;
};
struct tmcounts {
uint32 direct; /* things allocated by this node's code */
uint32 total; /* direct + things from all descendents */
};
struct tmallcounts {
tmcounts bytes;
tmcounts calls;
};
struct tmgraphnode {
PLHashEntry entry; /* key is serial or name, value must be name */
tmgraphlink *in;
tmgraphlink *out;
tmgraphnode *up; /* parent in supergraph, e.g., JS for JS_*() */
tmgraphnode *down; /* subgraph kids, declining bytes.total order */
tmgraphnode *next; /* next kid in supergraph node's down list */
int low; /* 0 or lowest current tree walk level */
tmallcounts allocs;
tmallcounts frees;
double sqsum; /* sum of squared bytes.direct */
int sort; /* sorted index in node table, -1 if no table */
};
#define tmgraphnode_name(node) ((char*) (node)->entry.value)
#define tmlibrary_serial(lib) ((uint32) (lib)->entry.key)
#define tmcomponent_name(comp) ((const char*) (comp)->entry.key)
/* Half a graphedge, not including per-edge allocation stats. */
struct tmgraphlink {
tmgraphlink *next; /* next fanning out from or into a node */
tmgraphnode *node; /* the other node (to if OUT, from if IN) */
};
/*
* It's safe to downcast a "from" tmgraphlink (one linked from a node's out
* pointer) to tmgraphedge. To go from an "out" (linked via tmgraphedge.from)
* or "in" (linked via tmgraphedge.to) list link to its containing edge, use
* TM_LINK_TO_EDGE(link, which).
*/
struct tmgraphedge {
tmgraphlink links[2];
tmallcounts allocs;
tmallcounts frees;
};
/* Indices into tmgraphedge.links -- out must come first. */
#define TM_EDGE_OUT_LINK 0
#define TM_EDGE_IN_LINK 1
#define TM_LINK_TO_EDGE(link,which) ((tmgraphedge*) &(link)[-(which)])
struct tmcallsite {
PLHashEntry entry; /* key is site serial number */
tmcallsite *parent; /* calling site */
tmcallsite *siblings; /* other sites reached from parent */
tmcallsite *kids; /* sites reached from here */
tmgraphnode *method; /* method node in tmr->methods graph */
uint32 offset; /* pc offset from start of method */
tmallcounts allocs;
tmallcounts frees;
};
struct tmreader {
const char *program;
void *data;
PLHashTable *libraries;
PLHashTable *components;
PLHashTable *methods;
PLHashTable *callsites;
tmcallsite calltree_root;
};
typedef void (*tmeventhandler)(tmreader *tmr, tmevent *event);
/* The tmreader constructor and destructor. */
extern tmreader *tmreader_new(const char *program, void *data);
extern void tmreader_destroy(tmreader *tmr);
/*
* Return -1 on permanent fatal error, 0 if filename can't be opened or is not
* a trace-malloc logfile, and 1 on success.
*/
extern int tmreader_eventloop(tmreader *tmr, const char *filename,
tmeventhandler eventhandler);
/* Map serial number or name to graphnode or callsite. */
extern tmgraphnode *tmreader_library(tmreader *tmr, uint32 serial);
extern tmgraphnode *tmreader_component(tmreader *tmr, const char *name);
extern tmgraphnode *tmreader_method(tmreader *tmr, uint32 serial);
extern tmcallsite *tmreader_callsite(tmreader *tmr, uint32 serial);
/*
* Connect node 'from' to node 'to' with an edge, if there isn't one already
* connecting the nodes. Add site's allocation stats to the edge only if we
* create the edge, or if we find that it exists, but that to->low is zero or
* less than from->low.
*
* If the callsite tree already totals allocation costs (tmcounts.total for
* each site includes tmcounts.direct for that site, plus tmcounts.total for
* all kid sites), then the node->low watermarks should be set from the tree
* level when walking the callsite tree, and should be set to non-zero values
* only if zero (the root is at level 0). A low watermark should be cleared
* when the tree walk unwinds past the level at which it was set non-zero.
*
* Return 0 on error (malloc failure) and 1 on success.
*/
extern int tmgraphnode_connect(tmgraphnode *from, tmgraphnode *to,
tmcallsite *site);
PR_END_EXTERN_C
#endif /* tmreader_h___ */

40
mozilla/xpcom/Makefile.in Normal file
View File

@@ -0,0 +1,40 @@
#
# 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 = typelib base ds io components threads reflect proxy build tools sample
ifdef ENABLE_TESTS
DIRS += \
typelib/xpt/tests \
reflect/xptinfo/tests \
reflect/xptcall/tests \
proxy/tests
endif
include $(topsrcdir)/config/rules.mk

View 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 the Mozilla browser.
#
# The Initial Developer of the Original Code is Netscape
# Communications, Inc. Portions created by Netscape are
# Copyright (C) 1999, Mozilla. All Rights Reserved.
#
# Contributor(s):
# Travis Bogard <travis@netscape.com>
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = eventloop nativeApp
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,36 @@
#
# 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 = xp
ifneq (,$(filter gtk photon,$(MOZ_WIDGET_TOOLKIT)))
DIRS += $(MOZ_WIDGET_TOOLKIT)
endif
include $(topsrcdir)/config/rules.mk

View File

@@ -1,3 +1,4 @@
#!nmake
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
@@ -9,19 +10,18 @@
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
# 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) 2001 Netscape Communications Corporation. All
# Rights Reserved.
# Communications, Inc. Portions created by Netscape are
# Copyright (C) 1999, Mozilla. All Rights Reserved.
#
# Contributor(s):
# Srilatha Moturi <srilatha@netscape.com>
#
# Contributor(s):
# Travis Bogard <travis@netscape.com>
DEPTH=..\..\..
DIRS=content locale
DIRS=xp windows
include <$(DEPTH)\config\rules.mak>
include <$(DEPTH)\config\config.mak>

View 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):
# Jerry Kirk <Jerry.Kirk@NexwareCorp.com>
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = xpcom_eventloop_photon
LIBRARY_NAME = eventloop
IS_COMPONENT = 1
CPPSRCS = \
nsCPhEvent.cpp \
nsCEvent.cpp \
nsCEventFilter.cpp \
nsCPlatformBaseLoop.cpp \
nsCAppLoop.cpp \
$(NULL)
LOCAL_INCLUDES = -I. -I../xp
SHARED_LIBRARY_LIBS = ../xp/libxp_eventloop.a
EXTRA_DSO_LDOPTS = \
$(TOOLKIT_DSO_LDOPTS) \
$(TK_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk
CXXFLAGS += $(TK_CFLAGS)

View File

@@ -0,0 +1,73 @@
/* -*- Mode: IDL; tab-width: 4; 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, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Travis Bogard <travis@netscape.com>
*/
#include "nsCAppLoop.h"
#include "nsCPhFilter.h"
#include "nsPhEventLog.h"
//*****************************************************************************
//*** nsCAppLoop: Object Management
//*****************************************************************************
nsCAppLoop::nsCAppLoop() : nsCBaseAppLoop()
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCAppLoop::nsCAppLoop m_PhThreadId=<%d>\n", m_PhThreadId));
}
nsCAppLoop::~nsCAppLoop()
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCAppLoop::~nsCAppLoop m_PhThreadId=<%d>\n", m_PhThreadId));
}
NS_METHOD nsCAppLoop::Create(nsISupports* aOuter, const nsIID& aIID,
void** ppv)
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCAppLoop::Create\n"));
NS_ENSURE_ARG_POINTER(ppv);
NS_ENSURE_NO_AGGREGATION(aOuter);
nsCAppLoop* app = new nsCAppLoop();
NS_ENSURE_TRUE(app, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(app);
nsresult rv = app->QueryInterface(aIID, ppv);
NS_RELEASE(app);
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCAppLoop::Create the end rv=<%d>\n", rv));
return rv;
}
//*****************************************************************************
// nsCAppLoop:: Internal Platform Implementations of nsIEventLoop
// (Error checking is ensured above)
//*****************************************************************************
nsresult nsCAppLoop::PlatformExit(PRInt32 exitCode)
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCAppLoop::PlatformExit exitCode=<%d>\n", exitCode));
PostQuitMessage(exitCode);
return NS_OK;
}

View File

@@ -0,0 +1,43 @@
/* -*- Mode: IDL; tab-width: 4; 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, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Travis Bogard <travis@netscape.com>
*/
#ifndef nsCAppLoop_h__
#define nsCAppLoop_h__
#include "nsCBaseAppLoop.h"
class nsCAppLoop : public nsCBaseAppLoop
{
public:
static NS_METHOD Create(nsISupports* aOuter, const nsIID& aIID, void** ppv);
protected:
nsCAppLoop();
virtual ~nsCAppLoop();
// Internal Platform Implementations of nsIEventLoop
// (Error checking is ensured above)
nsresult PlatformExit(PRInt32 exitCode);
};
#endif /* nsCAppLoop_h__ */

View File

@@ -0,0 +1,44 @@
/* -*- Mode: IDL; tab-width: 4; 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, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Travis Bogard <travis@netscape.com>
*/
#ifndef nsCBreathLoop_h__
#define nsCBreathLoop_h__
#include "nsCBaseBreathLoop.h"
class nsCBreathLoop : public nsCBaseBreathLoop
{
public:
static NS_METHOD Create(nsISupports* aOuter, const nsIID& aIID, void** ppv);
protected:
nsCBreathLoop();
virtual ~nsCBreathLoop();
// Internal Platform Implementations of nsIEventLoop
// (Error checking is ensured above)
nsresult PlatformExit(PRInt32 exitCode);
PRInt32 PlatformGetReturnCode(void* platformEventData);
};
#endif /* nsCBreathLoop_h__ */

View File

@@ -0,0 +1,103 @@
/* -*- Mode: IDL; tab-width: 4; 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, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Travis Bogard <travis@netscape.com>
* Jerry Kirk <Jerry.Kirk@NexwareCorp.com>
*/
#include "nsCRT.h"
#include "nsCEvent.h"
#include <prlog.h>
PRLogModuleInfo *PhEventLog = PR_NewLogModule("PhEventLog");
#include "nsPhEventLog.h"
//*****************************************************************************
//*** nsCEvent: Object Management
//*****************************************************************************
nsCEvent::nsCEvent(void* platformEventData)
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCEvent::nsCEvent platformEventData=<%p>\n", platformEventData));
NS_INIT_REFCNT();
m_msg = new nsCPhEvent( (PhEvent_t *) platformEventData);
}
nsCEvent::~nsCEvent()
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCEvent::~nsCEvent\n"));
if (m_msg)
{
delete m_msg;
}
}
//*****************************************************************************
// nsCEvent::nsISupports
//*****************************************************************************
NS_IMPL_ISUPPORTS1(nsCEvent, nsIEvent)
//*****************************************************************************
// nsCEvent::nsIEvent
//*****************************************************************************
NS_IMETHODIMP nsCEvent::GetNativeData(nsNativeEventDataType dataType,
void** data)
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCEvent::GetNativeData dataType=<%d> data=<%p>\n", dataType, data));
NS_ENSURE_ARG(nsNativeEventDataTypes::PhotonMsgStruct == dataType);
NS_ENSURE_ARG_POINTER(data);
*data = m_msg;
return NS_OK;
}
NS_IMETHODIMP nsCEvent::SetNativeData(nsNativeEventDataType dataType,
void* data)
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCEvent::SetNativeData dataType=<%d>\n", dataType));
NS_ENSURE_ARG(nsNativeEventDataTypes::PhotonMsgStruct == dataType);
if(!data)
{
/* Get rid of the Event */
if (m_msg)
delete m_msg;
m_msg = new nsCPhEvent(NULL);
}
else
{
/* Get rid of the Event */
if (m_msg)
delete m_msg;
nsCPhEvent *aEvent = (nsCPhEvent *) data;
m_msg = new nsCPhEvent(aEvent->m_msg);
}
return NS_OK;
}

View File

@@ -0,0 +1,46 @@
/* -*- Mode: IDL; tab-width: 4; 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, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Travis Bogard <travis@netscape.com>
* Jerry Kirk <Jerry.Kirk@NexwareCorp.com>
*/
#ifndef nsCEvent_h__
#define nsCEvent_h__
#include "nsCPhEvent.h"
#include "nsIEvent.h"
class nsCEvent : public nsIEvent
{
public:
nsCEvent(void* platformEventData=nsnull);
NS_DECL_ISUPPORTS
NS_DECL_NSIEVENT
protected:
virtual ~nsCEvent();
protected:
nsCPhEvent *m_msg;
};
#endif /* nsCEvent_h__ */

View File

@@ -0,0 +1,78 @@
/* -*- Mode: IDL; tab-width: 4; 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, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Travis Bogard <travis@netscape.com>
* Jerry Kirk <Jerry.Kirk@NexwareCorp.com>
*/
#include "nsCRT.h"
#include "nsCEventFilter.h"
//*****************************************************************************
//*** nsCEventFilter: Object Management
//*****************************************************************************
nsCEventFilter::nsCEventFilter(void* platformFilterData)
{
NS_INIT_REFCNT();
if(platformFilterData)
nsCRT::memcpy(&m_filter, platformFilterData, sizeof(m_filter));
else
nsCRT::memset(&m_filter, 0, sizeof(m_filter));
}
nsCEventFilter::~nsCEventFilter()
{
}
//*****************************************************************************
// nsCEventFilter::nsISupports
//*****************************************************************************
NS_IMPL_ISUPPORTS1(nsCEventFilter, nsIEventFilter)
//*****************************************************************************
// nsCEventFilter::nsIEventFilter
//*****************************************************************************
NS_IMETHODIMP nsCEventFilter::GetNativeData(nsNativeFilterDataType dataType,
void** data)
{
NS_ENSURE_ARG(nsNativeFilterDataTypes::PhotonFilter == dataType);
NS_ENSURE_ARG_POINTER(data);
*data = &m_filter;
return NS_OK;
}
NS_IMETHODIMP nsCEventFilter::SetNativeData(nsNativeFilterDataType dataType,
void* data)
{
NS_ENSURE_ARG(nsNativeFilterDataTypes::PhotonFilter == dataType);
if(!data)
nsCRT::memset(&m_filter, 0, sizeof(m_filter));
else
nsCRT::memcpy(&m_filter, data, sizeof(m_filter));
return NS_OK;
}

View File

@@ -0,0 +1,46 @@
/* -*- Mode: IDL; tab-width: 4; 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, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Travis Bogard <travis@netscape.com>
* Jerry Kirk <Jerry.Kirk@NexwareCorp.com>
*/
#ifndef nsCEventFilter_h__
#define nsCEventFilter_h__
#include "nsIEventFilter.h"
#include "nsCPhFilter.h"
class nsCEventFilter : public nsIEventFilter
{
public:
nsCEventFilter(void* platformFilterData=nsnull);
NS_DECL_ISUPPORTS
NS_DECL_NSIEVENTFILTER
protected:
virtual ~nsCEventFilter();
protected:
nsCPhFilter m_filter;
};
#endif /* nsCEventFilter_h__ */

View File

@@ -0,0 +1,89 @@
/* -*- Mode: IDL; tab-width: 4; 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, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Jerry Kirk <Jerry.Kirk@NexwareCorp.com>
*/
#include "nsCRT.h"
#include "nsCPhEvent.h"
#include "nsPhEventLog.h"
//*****************************************************************************
//*** nsCPhEvent: Object Management
//*****************************************************************************
nsCPhEvent::nsCPhEvent(PhEvent_t* platformEventData)
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCPhEvent::nsCPhEvent platformEventData=<%p>\n", platformEventData));
if (platformEventData)
{
mEventBufferSz = PhGetMsgSize ( platformEventData );
m_msg = (PhEvent_t *) malloc( mEventBufferSz );
if (m_msg);
nsCRT::memcpy(m_msg, platformEventData, mEventBufferSz);
}
else
{
mEventBufferSz = sizeof(PhEvent_t);
m_msg = (PhEvent_t *) malloc( mEventBufferSz );
if (m_msg);
nsCRT::memset(m_msg, 0, mEventBufferSz);
}
}
nsCPhEvent::~nsCPhEvent()
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCPhEvent::~nsCPhEvent\n"));
if (m_msg)
{
free(m_msg);
m_msg = nsnull;
mEventBufferSz = 0;
}
}
unsigned long nsCPhEvent::GetEventBufferSize()
{
return mEventBufferSz;
}
unsigned long nsCPhEvent::GetEventSize()
{
unsigned long theEventSize = 0;
if (m_msg)
theEventSize = PhGetMsgSize ( (PhEvent_t *) m_msg );
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCPhEvent::GetEventSize theEventSize=<%d>\n", theEventSize));
return theEventSize;
}
nsresult nsCPhEvent::ResizeEvent(unsigned long aEventSize)
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCPhEvent::ResizeEvent old_size=<%d> new_size=<%d>\n", mEventBufferSz, aEventSize));
mEventBufferSz = aEventSize;
m_msg = (PhEvent_t *) realloc( m_msg, mEventBufferSz );
NS_ENSURE_ARG_POINTER(m_msg);
return NS_OK;
}

View File

@@ -0,0 +1,43 @@
/* -*- Mode: IDL; tab-width: 4; 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, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Jerry Kirk <Jerry.Kirk@NexwareCorp.com>
*/
#ifndef nsCPhEvent_h__
#define nsCPhEvent_h__
#include "PhT.h"
class nsCPhEvent
{
public:
nsCPhEvent(PhEvent_t *platformEventData=nsnull);
virtual ~nsCPhEvent();
unsigned long GetEventBufferSize();
unsigned long GetEventSize();
nsresult ResizeEvent(unsigned long aEventSize);
public:
PhEvent_t *m_msg;
unsigned long mEventBufferSz;
};
#endif /* nsCPhEvent_h__ */

View File

@@ -0,0 +1,38 @@
/* -*- Mode: IDL; tab-width: 4; 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, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Travis Bogard <travis@netscape.com>
* Jerry Kirk <Jerry.Kirk@NexwareCorp.com>
*/
#ifndef nsCPhFilter_h__
#define nsCPhFilter_h__
//#include "PhT.h"
class nsCPhFilter
{
public:
// HWND hWnd;
// UINT wMsgFilterMin;
// UINT wMsgFilterMax;
// UINT wRemoveFlags; // fRemoveEvent flag passed to PeekEvent takes precedent
}; // over PM_NOREMOVE and PM_REMOVE.
#endif /* nsPhFilter_h__ */

View File

@@ -0,0 +1,188 @@
/* -*- Mode: IDL; tab-width: 4; 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, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Travis Bogard <travis@netscape.com>
* Jerry Kirk <Jerry.Kirk@NexwareCorp.com>
*/
#include "nsCPlatformBaseLoop.h"
#include "nsCPhEvent.h"
#include "nsCPhFilter.h"
#include "nsPhEventLog.h"
#include <Pt.h>
//*****************************************************************************
//*** nsCPlatformBaseLoop: Object Management
//*****************************************************************************
nsCPlatformBaseLoop::nsCPlatformBaseLoop(nsEventLoopType type) :
nsCBaseLoop(type)
{
m_PhThreadId = pthread_self();
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCPlatformBaseLoop::nsCPlatformBaseLoop nsEventLoopType=<%d> m_PhThreadId=<%d>\n", type, m_PhThreadId));
}
nsCPlatformBaseLoop::~nsCPlatformBaseLoop()
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCPlatformBaseLoop::~nsCPlatformBaseLoop m_PhThreadId=<%d>\n", m_PhThreadId));
}
//*****************************************************************************
// nsCPlatformBaseLoop:: Internal Platform Implementations of nsIEventLoop
// (Error checking is ensured above)
//*****************************************************************************
nsresult nsCPlatformBaseLoop::PlatformGetNextEvent(void* platformFilterData,
void* platformEventData)
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCPlatformBaseLoop::PlatformGetNextEvent platformFilterData=<%p> platformEventData=<%p>\n", platformFilterData, platformEventData));
nsCPhFilter* filter=(nsCPhFilter*)platformFilterData;
nsCPhEvent* pEvent = (nsCPhEvent*) platformEventData;
PRBool done = PR_FALSE;
if(filter != NULL)
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCPlatformBaseLoop::PlatformGetNextEvent Filters not supported\n"));
return NS_COMFALSE;
}
while(!done)
{
switch( PhEventNext(pEvent->m_msg, pEvent->GetEventBufferSize()))
{
case Ph_EVENT_MSG:
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCPlatformBaseLoop::PlatformGetNextEvent GetMessage\n"));
done = PR_TRUE;
break;
case Ph_RESIZE_MSG:
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCPlatformBaseLoop::PlatformGetNextEvent Resize Message from <%d> to <%d>\n", pEvent->GetEventBufferSize(), pEvent->GetEventSize()));
pEvent->ResizeEvent(pEvent->GetEventSize());
break;
}
}
return NS_OK;
}
nsresult nsCPlatformBaseLoop::PlatformPeekNextEvent(void* platformFilterData,
void* platformEventData, PRBool fRemoveEvent)
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCPlatformBaseLoop::PlatformPeekNextEvent platformFilterData=<%p> platformEventData=<%p> fRemoveEvent=<%d>\n", platformFilterData, platformEventData, fRemoveEvent));
if(fRemoveEvent == PR_FALSE)
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCPlatformBaseLoop::PlatformPeekNextEvent Leaving the element on the queue is not supported\n"));
return NS_COMFALSE;
}
#if 0
nsCWinFilter* filter=(nsCWinFilter*)platformFilterData;
MSG* pMsg=(MSG*)platformEventData;
if(fRemoveEvent)
filter->wRemoveFlags|= PM_REMOVE;
else
filter->wRemoveFlags&= ~PM_REMOVE;
if(::PeekMessage(pMsg, filter->hWnd, filter->wMsgFilterMin,
filter->wMsgFilterMax, filter->wRemoveFlags))
return NS_OK;
#endif
return NS_COMFALSE;
}
nsresult nsCPlatformBaseLoop::PlatformTranslateEvent(void* platformEventData)
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCPlatformBaseLoop::PlatformTranslateEvent platformEventData=<%p>\n", platformEventData));
#if 0
MSG* pMsg=(MSG*)platformEventData;
::TranslateMessage(pMsg);
#endif
return NS_OK;
}
nsresult nsCPlatformBaseLoop::PlatformDispatchEvent(void* platformEventData)
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCPlatformBaseLoop::PlatformDispatchEvent platformEventData=<%p>\n", platformEventData));
#if 0
MSG* pMsg=(MSG*)platformEventData;
::DispatchMessage(pMsg);
#endif
return NS_OK;
}
nsresult nsCPlatformBaseLoop::PlatformSendLoopEvent(void* platformEventData, PRInt32* result)
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCPlatformBaseLoop::PlatformSendLoopEvent platformEventData=<%p>\n", platformEventData));
#if 0
MSG* pMsg=(MSG*)platformEventData;
*result = ::SendMessage(pMsg->hwnd, pMsg->message, pMsg->wParam,pMsg->lParam);
#endif
return NS_OK;
}
nsresult nsCPlatformBaseLoop::PlatformPostLoopEvent(void* platformEventData)
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCPlatformBaseLoop::PlatformPostLoopEvent platformEventData=<%p>\n", platformEventData));
#if 0
MSG* pMsg=(MSG*)platformEventData;
if(!pMsg->hwnd)
{
if(!::PostThreadMessage(m_WinThreadId, pMsg->message, pMsg->wParam,
pMsg->lParam))
return NS_ERROR_FAILURE;
}
else if(!::PostMessage(pMsg->hwnd, pMsg->message, pMsg->wParam, pMsg->lParam))
return NS_ERROR_FAILURE;
#endif
return NS_OK;
}
nsNativeEventDataType nsCPlatformBaseLoop::PlatformGetEventType()
{
return nsNativeEventDataTypes::PhotonMsgStruct;
}
nsNativeEventDataType nsCPlatformBaseLoop::PlatformGetFilterType()
{
return nsNativeFilterDataTypes::PhotonFilter;
}
PRInt32 nsCPlatformBaseLoop::PlatformGetReturnCode(void* platformEventData)
{
PR_LOG(PhEventLog, PR_LOG_DEBUG, ("nsCPlatformBaseLoop::PlatformGetReturnCode platformEventData=<%p>\n", platformEventData));
#if 0
MSG* pMsg=(MSG*)platformEventData;
return pMsg->wParam;
#endif
return -1;
}

View File

@@ -0,0 +1,57 @@
/* -*- Mode: IDL; tab-width: 4; 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, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Travis Bogard <travis@netscape.com>
* Jerry Kirk <Jerry.Kirk@NexwareCorp.com>
*/
#ifndef nsCPlatformBaseLoop_h__
#define nsCPlatformBaseLoop_h__
#include "PhT.h"
#include "nsCBaseLoop.h"
class nsCPlatformBaseLoop : public nsCBaseLoop
{
protected:
nsCPlatformBaseLoop(nsEventLoopType type);
virtual ~nsCPlatformBaseLoop();
// Internal Platform Implementations of nsIEventLoop
// (Error checking is ensured above)
// We can over-ride these at a high level because they are the same
// across all types of event loops.
nsresult PlatformGetNextEvent(void* platformFilterData, void* platformEventData);
nsresult PlatformPeekNextEvent(void* FilterData, void* platformEventData,
PRBool fRemoveElement);
nsresult PlatformTranslateEvent(void* platformEventData);
nsresult PlatformDispatchEvent(void* platformEventData);
nsresult PlatformSendLoopEvent(void* platformEventData, PRInt32* result);
nsresult PlatformPostLoopEvent(void* platformEventData);
nsNativeEventDataType PlatformGetEventType();
nsNativeFilterDataType PlatformGetFilterType();
PRInt32 PlatformGetReturnCode(void* platformEventData);
protected:
pthread_t m_PhThreadId;
};
#endif /* nsCAppLoop_h__ */

View File

@@ -0,0 +1,44 @@
/* -*- Mode: IDL; tab-width: 4; 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, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Travis Bogard <travis@netscape.com>
*/
#ifndef nsCThreadLoop_h__
#define nsCThreadLoop_h__
#include "nsCBaseThreadLoop.h"
class nsCThreadLoop : public nsCBaseThreadLoop
{
public:
static NS_METHOD Create(nsISupports* aOuter, const nsIID& aIID, void** ppv);
protected:
nsCThreadLoop();
virtual ~nsCThreadLoop();
// Internal Platform Implementations of nsIEventLoop
// (Error checking is ensured above)
nsresult PlatformExit(PRInt32 exitCode);
protected:
};
#endif /* nsCThreadLoop_h__ */

View File

@@ -0,0 +1,12 @@
#include "nsISupports.idl"
#include "nsIEvent.idl"
/**
* The nsIPhEvent defines what a message looks like on the Photon Platform.
*/
[scriptable, uuid(2EFB5005-4508-11d3-AEDA-00A024FFC08C)]
interface nsIPhEvent : nsIEvent
{
//XXX Place the contents of a Photon PhEvent_t struct here.
};

View File

@@ -0,0 +1,14 @@
#include "nsISupports.idl"
#include "nsIEventFilter.idl"
/**
* The nsIPhEventFilter defines what a message filter looks like on the Photon
* Platform.
*/
[scriptable, uuid(2EFB5006-4508-11d3-AEDA-00A024FFC08C)]
interface nsIPhEventFilter : nsIEventFilter
{
//XXX Place the contents of a Photon PhEvent_t struct here.
//As well as other needed filtering criteria.
};

View File

@@ -0,0 +1,29 @@
/* -*- Mode: C++; tab-width: 4; 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):
*/
/*
* Used for Logging in the xpcom/appshell/eventloop/photon directory.
*/
#include <prlog.h>
extern PRLogModuleInfo *PhEventLog;

View File

@@ -0,0 +1,62 @@
#!nmake
#
# 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, Inc. Portions created by Netscape are
# Copyright (C) 1999, Mozilla. All Rights Reserved.
#
# Contributor(s):
# Travis Bogard <travis@netscape.com>
DEPTH=..\..\..\..
MODULE=xpcom_eventloop_windows
MAKE_OBJ_TYPE=DLL
DLLNAME=evntloop
DLL=.\$(OBJDIR)\$(DLLNAME).dll
XPIDLSRCS= \
.\nsIWinEvent.idl \
.\nsIWinEventFilter.idl \
$(NULL)
CPP_OBJS= \
.\..\xp\$(OBJDIR)\nsCLoopModule.obj \
.\..\xp\$(OBJDIR)\nsCBaseLoop.obj \
.\..\xp\$(OBJDIR)\nsCBaseAppLoop.obj \
.\..\xp\$(OBJDIR)\nsCBaseBreathLoop.obj \
.\..\xp\$(OBJDIR)\nsCBaseThreadLoop.obj \
.\$(OBJDIR)\nsCPlatformBaseLoop.obj \
.\$(OBJDIR)\nsCEvent.obj \
.\$(OBJDIR)\nsCEventFilter.obj \
.\$(OBJDIR)\nsCAppLoop.obj \
.\$(OBJDIR)\nsCThreadLoop.obj \
.\$(OBJDIR)\nsCBreathLoop.obj \
$(NULL)
LLIBS= \
$(DIST)\lib\xpcom.lib \
$(LIBNSPR)
LINCS= \
-I..\xp \
$(NULL)
include <$(DEPTH)\config\config.mak>
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib

View File

@@ -0,0 +1,62 @@
/* -*- Mode: IDL; tab-width: 4; 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, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Travis Bogard <travis@netscape.com>
*/
#include "nsCAppLoop.h"
#include "nsCWinFilter.h"
//*****************************************************************************
//*** nsCAppLoop: Object Management
//*****************************************************************************
nsCAppLoop::nsCAppLoop() : nsCBaseAppLoop()
{
}
nsCAppLoop::~nsCAppLoop()
{
}
NS_METHOD nsCAppLoop::Create(nsISupports* aOuter, const nsIID& aIID,
void** ppv)
{
NS_ENSURE_ARG_POINTER(ppv);
NS_ENSURE_NO_AGGREGATION(aOuter);
nsCAppLoop* app = new nsCAppLoop();
NS_ENSURE_TRUE(app, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(app);
nsresult rv = app->QueryInterface(aIID, ppv);
NS_RELEASE(app);
return rv;
}
//*****************************************************************************
// nsCAppLoop:: Internal Platform Implementations of nsIEventLoop
// (Error checking is ensured above)
//*****************************************************************************
nsresult nsCAppLoop::PlatformExit(PRInt32 exitCode)
{
PostQuitMessage(exitCode);
return NS_OK;
}

View File

@@ -0,0 +1,44 @@
/* -*- Mode: IDL; tab-width: 4; 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, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Travis Bogard <travis@netscape.com>
*/
#ifndef nsCAppLoop_h__
#define nsCAppLoop_h__
#include "windows.h"
#include "nsCBaseAppLoop.h"
class nsCAppLoop : public nsCBaseAppLoop
{
public:
static NS_METHOD Create(nsISupports* aOuter, const nsIID& aIID, void** ppv);
protected:
nsCAppLoop();
virtual ~nsCAppLoop();
// Internal Platform Implementations of nsIEventLoop
// (Error checking is ensured above)
nsresult PlatformExit(PRInt32 exitCode);
};
#endif /* nsCAppLoop_h__ */

View File

@@ -0,0 +1,80 @@
/* -*- Mode: IDL; tab-width: 4; 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, Inc. Portions created by Netscape are
* Copyright (C) 1999, Mozilla. All Rights Reserved.
*
* Contributor(s):
* Travis Bogard <travis@netscape.com>
*/
#include "nsCBreathLoop.h"
#include "nsCWinFilter.h"
//*****************************************************************************
//*** nsCBreathLoop: Object Management
//*****************************************************************************
nsCBreathLoop::nsCBreathLoop() : nsCBaseBreathLoop()
{
}
nsCBreathLoop::~nsCBreathLoop()
{
}
NS_METHOD nsCBreathLoop::Create(nsISupports* aOuter, const nsIID& aIID,
void** ppv)
{
NS_ENSURE_ARG_POINTER(ppv);
NS_ENSURE_NO_AGGREGATION(aOuter);
nsCBreathLoop* app = new nsCBreathLoop();
NS_ENSURE_TRUE(app, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(app);
nsresult rv = app->QueryInterface(aIID, ppv);
NS_RELEASE(app);
return rv;
}
//*****************************************************************************
// nsCBreathLoop:: Internal Platform Implementations of nsIEventLoop
// (Error checking is ensured above)
//*****************************************************************************
nsresult nsCBreathLoop::PlatformExit(PRInt32 exitCode)
{
// XXX Not sure we can force PeekMessage out....
return NS_OK;
}
PRInt32 nsCBreathLoop::PlatformGetReturnCode(void* platformEventData)
{
return 0;
}
nsresult nsCBreathLoop::PlatformRetrieveNextEvent(void* platformFilterData,
void* platformEventData)
{
nsCWinFilter* filter=(nsCWinFilter*)platformFilterData;
MSG* pMsg=(MSG*)platformEventData;
filter->wRemoveFlags|= PM_REMOVE;
if(::PeekMessage(pMsg, filter->hWnd, filter->wMsgFilterMin,
filter->wMsgFilterMax, filter->wRemoveFlags))
return NS_OK;
return NS_COMFALSE;
}

Some files were not shown because too many files have changed in this diff Show More