Compare commits

..

60 Commits

Author SHA1 Message Date
blizzard%redhat.com
2ca39b9b17 merge from head
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53740 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-17 03:57:27 +00:00
blizzard%redhat.com
fe94a6ca17 merges from head
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53737 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-17 03:27:47 +00:00
blizzard%redhat.com
dbd81545d5 remove these files from the branch, they are elsewhere in head now...
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53733 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-17 03:14:54 +00:00
blizzard%redhat.com
eae64955ac merge modal changes from head
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53660 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-16 16:15:13 +00:00
blizzard%redhat.com
ac2b83c0f5 merge IM fixes from head
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53656 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-16 16:08:54 +00:00
blizzard%redhat.com
4de4b9b262 merges from head
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53653 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-16 15:56:04 +00:00
(no author)
585367a7b8 This commit was manufactured by cvs2svn to create branch 'SUPERWIN'.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53594 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-16 01:52:21 +00:00
blizzard%redhat.com
8226158ae4 focus changes from head
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53447 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-14 04:34:41 +00:00
blizzard%redhat.com
9cb5b0bd0f don't clear the xlate queue for ConfigureEvents on shell windows since the xlate queue has nothing to do with that shell window...
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53425 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-13 15:10:10 +00:00
blizzard%redhat.com
ac24bf46fe merges from head
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53408 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-13 04:55:21 +00:00
blizzard%redhat.com
feb3b49669 work around for lame NS_SIZE event problems...
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53361 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-12 20:24:19 +00:00
blizzard%redhat.com
e4d84ceca8 use the external gtksuperwin library
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53360 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-12 20:14:52 +00:00
blizzard%redhat.com
63e9105b5f add gtksuperwin to the build list
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53359 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-12 20:13:40 +00:00
blizzard%redhat.com
21904a64db patch from claudius@netscape.com to make this build on platforms with picky c++ compilers
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53355 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-12 18:10:02 +00:00
blizzard%redhat.com
6d8df6d4e7 add a -lgtksuperwin for the viewer since it embeds a native widget into the layout
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53354 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-12 17:29:47 +00:00
blizzard%redhat.com
8f49d292ca merge in some of pav's IM changes...
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53281 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-12 00:04:56 +00:00
pavlov%netscape.com
e1431cd937 fix loop in debugging code
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53251 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-11 22:03:47 +00:00
blizzard%redhat.com
d8ee1acce8 make sure that we do a gtk_style_attach() in the realize method so the style doesn't get destroyed early...
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53241 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-11 21:39:27 +00:00
blizzard%redhat.com
db224b8d6e merge in clipboard changes. remove some more debugging spew.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53089 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-10 21:29:44 +00:00
blizzard%redhat.com
37106d7fc3 remove more debugging spew
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53088 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-10 21:05:38 +00:00
blizzard%redhat.com
0c074d2a55 remove debugging spew
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53086 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-10 19:35:01 +00:00
blizzard%redhat.com
7d47d3aace make sure to send focus in and focus out events properly when giving focus to a superwin.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53085 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-10 19:31:50 +00:00
blizzard%redhat.com
4d1a2e8639 merge the license whackage
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53020 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-09 23:06:12 +00:00
blizzard%redhat.com
8b6d035f17 add focus support
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53016 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-09 22:53:26 +00:00
blizzard%redhat.com
4d22490af1 fix warnings due to passing bad data to the debug code
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53008 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-09 19:48:03 +00:00
blizzard%redhat.com
4a1d8f7401 fix bogus warnings for gtk_signal_emit_stop_by_name
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52997 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-09 17:20:22 +00:00
blizzard%redhat.com
3ed82d86a0 add nsWindow::SetCursor
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52996 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-09 17:10:22 +00:00
blizzard%redhat.com
e763644046 fix background colors on windows
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52995 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-09 17:03:43 +00:00
blizzard%redhat.com
e94c0535d1 add hacks for superwin
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52971 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 22:56:27 +00:00
blizzard%redhat.com
201eebe4ec add mozbox code
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52965 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 22:34:41 +00:00
blizzard%redhat.com
91802fc4cb add superwin code for mozbox
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52964 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 22:34:22 +00:00
pavlov%netscape.com
68a592d45f fix debugging stuff like flashing, etc
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52963 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 22:32:36 +00:00
blizzard%redhat.com
60c89eba4b export our gtk header files. we'll need them for embedding.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52953 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 21:52:35 +00:00
blizzard%redhat.com
ceecd95095 make sure that the child window uses the same destroy as the nsWindow class
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52950 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 21:40:54 +00:00
blizzard%redhat.com
220151a643 assert if we get passed bad data. this is for testing.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52944 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 16:11:10 +00:00
blizzard%redhat.com
35d00c2c83 only send resize events on windows that are toplevel or have been created with a native parent
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52930 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-07 19:31:15 +00:00
blizzard%redhat.com
dfccc12330 add nsWindow::SetBackgroundColor, fix a warning
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52923 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-06 20:39:28 +00:00
(no author)
3c0a628da5 This commit was manufactured by cvs2svn to create branch 'SUPERWIN'.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52913 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-06 03:43:57 +00:00
blizzard%redhat.com
e67e916ea6 turn off the backing store for now
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52889 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-06 00:30:53 +00:00
blizzard%redhat.com
2312b5fc11 fix problems with using nsWindow::WidgetToScreen with toplevel windows
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52863 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 21:37:52 +00:00
blizzard%redhat.com
fcb064c579 turn on backing store for the bin_window
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52856 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 16:39:20 +00:00
blizzard%redhat.com
72255234ea add expose event compression
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52854 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 15:58:56 +00:00
blizzard%redhat.com
2cff6771cb never assign a mozarea to mMozArea unless you own it.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52853 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 15:49:31 +00:00
pavlov%netscape.com
f16eb3c3d2 fix WidgetToScreen
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52850 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 06:05:37 +00:00
pavlov%netscape.com
cc5f4699b6 remove #ifdef GTK_FIXED crap. make USE_SUPERWIN default, and fix native system color stuff (to be in head soon)
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52845 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 05:45:52 +00:00
blizzard%redhat.com
8dbfb05c9f fix some refcounting problems with the superwin and mozarea
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52821 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-04 23:12:20 +00:00
blizzard%redhat.com
4f6c078a40 make sure to destroy the superwin when the object goes out of scope
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52806 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-04 21:51:50 +00:00
blizzard%redhat.com
f303b7b880 add queued drawing
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52803 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-04 21:16:21 +00:00
blizzard%redhat.com
d5d532bbdf make rollup events work.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52801 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-04 20:33:34 +00:00
blizzard%redhat.com
1e9545d94e scrolling added
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52797 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-04 20:06:53 +00:00
blizzard%redhat.com
bbaf2a8966 implement nsWindow::Resize and nsWindow::Move methods
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52772 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-04 03:25:04 +00:00
blizzard%redhat.com
4979b2734e first pass at getting superwin code to build. it will run now but doesn't have nsWindow::Move and nsWindow::Resize implemented...
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52747 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-03 23:07:52 +00:00
blizzard%redhat.com
0ba4ab32b2 fix some indenting issues
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52724 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-03 20:10:28 +00:00
blizzard%redhat.com
53df453f1a add gdk event handler
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52722 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-03 19:47:14 +00:00
blizzard%redhat.com
db90d4ddcf start adding glue code for events for the superwin and mozbox code. also, add the box and superwin as class members.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52721 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-03 18:58:37 +00:00
blizzard%redhat.com
24a4aec113 change all of the debugging calls to use GtkObject or GtkWidget
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52718 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-03 16:38:21 +00:00
blizzard%redhat.com
74599c2956 change all of the CreateNative calls to use GtkObject instead of GtkWidget
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52717 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-03 16:09:35 +00:00
(no author)
9b52dc355f This commit was manufactured by cvs2svn to create branch 'SUPERWIN'.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52698 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-03 07:34:51 +00:00
blizzard%redhat.com
1792ff0e46 start on the branch to get the superwin code to build.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52591 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-02 22:21:47 +00:00
(no author)
fb08d16e05 This commit was manufactured by cvs2svn to create branch 'SUPERWIN'.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52461 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-02 01:25:01 +00:00
1002 changed files with 19066 additions and 296683 deletions

View File

@@ -1,621 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 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

@@ -1,78 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 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,124 +0,0 @@
/* -*- 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

@@ -1,44 +0,0 @@
/* -*- 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

@@ -1,55 +0,0 @@
/* -*- 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

@@ -1,621 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 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

@@ -1,78 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 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,923 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* 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

@@ -1,523 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* 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

@@ -1,629 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* 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

@@ -1,743 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* 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

@@ -1,163 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "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

@@ -1,382 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
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

@@ -1,882 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 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

@@ -1,113 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* 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

@@ -1,181 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is 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

@@ -1,703 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 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

@@ -1,69 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is 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

@@ -1,93 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is 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

@@ -1,60 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is 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

@@ -1,145 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is 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

@@ -1,163 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is 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

@@ -1,203 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* 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

@@ -1,135 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is 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

@@ -1,162 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is 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

@@ -1,135 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is 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

@@ -1,343 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is 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

@@ -1,186 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is 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

@@ -1,180 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is 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

@@ -1,746 +0,0 @@
/* -*- 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

@@ -1,173 +0,0 @@
/* -*- 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

@@ -1,700 +0,0 @@
/* -*- 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

@@ -1,192 +0,0 @@
/* -*- 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___ */

View File

@@ -0,0 +1,197 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public
PROGRAM = viewer
CPPSRCS = \
$(TOOLKIT_CPPSRCS) \
nsBaseDialog.cpp \
nsFindDialog.cpp \
nsXPBaseWindow.cpp \
nsTableInspectorDialog.cpp \
nsImageInspectorDialog.cpp \
nsPrintSetupDialog.cpp \
nsBrowserWindow.cpp \
nsEditorMode.cpp \
nsSetupRegistry.cpp \
nsThrobber.cpp \
nsViewerApp.cpp \
nsWebCrawler.cpp \
$(NULL)
EXPORT_RESOURCE_SAMPLES := \
$(wildcard $(srcdir)/samples/test*.html) \
$(wildcard $(srcdir)/samples/toolbarTest*.xul) \
$(wildcard $(srcdir)/samples/treeTest*.xul) \
$(wildcard $(srcdir)/samples/treeTest*.css) \
$(wildcard $(srcdir)/samples/slider*.xul) \
$(wildcard $(srcdir)/samples/scrollbar*.xul) \
$(srcdir)/resources/find.html \
$(srcdir)/resources/printsetup.html \
$(srcdir)/resources/image_props.html \
$(srcdir)/samples/aform.css \
$(srcdir)/samples/bform.css \
$(srcdir)/samples/cform.css \
$(srcdir)/samples/demoform.css \
$(srcdir)/samples/mozform.css \
$(srcdir)/samples/xulTest.css \
$(srcdir)/samples/Anieyes.gif \
$(srcdir)/samples/gear1.gif \
$(srcdir)/samples/rock_gra.gif \
$(srcdir)/samples/beeptest.html \
$(srcdir)/samples/soundtest.html \
$(srcdir)/samples/bg.jpg \
$(srcdir)/samples/raptor.jpg \
$(srcdir)/samples/test.wav \
$(srcdir)/samples/checkboxTest.xul \
$(NULL)
EXPORT_RESOURCE_THROBBER := $(wildcard $(srcdir)/throbber/anim*.gif)
ifeq (,$(filter beos os2 rhapsody photon,$(MOZ_WIDGET_TOOLKIT)))
DIRS += unix
UNIX_VIEWER_TK_LIBS = $(DIST)/lib/libviewer_$(MOZ_WIDGET_TOOLKIT)_s.a
else
ifeq ($(MOZ_WIDGET_TOOLKIT),beos)
BEOS_PROGRAM_RESOURCE = $(srcdir)/viewer-beos.rsrc
TOOLKIT_CPPSRCS = nsBeOSMain.cpp
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),photon)
TOOLKIT_CPPSRCS = nsPhMain.cpp nsPhMenu.cpp
endif
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk)
GTK_GLUE = -lgtksuperwin
endif
ifdef MOZ_OJI
JSJ_LIB = -ljsj
endif
XP_DIST_LIBS = \
-lraptorgfx \
-lmozjs \
-lxpcom \
$(JSJ_LIB) \
$(NULL)
XP_NS_UNDERBAR_CRAP = \
$(MOZ_NECKO_UTIL_LIBS) \
$(MOZ_TIMER_LIBS) \
$(MOZ_WIDGET_SUPPORT_LIBS) \
$(NULL)
XP_LIBS = \
$(XP_NS_UNDERBAR_CRAP) \
$(XP_DIST_LIBS) \
$(NSPR_LIBS) \
$(NULL)
ifdef MOZ_FULLCIRCLE
XP_LIBS += $(FULLCIRCLE_LIBS)
endif
LIBS = \
$(UNIX_VIEWER_TK_LIBS) \
$(GTK_GLUE) \
$(XP_LIBS) \
$(TK_LIBS) \
$(NULL)
MOTIF_LIBS = -lviewer_motif_s $(XP_LIBS) $(MOZ_MOTIF_LDFLAGS)
QT_LIBS = -lviewer_qt_s $(XP_LIBS) $(MOZ_QT_LDFLAGS)
XLIB_LIBS = -lviewer_xlib_s $(XP_LIBS) $(MOZ_XLIB_LDFLAGS)
GTK_LIBS = -lviewer_gtk_s -lgtksuperwin $(XP_LIBS) $(MOZ_GTK_LDFLAGS)
EXTRA_DEPS = \
$(addprefix $(DIST)/,$(patsubst -l%,bin/lib%.$(DLL_SUFFIX),$(XP_DIST_LIBS:-l%_s=lib/lib%_s.a))) \
$(UNIX_VIEWER_TK_LIBS) \
$(XP_NS_UNDERBAR_CRAP) \
$(NULL)
include $(topsrcdir)/config/rules.mk
CXXFLAGS += $(MOZ_TOOLKIT_REGISTRY_CFLAGS)
install:: $(PROGRAM) $(srcdir)/mozilla-viewer.sh
$(INSTALL) $(EXPORT_RESOURCE_SAMPLES) $(DIST)/bin/res/samples
$(INSTALL) $(EXPORT_RESOURCE_THROBBER) $(DIST)/bin/res/throbber
$(INSTALL) $(srcdir)/resources/viewer.properties $(DIST)/bin/res
$(INSTALL) $(srcdir)/mozilla-viewer.sh $(DIST)/bin
$(PROGRAM)_gtk: $(PROGOBJS) $(EXTRA_DEPS) Makefile Makefile.in $(DIST)/lib/libviewer_gtk_s.a
$(CCC) -o $@ $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(GTK_LIBS) $(OS_LIBS)
$(MOZ_POST_PROGRAM_COMMAND) $@
$(PROGRAM)_motif: $(PROGOBJS) $(EXTRA_DEPS) Makefile Makefile.in $(DIST)/lib/libviewer_motif_s.a
$(CCC) -o $@ $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(MOTIF_LIBS) $(OS_LIBS)
$(MOZ_POST_PROGRAM_COMMAND) $@
$(PROGRAM)_qt: $(PROGOBJS) $(EXTRA_DEPS) Makefile Makefile.in $(DIST)/lib/libviewer_qt_s.a
$(CCC) -o $@ $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(QT_LIBS) $(OS_LIBS)
$(MOZ_POST_PROGRAM_COMMAND) $@
$(PROGRAM)_xlib: $(PROGOBJS) $(EXTRA_DEPS) Makefile Makefile.in $(DIST)/lib/libviewer_xlib_s.a
$(CCC) -o $@ $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(XLIB_LIBS) $(OS_LIBS)
$(MOZ_POST_PROGRAM_COMMAND) $@
ifdef MOZ_ENABLE_GTK
install:: $(PROGRAM)_gtk
$(INSTALL) -m 555 $< $(DIST)/bin
clobber::
rm -f $(PROGRAM)_gtk
endif
ifdef MOZ_ENABLE_MOTIF
install:: $(PROGRAM)_motif
$(INSTALL) -m 555 $< $(DIST)/bin
clobber::
rm -f $(PROGRAM)_motif
endif
ifdef MOZ_ENABLE_QT
install:: $(PROGRAM)_qt
$(INSTALL) -m 555 $< $(DIST)/bin
clobber::
rm -f $(PROGRAM)_qt
endif
ifdef MOZ_ENABLE_XLIB
install:: $(PROGRAM)_xlib
$(INSTALL) -m 555 $< $(DIST)/bin
clobber::
rm -f $(PROGRAM)_xlib
endif

View File

@@ -0,0 +1,179 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "gdksuperwin.h"
#include "gtkmozbox.h"
#include "nsBrowserWindow.h"
#include "resources.h"
#include "nscore.h"
#include "stdio.h"
typedef GtkItemFactoryCallback GIFC;
void gtk_ifactory_cb (nsBrowserWindow *nbw,
guint callback_action,
GtkWidget *widget)
{
nbw->DispatchMenuItem(callback_action);
}
GtkItemFactoryEntry menu_items[] =
{
{ "/_File", nsnull, nsnull, 0, "<Branch>" },
{ "/File/_New Window", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_WINDOW_OPEN, nsnull },
{ "/File/_Open...", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_FILE_OPEN, nsnull },
{ "/File/_View Source", nsnull, (GIFC)gtk_ifactory_cb, VIEW_SOURCE, nsnull },
{ "/File/_Samples", nsnull, nsnull, 0, "<Branch>" },
{ "/File/Samples/demo #0", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO0, nsnull },
{ "/File/Samples/demo #1", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO1, nsnull },
{ "/File/Samples/demo #2", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO2, nsnull },
{ "/File/Samples/demo #3", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO3, nsnull },
{ "/File/Samples/demo #4", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO4, nsnull },
{ "/File/Samples/demo #5", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO5, nsnull },
{ "/File/Samples/demo #6", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO6, nsnull },
{ "/File/Samples/demo #7", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO7, nsnull },
{ "/File/Samples/demo #8", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO8, nsnull },
{ "/File/Samples/demo #9", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO9, nsnull },
{ "/File/Samples/demo #10", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO10, nsnull },
{ "/File/Samples/demo #11", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO11, nsnull },
{ "/File/Samples/demo #12", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO12, nsnull },
{ "/File/Samples/demo #13", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO13, nsnull },
{ "/File/Samples/demo #14", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO14, nsnull },
{ "/File/Samples/demo #15", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO15, nsnull },
{ "/File/Samples/demo #16", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO16, nsnull },
{ "/File/Samples/demo #17", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO17, nsnull },
{ "/File/_Test Sites", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOP100, nsnull },
{ "/File/XPToolkit Tests", nsnull, nsnull, 0, "<Branch>" },
{ "/File/XPToolkit Tests/Toolbar Test 1", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_XPTOOLKITTOOLBAR1, nsnull },
{ "/File/XPToolkit Tests/Tree Test 1", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_XPTOOLKITTREE1, nsnull },
{ "/File/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/File/Print Preview", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_ONE_COLUMN, nsnull },
{ "/File/Print", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_PRINT, nsnull },
{ "/File/Print Setup", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_PRINT_SETUP, nsnull },
{ "/File/sep2", nsnull, nsnull, 0, "<Separator>" },
{ "/File/_Exit", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EXIT, nsnull },
{ "/_Edit", nsnull, nsnull, 0, "<Branch>" },
{ "/Edit/Cu_t", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_CUT, nsnull },
{ "/Edit/_Copy", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_COPY, nsnull },
{ "/Edit/_Paste", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_PASTE, nsnull },
{ "/Edit/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Edit/Select All", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_SELECTALL, nsnull },
{ "/Edit/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Edit/Find in Page", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_FINDINPAGE, nsnull },
//#ifdef DEBUG // turning off for now
{ "/_Debug", nsnull, nsnull, 0, "<Branch>" },
{ "/Debug/_Visual Debugging", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_VISUAL_DEBUGGING,nsnull },
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Debug/Event Debugging/Toggle Paint Flashing", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_PAINT_FLASHING,nsnull },
{ "/Debug/Event Debugging/Toggle Paint Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_PAINT_DUMPING,nsnull },
{ "/Debug/Event Debugging/Toggle Invalidate Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_INVALIDATE_DUMPING,nsnull },
{ "/Debug/Event Debugging/Toggle Event Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_EVENT_DUMPING,nsnull },
{ "/Debug/Event Debugging/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Debug/Event Debugging/Toggle Motion Event Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_MOTION_EVENT_DUMPING,nsnull },
{ "/Debug/Event Debugging/Toggle Crossing Event Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_CROSSING_EVENT_DUMPING,nsnull },
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Debug/_Reflow Test", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_REFLOW_TEST, nsnull },
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Debug/Dump _Content", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_CONTENT, nsnull },
{ "/Debug/Dump _Frames", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_FRAMES, nsnull },
{ "/Debug/Dump _Views", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_VIEWS, nsnull },
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Debug/Dump _Style Sheets", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_STYLE_SHEETS, nsnull },
{ "/Debug/Dump _Style Contexts", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_STYLE_CONTEXTS, nsnull},
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Debug/Show Content Size", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SHOW_CONTENT_SIZE,nsnull },
{ "/Debug/Show Frame Size", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SHOW_FRAME_SIZE, nsnull },
{ "/Debug/Show Style Size", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SHOW_STYLE_SIZE, nsnull },
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Debug/Debug Save", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEBUGSAVE, nsnull },
{ "/Debug/Debug Output Text", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DISPLAYTEXT, nsnull },
{ "/Debug/Debug Output HTML", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DISPLAYHTML, nsnull },
{ "/Debug/Debug Toggle Selection", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_SELECTION,nsnull },
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Debug/Debug Robot", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEBUGROBOT, nsnull },
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Debug/Show Content Quality", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SHOW_CONTENT_QUALITY, nsnull },
{ "/_Style", nsnull, nsnull, 0, "<Branch>" },
{ "/Style/Select _Style Sheet", nsnull, nsnull, 0, "<Branch>" },
{ "/Style/Select Style Sheet/List Available Sheets", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_LIST, nsnull },
{ "/Style/Select Style Sheet/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Style/Select Style Sheet/Select Default", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_DEFAULT, nsnull },
{ "/Style/Select Style Sheet/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Style/Select Style Sheet/Select Alternative 1", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_ONE, nsnull },
{ "/Style/Select Style Sheet/Select Alternative 2", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_TWO, nsnull },
{ "/Style/Select Style Sheet/Select Alternative 3", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_THREE, nsnull },
{ "/Style/Select Style Sheet/Select Alternative 4", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_FOUR, nsnull },
{ "/Style/_Compatibility Mode", nsnull, nsnull, 0, "<Branch>" },
{ "/Style/Compatibility Mode/Nav Quirks", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_NAV_QUIRKS_MODE, nsnull },
{ "/Style/Compatibility Mode/Standard", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_STANDARD_MODE, nsnull },
{ "/Style/_Widget Render Mode", nsnull, nsnull, 0, "<Branch>" },
{ "/Style/Widget Render Mode/Native", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_NATIVE_WIDGET_MODE, nsnull },
{ "/Style/Widget Render Mode/Gfx", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_GFX_WIDGET_MODE, nsnull },
//#endif
{ "/_Tools", nsnull, nsnull, 0, "<Branch>" },
{ "/Tools/_JavaScript Console", nsnull, (GIFC)gtk_ifactory_cb, JS_CONSOLE, nsnull },
{ "/Tools/_Editor Mode", nsnull, (GIFC)gtk_ifactory_cb, EDITOR_MODE, nsnull }
};
void CreateViewerMenus(nsIWidget * aParent,
gpointer data,
GtkWidget ** aMenuBarOut)
{
NS_ASSERTION(nsnull != aParent,"null parent.");
NS_ASSERTION(nsnull != aMenuBarOut,"null out param.");
GtkItemFactory *item_factory;
GtkWidget *menubar;
GdkSuperWin *gdkSuperWin;
GtkWidget *mozBox;
gdkSuperWin = (GdkSuperWin*)aParent->GetNativeData(NS_NATIVE_WIDGET);
int nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", nsnull);
gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, data);
menubar = gtk_item_factory_get_widget (item_factory, "<main>");
gtk_menu_bar_set_shadow_type (GTK_MENU_BAR(menubar), GTK_SHADOW_NONE);
NS_ASSERTION(GDK_IS_SUPERWIN(gdkSuperWin), "code assumes a gdksuperwin.");
mozBox = gtk_mozbox_new(gdkSuperWin->bin_window);
NS_ASSERTION((mozBox != NULL), "failed to create mozBox.");
gtk_container_add(GTK_CONTAINER(mozBox), menubar);
gtk_mozbox_set_position(GTK_MOZBOX(mozBox), 0, 0 );
gtk_widget_show(mozBox);
gtk_widget_show(menubar);
*aMenuBarOut = menubar;
}

View File

@@ -19,18 +19,49 @@
# Contributor(s):
#
DEPTH = ../../..
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = xp
DIRS = xpwidgets support
ifneq (,$(filter gtk photon,$(MOZ_WIDGET_TOOLKIT)))
#
# Dont build the DSO under the 'build' directory as windows does.
#
# The DSOs get built in the toolkit dir itself. Do this so that
# multiple implementations of widget can be built on the same
# source tree.
#
ifndef MOZ_MONOLITHIC_TOOLKIT
ifdef MOZ_ENABLE_GTK
DIRS += gtksuperwin
DIRS += gtk
endif
ifdef MOZ_ENABLE_MOTIF
DIRS += motif
endif
ifdef MOZ_ENABLE_XLIB
DIRS += xlib
endif
ifdef MOZ_ENABLE_QT
DIRS += qt
endif
else
DIRS += $(MOZ_WIDGET_TOOLKIT)
endif
# unix_services are only useful in unix, duh...
ifeq (,$(filter beos os2 rhapsody photon,$(MOZ_WIDGET_TOOLKIT)))
DIRS += unix_services
endif
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,100 @@
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
LIBRARY_NAME = widget_gtk
REQUIRES = util img xpcom raptor netlib
CPPSRCS = \
nsAppShell.cpp \
nsButton.cpp \
nsCheckButton.cpp \
nsClipboard.cpp \
nsComboBox.cpp \
nsContextMenu.cpp \
nsDragService.cpp \
nsFilePicker.cpp \
nsFileWidget.cpp \
nsFontRetrieverService.cpp \
nsFontSizeIterator.cpp \
nsGtkEventHandler.cpp \
nsGtkUtils.cpp \
nsLabel.cpp \
nsListBox.cpp \
nsLookAndFeel.cpp \
nsMenu.cpp \
nsMenuBar.cpp \
nsMenuItem.cpp \
nsPopUpMenu.cpp \
nsRadioButton.cpp \
nsScrollbar.cpp \
nsSound.cpp \
nsTextAreaWidget.cpp \
nsTextHelper.cpp \
nsTextWidget.cpp \
nsToolkit.cpp \
nsWidget.cpp \
nsWidgetFactory.cpp \
nsWindow.cpp \
$(NULL)
SHARED_LIBRARY_LIBS = $(DIST)/lib/libraptorbasewidget_s.a
EXTRA_DSO_LDOPTS = \
$(MKSHLIB_FORCE_ALL) \
$(SHARED_LIBRARY_LIBS) \
$(MKSHLIB_UNFORCE_ALL) \
$(MOZ_COMPONENT_LIBS) \
-lraptorgfx \
$(NULL)
ifndef MOZ_MONOLITHIC_TOOLKIT
EXTRA_DSO_LDOPTS += -L$(DIST)/lib -lgtksuperwin $(MOZ_GTK_LDFLAGS)
else
EXTRA_DSO_LDOPTS += $(TK_LIBS)
endif
include $(topsrcdir)/config/rules.mk
ifndef MOZ_MONOLITHIC_TOOLKIT
CXXFLAGS += $(MOZ_GTK_CFLAGS)
CFLAGS += $(MOZ_GTK_CFLAGS)
else
CXXFLAGS += $(TK_CFLAGS)
CFLAGS += $(TK_CFLAGS)
endif
DEFINES += -D_IMPL_NS_WIDGET -DUSE_XIM
ifeq ($(OS_ARCH), Linux)
DEFINES += -D_BSD_SOURCE
endif
INCLUDES += \
-I$(srcdir)/../xpwidgets \
-I$(srcdir) \
$(NULL)
$(LIBRARY) $(SHARED_LIBRARY): $(SHARED_LIBRARY_LIBS) Makefile

View File

@@ -0,0 +1,292 @@
/* XPM */
static char * mozilla_icon_xpm[] = {
"32 32 257 2",
" c None",
". c #AA7303",
"+ c #A67003",
"@ c #B77C03",
"# c #8D6003",
"$ c #8D6004",
"% c #6C4A04",
"& c #3A2804",
"* c #6B4802",
"= c #9B6903",
"- c #5A2C04",
"; c #411B04",
"> c #9D6A03",
", c #7A5203",
"' c #510D04",
") c #6B1104",
"! c #7D5503",
"~ c #674604",
"{ c #C21E04",
"] c #C21D04",
"^ c #523804",
"/ c #513702",
"( c #552904",
"_ c #DD2204",
": c #DF2204",
"< c #582904",
"[ c #5F3F02",
"} c #6B2504",
"| c #FE2604",
"1 c #AB7303",
"2 c #9B6904",
"3 c #C31F04",
"4 c #FE2704",
"5 c #A81904",
"6 c #926304",
"7 c #4D3302",
"8 c #483104",
"9 c #C61E04",
"0 c #B11B04",
"a c #891604",
"b c #761204",
"c c #614304",
"d c #775102",
"e c #795102",
"f c #785102",
"g c #C58603",
"h c #642404",
"i c #B21A04",
"j c #1F0604",
"k c #550E04",
"l c #631004",
"m c #402404",
"n c #AF7703",
"o c #3D2902",
"p c #7F5602",
"q c #805604",
"r c #0C0904",
"s c #080604",
"t c #080706",
"u c #090604",
"v c #060404",
"w c #620F04",
"x c #7A1304",
"y c #030204",
"z c #570E04",
"A c #721204",
"B c #270704",
"C c #080504",
"D c #0A0604",
"E c #533804",
"F c #A56F02",
"G c #B87C03",
"H c #3B2804",
"I c #A51904",
"J c #FC2704",
"K c #D62004",
"L c #691004",
"M c #C01E04",
"N c #6D1004",
"O c #9C1804",
"P c #B31C04",
"Q c #150404",
"R c #801404",
"S c #DD2304",
"T c #120404",
"U c #130404",
"V c #500C04",
"W c #CC1E04",
"X c #AA1A04",
"Y c #100904",
"Z c #B47A03",
"` c #A77103",
" . c #513704",
".. c #891704",
"+. c #F62604",
"@. c #BA1D04",
"#. c #3C0A04",
"$. c #EB2304",
"%. c #DE2304",
"&. c #560E04",
"*. c #E82304",
"=. c #FE2804",
"-. c #BE1D04",
";. c #F12404",
">. c #661004",
",. c #020204",
"'. c #5E0F04",
"). c #A61A04",
"!. c #4A3204",
"~. c #BC7E03",
"{. c #8E6002",
"]. c #684604",
"^. c #390D04",
"/. c #EE2404",
"(. c #FE2904",
"_. c #7D1304",
":. c #8C1504",
"<. c #200604",
"[. c #A81A04",
"}. c #E72204",
"|. c #DA2004",
"1. c #070204",
"2. c #280704",
"3. c #543904",
"4. c #9F6C02",
"5. c #674602",
"6. c #B47B04",
"7. c #311004",
"8. c #B11C04",
"9. c #AA1B04",
"0. c #6A1104",
"a. c #801504",
"b. c #2B0704",
"c. c #09090A",
"d. c #450B04",
"e. c #360904",
"f. c #DC2204",
"g. c #EE2504",
"h. c #C11D04",
"i. c #6F1104",
"j. c #704B04",
"k. c #9C6902",
"l. c #A56F03",
"m. c #5F4004",
"n. c #8D1604",
"o. c #440A04",
"p. c #1A0504",
"q. c #931604",
"r. c #621004",
"s. c #7F1404",
"t. c #921704",
"u. c #F82504",
"v. c #F52504",
"w. c #981804",
"x. c #241804",
"y. c #5B3E04",
"z. c #D82204",
"A. c #D02004",
"B. c #DA2104",
"C. c #D52104",
"D. c #2A1A04",
"E. c #AC7403",
"F. c #2B1C04",
"G. c #D04004",
"H. c #FC3C04",
"I. c #F94E04",
"J. c #881504",
"K. c #FC2604",
"L. c #792804",
"M. c #AC7503",
"N. c #9A6803",
"O. c #782804",
"P. c #F66504",
"Q. c #F94B04",
"R. c #F46804",
"S. c #F46604",
"T. c #F76504",
"U. c #FB4204",
"V. c #C13D04",
"W. c #5D0E04",
"X. c #DA2204",
"Y. c #741604",
"Z. c #8C5E03",
"`. c #885B03",
" + c #8B1904",
".+ c #DE2204",
"++ c #D22D04",
"@+ c #C42D04",
"#+ c #580E04",
"$+ c #9F1804",
"%+ c #895D04",
"&+ c #D62204",
"*+ c #371904",
"=+ c #2C1A04",
"-+ c #4A0C04",
";+ c #140404",
">+ c #AB1A04",
",+ c #DA2304",
"'+ c #6A4702",
")+ c #754F02",
"!+ c #821404",
"~+ c #462B04",
"{+ c #B37A03",
"]+ c #B17803",
"^+ c #714C04",
"/+ c #580F04",
"(+ c #E32204",
"_+ c #DD2104",
":+ c #611D04",
"<+ c #BA7F03",
"[+ c #B27803",
"}+ c #6F1D04",
"|+ c #FD2704",
"1+ c #F22504",
"2+ c #634304",
"3+ c #875B03",
"4+ c #734F02",
"5+ c #805704",
"6+ c #1D0504",
"7+ c #DB2204",
"8+ c #EA2404",
"9+ c #2E0804",
"0+ c #815803",
"a+ c #941704",
"b+ c #C11E04",
"c+ c #391B04",
"d+ c #A77104",
"e+ c #B67C04",
"f+ c #371D04",
"g+ c #360A04",
"h+ c #573A04",
"i+ c #372604",
"j+ c #3E2104",
"k+ c #B57A03",
"l+ c #B57B03",
"m+ c #603F04",
"n+ c #430A04",
"o+ c #351904",
"p+ c #A36E03",
"q+ c #BE8103",
"r+ c #1D1404",
"s+ c #483004",
"t+ c #A26E03",
"u+ c #6D4B02",
"v+ c #825804",
"w+ c #0B0804",
"x+ c #976603",
"y+ c #815703",
"z+ c #926404",
"A+ c #895D03",
"B+ c #614202",
"C+ c #9A6804",
"D+ c #C88704",
"E+ c #C18303",
"F+ c #654302",
"G+ c #744F02",
"H+ c #704B02",
" ",
" . ",
" + @ ",
" # $ ",
" % & * ",
" = - ; > ",
" , ' ) ! ",
" ~ { ] ^ ",
" / ( _ : < [ ",
" . } | | } 1 ",
" 2 3 | 4 5 6 ",
" 7 8 9 0 a b c ",
" d e f f f d d d d d d g h i j k l m n d d d d d d d d d d d o ",
" p q r s s s s t s s u v w x y z A B C D D D D D s s s s E F ",
" G H I J 4 | 4 | K L L M N O P Q R | S T U V W X Y Z ",
" ` ...+.| 4 @.#.$.4 | %.&.*.4 =.-.;.>.,.'.).!.~. ",
" {.].^./.(.X _.;.| :.T <.[.| }.z | |.1.2.3.4. ",
" 5.6.7.8.9.0.a.b.c.d.e.f.g.h.&.| i.u j.k. ",
" l.m.n.o.p.q._.r.a.s.t.u.v.w.x.Z ",
" {.y.P z.R A.v.x j B.| C.D.E. ",
" F.G.H.I.4 | 4 t.J.f.K.L.M. ",
" N.O.P.Q.R.S.T.U.V.W.X.4 Y.Z. ",
" `. +4 =.| | .+++@+#+$+| K %+ ",
" %+&+| | | I *+=+-+;+>+,+&+x.'+ ",
" )+=+X.=.| !+~+{+]+^+,./+(+_+:+<+ ",
" [+}+|+1+) 2+3+ 4+5+6+7+8+9+0+ ",
" $ a+b+c+d+ e+f+0.g+h+ ",
" i+A j+k+ l+m+n+o+p+ ",
" q+r+s+t+ u+v+w+x+ ",
" y+z+A+ B+C+2 ",
" D+ E+F+ ",
" G+ H+ "};

View File

@@ -0,0 +1,63 @@
/* XPM */
static char * mozicon50_xpm[] = {
"50 51 9 1",
" c None",
". c #000000",
"+ c #FF0000",
"@ c #808000",
"# c #800000",
"$ c #FF6633",
"% c #990066",
"& c #FF00FF",
"* c #222222",
" ",
" @ ",
" $@ ",
" @@ ",
" @@$ ",
" $@*@ ",
" @@.@ ",
" @..@ ",
" $@..@@ ",
" $@##*@ ",
" @*#+.@ ",
" @.++.@$ ",
" $@.++.@$ ",
" @*#++#*@ ",
" @.++++.@ ",
" $@.++++.@$ ",
" @*#++++**@ ",
" @.#++++#.@ ",
" $@.++####.@ ",
" @@*+#*##*.@@ ",
"*@@@@@@@@@@@@@@@@@@@.#+..*##*#@@@@@@@@@@@@@@@@@@@*",
" *@@*................+#..*###.................@@* ",
" %@@@.#++++++++++++#**#*#++.###++*...#+++#.*@@* ",
" *@@.#+++++++++#.##++#+#+*.#+++#..##++#.@@@% ",
" $@..+++++++.#++++++##++++#++#...++*.@@$ ",
" @@*.#+++++.#+++++*.#++++##++#.*...@@ ",
" $@@.#+++#*++++#....#+++*#+++...*@$ ",
" *@@..++#*++#**.*.*+++#.#++*..@@$ ",
" $@*.++******#+++++#+#+++..@@ ",
" $@@.##..*$#**#+#*#++++..@@ ",
" $@@.#+#***##...#++++.*@@ ",
" %@@*++++++++#.#++++.@@ ",
" @.#+++++++++.##+++.@$ ",
" @.+$$$$$+$$$#*#+++*@@ ",
" $@*+$$$$$$$+$#.#+++#.@ ",
" @*#+++++++++++.#++++.@ ",
" @.#+++++++#*++.##+++.@$ ",
" $@.+++++++....#..+#++*@@ ",
" @@*+++++#.*@@@...*+++#.@ ",
" @.#++++#.@@@ @@..#++++.@ ",
" @.++++*.@@$ %@@..+++#.@@ ",
" $@.+++..@@* $@*.#+#**@ ",
" @@#+#.*@$% $@@.##..@ ",
" @.##.@@ @@..#.@$ ",
" $@.*.@@$ @@**.@$ ",
" $@.*@@ %$@@.*@ ",
" @.@@$ *@@.@ ",
" @@@$ %@@@$ ",
" $@@% %@@@ ",
" @@ $@ ",
" $ * "};

View File

@@ -0,0 +1,459 @@
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "prmon.h"
#include "nsCOMPtr.h"
#include "nsAppShell.h"
#include "nsIAppShell.h"
#include "nsIServiceManager.h"
#include "nsIEventQueueService.h"
#include "nsICmdLineService.h"
#include "nsGtkEventHandler.h"
#include <stdlib.h>
#ifdef MOZ_GLE
#include <gle/gle.h>
#endif
#include "nsIWidget.h"
#include "nsIPref.h"
#include "glib.h"
struct OurGdkIOClosure {
GdkInputFunction function;
gpointer data;
};
static gboolean
our_gdk_io_invoke(GIOChannel* source, GIOCondition condition, gpointer data)
{
OurGdkIOClosure* ioc = (OurGdkIOClosure*) data;
if (ioc) {
(*ioc->function)(ioc->data, g_io_channel_unix_get_fd(source),
GDK_INPUT_READ);
}
return TRUE;
}
static void
our_gdk_io_destroy(gpointer data)
{
OurGdkIOClosure* ioc = (OurGdkIOClosure*) data;
if (ioc) {
g_free(ioc);
}
}
static gint
our_gdk_input_add (gint source,
GdkInputFunction function,
gpointer data,
gint priority)
{
guint result;
OurGdkIOClosure *closure = g_new (OurGdkIOClosure, 1);
GIOChannel *channel;
closure->function = function;
closure->data = data;
channel = g_io_channel_unix_new (source);
result = g_io_add_watch_full (channel, priority, G_IO_IN,
our_gdk_io_invoke,
closure, our_gdk_io_destroy);
g_io_channel_unref (channel);
return result;
}
//-------------------------------------------------------------------------
//
// XPCOM CIDs
//
//-------------------------------------------------------------------------
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_CID(kCmdLineServiceCID, NS_COMMANDLINE_SERVICE_CID);
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
// a linked, ordered list of event queues and their tokens
class EventQueueToken {
public:
EventQueueToken(nsIEventQueue *aQueue, const gint aToken);
virtual ~EventQueueToken();
nsIEventQueue *mQueue;
gint mToken;
EventQueueToken *mNext;
};
EventQueueToken::EventQueueToken(nsIEventQueue *aQueue, const gint aToken) {
mQueue = aQueue;
NS_IF_ADDREF(mQueue);
mToken = aToken;
mNext = 0;
}
EventQueueToken::~EventQueueToken(){
NS_IF_RELEASE(mQueue);
}
class EventQueueTokenQueue {
public:
EventQueueTokenQueue();
virtual ~EventQueueTokenQueue();
nsresult PushToken(nsIEventQueue *aQueue, gint aToken);
PRBool PopToken(nsIEventQueue *aQueue, gint *aToken);
private:
EventQueueToken *mHead;
};
EventQueueTokenQueue::EventQueueTokenQueue() {
mHead = 0;
}
EventQueueTokenQueue::~EventQueueTokenQueue() {
// if we reach this point with an empty token queue, well, fab. however,
// we expect the first event queue to still be active. so we take
// special care to unhook that queue (not that failing to do so seems
// to hurt anything). more queues than that would be an error.
//NS_ASSERTION(!mHead || !mHead->mNext, "event queue token list deleted when not empty");
// (and skip the assertion for now. we're leaking event queues because they
// are referenced by things that leak, so this assertion goes off a lot.)
if (mHead) {
gdk_input_remove(mHead->mToken);
delete mHead;
// and leak the rest. it's an error, anyway
}
}
nsresult EventQueueTokenQueue::PushToken(nsIEventQueue *aQueue, gint aToken) {
EventQueueToken *newToken = new EventQueueToken(aQueue, aToken);
NS_ASSERTION(newToken, "couldn't allocate token queue element");
if (!newToken)
return NS_ERROR_OUT_OF_MEMORY;
newToken->mNext = mHead;
mHead = newToken;
return NS_OK;
}
PRBool EventQueueTokenQueue::PopToken(nsIEventQueue *aQueue, gint *aToken) {
EventQueueToken *token, *lastToken;
PRBool found = PR_FALSE;
NS_ASSERTION(mHead, "attempt to retrieve event queue token from empty queue");
if (mHead)
NS_ASSERTION(mHead->mQueue == aQueue, "retrieving event queue from past head of queue queue");
token = mHead;
lastToken = 0;
while (token && token->mQueue != aQueue) {
lastToken = token;
token = token->mNext;
}
if (token) {
if (lastToken)
lastToken->mNext = token->mNext;
else
mHead = token->mNext;
found = PR_TRUE;
*aToken = token->mToken;
delete token;
}
return found;
}
//-------------------------------------------------------------------------
//
// nsAppShell constructor
//
//-------------------------------------------------------------------------
nsAppShell::nsAppShell()
{
NS_INIT_REFCNT();
mDispatchListener = 0;
mEventQueueTokens = new EventQueueTokenQueue();
// throw on error would really be civilized here
NS_ASSERTION(mEventQueueTokens, "couldn't allocate event queue token queue");
}
//-------------------------------------------------------------------------
//
// nsAppShell destructor
//
//-------------------------------------------------------------------------
nsAppShell::~nsAppShell()
{
delete mEventQueueTokens;
}
//-------------------------------------------------------------------------
//
// nsISupports implementation macro
//
//-------------------------------------------------------------------------
NS_IMPL_ISUPPORTS1(nsAppShell, nsIAppShell)
//-------------------------------------------------------------------------
NS_IMETHODIMP nsAppShell::SetDispatchListener(nsDispatchListener* aDispatchListener)
{
mDispatchListener = aDispatchListener;
return NS_OK;
}
static void event_processor_callback(gpointer data,
gint source,
GdkInputCondition condition)
{
nsIEventQueue *eventQueue = (nsIEventQueue*)data;
if (eventQueue)
eventQueue->ProcessPendingEvents();
}
#define PREF_NCOLS "browser.ncols"
#define PREF_INSTALLCMAP "browser.installcmap"
static void
HandleColormapPrefs( void )
{
PRInt32 ivalue = 0;
PRBool bvalue;
nsresult rv;
/* The default is to do nothing. INSTALLCMAP has precedence over
NCOLS. Ignore the fact we can't do this if it fails, as it is
not critical */
NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv);
if (NS_FAILED(rv) || (!prefs))
return;
/* first check ncols */
rv = prefs->GetIntPref(PREF_NCOLS, &ivalue);
if (NS_SUCCEEDED(rv) && ivalue >= 0 && ivalue <= 255 ) {
gdk_rgb_set_min_colors( ivalue );
return;
}
/* next check installcmap */
rv = prefs->GetBoolPref(PREF_INSTALLCMAP, &bvalue);
if (NS_SUCCEEDED(rv)) {
if ( PR_TRUE == bvalue )
gdk_rgb_set_min_colors( 255 ); // force it
else
gdk_rgb_set_min_colors( 0 );
}
}
//-------------------------------------------------------------------------
//
// Create the application shell
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsAppShell::Create(int *bac, char **bav)
{
gchar *home=nsnull;
gchar *path=nsnull;
int argc = bac ? *bac : 0;
char **argv = bav;
#if 1
nsresult rv;
NS_WITH_SERVICE(nsICmdLineService, cmdLineArgs, kCmdLineServiceCID, &rv);
if (NS_SUCCEEDED(rv))
{
rv = cmdLineArgs->GetArgc(&argc);
if(NS_FAILED(rv))
argc = bac ? *bac : 0;
rv = cmdLineArgs->GetArgv(&argv);
if(NS_FAILED(rv))
argv = bav;
}
#endif
gtk_set_locale ();
gtk_init (&argc, &argv);
// It is most convenient for us to intercept our events after
// they have been converted to GDK, but before GTK+ gets them
gdk_event_handler_set (handle_gdk_event, NULL, NULL);
#ifdef MOZ_GLE
gle_init (&argc, &argv);
#endif
// delete the cmdLineArgs thing?
HandleColormapPrefs();
gdk_rgb_init();
home = g_get_home_dir();
if ((char*)nsnull != home) {
path = g_strdup_printf("%s%c%s", home, G_DIR_SEPARATOR, ".gtkrc");
if ((char *)nsnull != path) {
gtk_rc_parse(path);
g_free(path);
}
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Spinup - do any preparation necessary for running a message loop
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsAppShell::Spinup()
{
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Spindown - do any cleanup necessary for finishing a message loop
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsAppShell::Spindown()
{
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Run
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsAppShell::Run()
{
NS_ADDREF_THIS();
nsresult rv = NS_OK;
nsIEventQueue * EQueue = nsnull;
// Get the event queue service
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
if (NS_FAILED(rv)) {
NS_ASSERTION("Could not obtain event queue service", PR_FALSE);
return rv;
}
#ifdef DEBUG
printf("Got the event queue from the service\n");
#endif /* DEBUG */
//Get the event queue for the thread.
rv = eventQService->GetThreadEventQueue(PR_GetCurrentThread(), &EQueue);
// If a queue already present use it.
if (EQueue)
goto done;
// Create the event queue for the thread
rv = eventQService->CreateThreadEventQueue();
if (NS_OK != rv) {
NS_ASSERTION("Could not create the thread event queue", PR_FALSE);
return rv;
}
//Get the event queue for the thread
rv = eventQService->GetThreadEventQueue(PR_GetCurrentThread(), &EQueue);
if (NS_OK != rv) {
NS_ASSERTION("Could not obtain the thread event queue", PR_FALSE);
return rv;
}
done:
#ifdef DEBUG
printf("Calling gdk_input_add with event queue\n");
#endif /* DEBUG */
// (has to be called explicitly for this, the primordial appshell, because
// of startup ordering problems.)
ListenToEventQueue(EQueue, PR_TRUE);
gtk_main();
NS_IF_RELEASE(EQueue);
Release();
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Exit a message handler loop
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsAppShell::Exit()
{
gtk_main_quit ();
return NS_OK;
}
// does nothing. used by xp code with non-gtk expectations.
// this method will be removed once xp eventloops are working.
NS_IMETHODIMP nsAppShell::GetNativeEvent(PRBool &aRealEvent, void *& aEvent)
{
aRealEvent = PR_FALSE;
aEvent = 0;
return NS_OK;
}
// simply executes one iteration of the event loop. used by xp code with
// non-gtk expectations.
// this method will be removed once xp eventloops are working.
NS_IMETHODIMP nsAppShell::DispatchNativeEvent(PRBool aRealEvent, void *aEvent)
{
g_main_iteration(PR_TRUE);
return NS_OK;
}
NS_IMETHODIMP nsAppShell::ListenToEventQueue(nsIEventQueue *aQueue,
PRBool aListen)
{
// tell gdk to listen to the event queue or not
gint queueToken;
if (aListen) {
queueToken = our_gdk_input_add(aQueue->GetEventQueueSelectFD(),
event_processor_callback,
aQueue, G_PRIORITY_DEFAULT_IDLE);
mEventQueueTokens->PushToken(aQueue, queueToken);
} else {
if (mEventQueueTokens->PopToken(aQueue, &queueToken))
gdk_input_remove(queueToken);
}
return NS_OK;
}

View File

@@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
@@ -20,31 +20,31 @@
* Contributor(s):
*/
#ifndef __nsIID_h
#define __nsIID_h
#ifndef nsAppShell_h__
#define nsAppShell_h__
#ifndef nsID_h__
#include "nsID.h"
#endif
#include "nsIAppShell.h"
#include <gtk/gtk.h>
/**
* An "interface id" which can be used to uniquely identify a given
* interface.
* Native GTK+ Application shell wrapper
*/
typedef nsID nsIID;
class EventQueueTokenQueue;
/**
* A macro shorthand for <tt>const nsIID&<tt>
*/
class nsAppShell : public nsIAppShell
{
public:
nsAppShell();
virtual ~nsAppShell();
#define REFNSIID const nsIID&
NS_DECL_ISUPPORTS
NS_DECL_NSIAPPSHELL
/**
* Define an IID (obsolete)
*/
#define NS_DEFINE_IID(_name, _iidspec) \
const nsIID _name = _iidspec
private:
nsDispatchListener *mDispatchListener;
EventQueueTokenQueue *mEventQueueTokens;
};
#endif // nsAppShell_h__
#endif /* __nsIID_h */

View File

@@ -0,0 +1,156 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsGtkEventHandler.h"
#include "nsButton.h"
#include "nsString.h"
NS_IMPL_ADDREF_INHERITED(nsButton, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsButton, nsWidget)
NS_IMPL_QUERY_INTERFACE2(nsButton, nsIButton, nsIWidget)
//-------------------------------------------------------------------------
//
// nsButton constructor
//
//-------------------------------------------------------------------------
nsButton::nsButton() : nsWidget() , nsIButton()
{
}
//-------------------------------------------------------------------------
//
// Create the native Button widget
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsButton::CreateNative(GtkObject *parentWindow)
{
#ifdef USE_SUPERWIN
if (!GDK_IS_SUPERWIN(parentWindow)) {
g_print("Damn, brother. That's not a superwin.\n");
return NS_ERROR_FAILURE;
}
GdkSuperWin *superwin = GDK_SUPERWIN(parentWindow);
mMozBox = gtk_mozbox_new(superwin->bin_window);
#endif
mWidget = gtk_button_new_with_label("");
gtk_widget_set_name(mWidget, "nsButton");
#ifdef USE_SUPERWIN
// make sure that we put the scrollbar into the mozbox
gtk_container_add(GTK_CONTAINER(mMozBox), mWidget);
#endif /* USE_SUPERWIN */
return NS_OK;
}
//-------------------------------------------------------------------------
//
// nsButton destructor
//
//-------------------------------------------------------------------------
nsButton::~nsButton()
{
}
void nsButton::InitCallbacks(char * aName)
{
InstallButtonPressSignal(mWidget);
InstallButtonReleaseSignal(mWidget);
InstallEnterNotifySignal(mWidget);
InstallLeaveNotifySignal(mWidget);
// These are needed so that the events will go to us and not our parent.
AddToEventMask(mWidget,
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_ENTER_NOTIFY_MASK |
GDK_EXPOSURE_MASK |
GDK_FOCUS_CHANGE_MASK |
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_POINTER_MOTION_MASK);
}
//-------------------------------------------------------------------------
//
// Set this button label
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsButton::SetLabel(const nsString& aText)
{
NS_ALLOC_STR_BUF(label, aText, 256);
gtk_label_set(GTK_LABEL(GTK_BIN (mWidget)->child), label);
NS_FREE_STR_BUF(label);
return (NS_OK);
}
//-------------------------------------------------------------------------
//
// Get this button label
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsButton::GetLabel(nsString& aBuffer)
{
char * text;
gtk_label_get(GTK_LABEL(GTK_BIN (mWidget)->child), &text);
aBuffer.SetLength(0);
aBuffer.Append(text);
return (NS_OK);
}
//-------------------------------------------------------------------------
//
// set font for button
//
//-------------------------------------------------------------------------
/* virtual */
void nsButton::SetFontNative(GdkFont *aFont)
{
GtkStyle *style = gtk_style_copy(GTK_BIN (mWidget)->child->style);
// gtk_style_copy ups the ref count of the font
gdk_font_unref (style->font);
style->font = aFont;
gdk_font_ref(style->font);
gtk_widget_set_style(GTK_BIN (mWidget)->child, style);
gtk_style_unref(style);
}

View File

@@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsButton_h__
#define nsButton_h__
#include "nsWidget.h"
#include "nsIButton.h"
/**
* Native GTK+ button wrapper
*/
class nsButton : public nsWidget,
public nsIButton
{
public:
nsButton();
virtual ~nsButton();
NS_DECL_ISUPPORTS_INHERITED
// nsIButton part
NS_IMETHOD SetLabel(const nsString& aText);
NS_IMETHOD GetLabel(nsString& aBuffer);
virtual void SetFontNative(GdkFont *aFont);
protected:
NS_METHOD CreateNative(GtkObject *parentWindow);
virtual void InitCallbacks(char * aName = nsnull);
};
#endif // nsButton_h__

View File

@@ -0,0 +1,250 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsCheckButton.h"
#include "nsString.h"
NS_IMPL_ADDREF_INHERITED(nsCheckButton, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsCheckButton, nsWidget)
NS_IMPL_QUERY_INTERFACE2(nsCheckButton, nsICheckButton, nsIWidget)
//-------------------------------------------------------------------------
//
// nsCheckButton constructor
//
//-------------------------------------------------------------------------
nsCheckButton::nsCheckButton() : nsWidget() , nsICheckButton()
{
NS_INIT_REFCNT();
mLabel = nsnull;
mCheckButton = nsnull;
mState = PR_FALSE;
}
//-------------------------------------------------------------------------
//
// nsCheckButton destructor
//
//-------------------------------------------------------------------------
nsCheckButton::~nsCheckButton()
{
}
void
nsCheckButton::OnDestroySignal(GtkWidget* aGtkWidget)
{
if (aGtkWidget == mCheckButton) {
mCheckButton = nsnull;
}
else if (aGtkWidget == mLabel) {
mLabel = nsnull;
}
else {
nsWidget::OnDestroySignal(aGtkWidget);
}
}
//-------------------------------------------------------------------------
//
// Create the native CheckButton widget
//
//-------------------------------------------------------------------------
NS_METHOD nsCheckButton::CreateNative(GtkObject *parentWindow)
{
mWidget = gtk_event_box_new();
mCheckButton = gtk_check_button_new();
gtk_container_add(GTK_CONTAINER(mWidget), mCheckButton);
gtk_widget_show(mCheckButton);
gtk_widget_set_name(mWidget, "nsCheckButton");
return NS_OK;
}
void nsCheckButton::InitCallbacks(char * aName)
{
InstallButtonPressSignal(mCheckButton);
InstallButtonReleaseSignal(mCheckButton);
InstallEnterNotifySignal(mWidget);
InstallLeaveNotifySignal(mWidget);
// These are needed so that the events will go to us and not our parent.
AddToEventMask(mWidget,
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_ENTER_NOTIFY_MASK |
GDK_EXPOSURE_MASK |
GDK_FOCUS_CHANGE_MASK |
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_POINTER_MOTION_MASK);
// Add in destroy callback
gtk_signal_connect(GTK_OBJECT(mCheckButton),
"destroy",
GTK_SIGNAL_FUNC(DestroySignal),
this);
InstallSignal((GtkWidget *)mCheckButton,
(gchar *)"toggled",
GTK_SIGNAL_FUNC(nsCheckButton::ToggledSignal));
}
//-------------------------------------------------------------------------
//
// Set this button label
//
//-------------------------------------------------------------------------
NS_METHOD nsCheckButton::SetState(const PRBool aState)
{
mState = aState;
if (mWidget && mCheckButton)
{
GtkToggleButton * item = GTK_TOGGLE_BUTTON(mCheckButton);
item->active = (gboolean) mState;
gtk_widget_queue_draw(GTK_WIDGET(item));
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set this button label
//
//-------------------------------------------------------------------------
NS_METHOD nsCheckButton::GetState(PRBool& aState)
{
aState = mState;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set this Checkbox label
//
//-------------------------------------------------------------------------
NS_METHOD nsCheckButton::SetLabel(const nsString& aText)
{
if (mWidget) {
NS_ALLOC_STR_BUF(label, aText, 256);
if (mLabel) {
gtk_label_set(GTK_LABEL(mLabel), label);
} else {
mLabel = gtk_label_new(label);
gtk_misc_set_alignment (GTK_MISC (mLabel), 0.0, 0.5);
gtk_container_add(GTK_CONTAINER(mCheckButton), mLabel);
gtk_widget_show(mLabel);
gtk_signal_connect(GTK_OBJECT(mLabel),
"destroy",
GTK_SIGNAL_FUNC(DestroySignal),
this);
}
NS_FREE_STR_BUF(label);
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get this button label
//
//-------------------------------------------------------------------------
NS_METHOD nsCheckButton::GetLabel(nsString& aBuffer)
{
aBuffer.SetLength(0);
if (mWidget) {
char * text;
if (mLabel) {
gtk_label_get(GTK_LABEL(mLabel), &text);
aBuffer.Append(text);
}
}
return NS_OK;
}
/* virtual */ void
nsCheckButton::OnToggledSignal(const gboolean aState)
{
// Untoggle the sonofabitch
if (mWidget && mCheckButton)
{
GtkToggleButton * item = GTK_TOGGLE_BUTTON(mCheckButton);
item->active = !item->active;
gtk_widget_queue_draw(GTK_WIDGET(item));
}
}
//////////////////////////////////////////////////////////////////////
/* static */ gint
nsCheckButton::ToggledSignal(GtkWidget * aWidget,
gpointer aData)
{
NS_ASSERTION( nsnull != aWidget, "widget is null");
nsCheckButton * button = (nsCheckButton *) aData;
NS_ASSERTION( nsnull != button, "instance pointer is null");
button->OnToggledSignal(GTK_TOGGLE_BUTTON(aWidget)->active);
return PR_TRUE;
}
//////////////////////////////////////////////////////////////////////
// SetBackgroundColor for CheckButton
/*virtual*/
void nsCheckButton::SetBackgroundColorNative(GdkColor *aColorNor,
GdkColor *aColorBri,
GdkColor *aColorDark)
{
// use same style copy as SetFont
GtkStyle *style = gtk_style_copy(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0))->style);
style->bg[GTK_STATE_NORMAL]=*aColorNor;
// Mouse over button
style->bg[GTK_STATE_PRELIGHT]=*aColorBri;
// Button is down
style->bg[GTK_STATE_ACTIVE]=*aColorDark;
// other states too? (GTK_STATE_ACTIVE, GTK_STATE_PRELIGHT,
// GTK_STATE_SELECTED, GTK_STATE_INSENSITIVE)
gtk_widget_set_style(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0)), style);
// set style for eventbox too
gtk_widget_set_style(mWidget, style);
gtk_style_unref(style);
}

View File

@@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsCheckButton_h__
#define nsCheckButton_h__
#include "nsWidget.h"
#include "nsICheckButton.h"
/**
* Native GTK+ Checkbox wrapper
*/
class nsCheckButton : public nsWidget,
public nsICheckButton
{
public:
nsCheckButton();
virtual ~nsCheckButton();
NS_DECL_ISUPPORTS_INHERITED
// nsICheckButton part
NS_IMETHOD SetLabel(const nsString &aText);
NS_IMETHOD GetLabel(nsString &aBuffer);
NS_IMETHOD SetState(const PRBool aState);
NS_IMETHOD GetState(PRBool& aState);
virtual void OnToggledSignal(const gboolean aState);
protected:
NS_IMETHOD CreateNative(GtkObject *parentWindow);
virtual void InitCallbacks(char * aName = nsnull);
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
// Sets background for checkbutton
virtual void SetBackgroundColorNative(GdkColor *aColorNor,
GdkColor *aColorBri,
GdkColor *aColorDark);
GtkWidget *mLabel;
GtkWidget *mCheckButton;
// We need to maintain our own state to be in sync with the
// gecko check controlling frame.
PRBool mState;
private:
static gint ToggledSignal(GtkWidget * aWidget,
gpointer aData);
};
#endif // nsCheckButton_h__

View File

@@ -0,0 +1,872 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsClipboard.h"
#include "nsCOMPtr.h"
#include "nsISupportsArray.h"
#include "nsIClipboardOwner.h"
#include "nsITransferable.h" // kTextMime
#include "nsISupportsPrimitives.h"
#include "nsIWidget.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsWidgetsCID.h"
#include "nsXPIDLString.h"
#include "nsPrimitiveHelpers.h"
#include "nsVoidArray.h"
// The class statics:
GtkWidget* nsClipboard::sWidget = 0;
#if defined(DEBUG_mcafee) || defined(DEBUG_pavlov)
#define DEBUG_CLIPBOARD
#endif
enum {
TARGET_NONE,
TARGET_TEXT_PLAIN,
TARGET_TEXT_XIF,
TARGET_TEXT_UNICODE,
TARGET_TEXT_HTML,
TARGET_AOLMAIL,
TARGET_IMAGE_PNG,
TARGET_IMAGE_JPEG,
TARGET_IMAGE_GIF,
// compatibility types
TARGET_UTF8,
TARGET_UNKNOWN,
TARGET_LAST
};
static GdkAtom sSelTypes[TARGET_LAST];
//-------------------------------------------------------------------------
//
// nsClipboard constructor
//
//-------------------------------------------------------------------------
nsClipboard::nsClipboard() : nsBaseClipboard()
{
#ifdef DEBUG_CLIPBOARD
g_print("nsClipboard::nsClipboard()\n");
#endif /* DEBUG_CLIPBOARD */
//NS_INIT_REFCNT();
mIgnoreEmptyNotification = PR_FALSE;
mClipboardOwner = nsnull;
mTransferable = nsnull;
mSelectionData.data = nsnull;
mSelectionData.length = 0;
// initialize the widget, etc we're binding to
Init();
}
// XXX if GTK's internal code changes this isn't going to work
// copied from gtk code because it is a static function we can't get to it.
// need to bug owen taylor about getting this code public.
typedef struct _GtkSelectionTargetList GtkSelectionTargetList;
struct _GtkSelectionTargetList {
GdkAtom selection;
GtkTargetList *list;
};
static const char *gtk_selection_handler_key = "gtk-selection-handlers";
void __gtk_selection_target_list_remove (GtkWidget *widget)
{
GtkSelectionTargetList *sellist;
GList *tmp_list;
GList *lists;
lists = (GList*)gtk_object_get_data (GTK_OBJECT (widget), gtk_selection_handler_key);
tmp_list = lists;
while (tmp_list)
{
sellist = (GtkSelectionTargetList*)tmp_list->data;
gtk_target_list_unref (sellist->list);
g_free (sellist);
tmp_list = tmp_list->next;
}
g_list_free (lists);
gtk_object_set_data (GTK_OBJECT (widget), gtk_selection_handler_key, NULL);
}
//-------------------------------------------------------------------------
//
// nsClipboard destructor
//
//-------------------------------------------------------------------------
nsClipboard::~nsClipboard()
{
#ifdef DEBUG_CLIPBOARD
printf("nsClipboard::~nsClipboard()\n");
#endif /* DEBUG_CLIPBOARD */
// Remove all our event handlers:
if (sWidget &&
(gdk_selection_owner_get(GDK_SELECTION_PRIMARY) == sWidget->window))
gtk_selection_remove_all(sWidget);
// free the selection data, if any
if (mSelectionData.data != nsnull)
g_free(mSelectionData.data);
nsClipboard *cb = (nsClipboard*)gtk_object_get_data(GTK_OBJECT(sWidget), "cb");
if (cb != nsnull)
{
NS_RELEASE(cb);
gtk_object_remove_data(GTK_OBJECT(sWidget), "cb");
}
if (sWidget)
{
gtk_widget_destroy(sWidget);
sWidget = nsnull;
}
}
//
// GTK Weirdness!
// This is here in the hope of being able to call
// gtk_selection_add_targets(w, GDK_SELECTION_PRIMARY,
// targets,
// 1);
// instead of
// gtk_selection_add_target(sWidget,
// GDK_SELECTION_PRIMARY,
// GDK_SELECTION_TYPE_STRING,
// GDK_SELECTION_TYPE_STRING);
// but it turns out that this changes the whole gtk selection model;
// when calling add_targets copy uses selection_clear_event and the
// data structure needs to be filled in in a way that we haven't
// figured out; when using add_target copy uses selection_get and
// the data structure is already filled in as much as it needs to be.
// Some gtk internals wizard will need to solve this mystery before
// we can use add_targets().
//static GtkTargetEntry targets[] = {
// { "strings n stuff", GDK_SELECTION_TYPE_STRING, GDK_SELECTION_TYPE_STRING }
//};
//
//-------------------------------------------------------------------------
void nsClipboard::Init(void)
{
#ifdef DEBUG_CLIPBOARD
g_print("nsClipboard::Init\n");
#endif
sSelTypes[TARGET_NONE] = GDK_NONE;
sSelTypes[TARGET_TEXT_PLAIN] = gdk_atom_intern(kTextMime, FALSE);
sSelTypes[TARGET_TEXT_XIF] = gdk_atom_intern(kXIFMime, FALSE);
sSelTypes[TARGET_TEXT_UNICODE] = gdk_atom_intern(kUnicodeMime, FALSE);
sSelTypes[TARGET_UTF8] = gdk_atom_intern("UTF8", FALSE);
sSelTypes[TARGET_TEXT_HTML] = gdk_atom_intern(kHTMLMime, FALSE);
sSelTypes[TARGET_AOLMAIL] = gdk_atom_intern(kAOLMailMime, FALSE);
sSelTypes[TARGET_IMAGE_PNG] = gdk_atom_intern(kPNGImageMime, FALSE);
sSelTypes[TARGET_IMAGE_JPEG] = gdk_atom_intern(kJPEGImageMime, FALSE);
sSelTypes[TARGET_IMAGE_GIF] = gdk_atom_intern(kGIFImageMime, FALSE);
// compatibility with other apps
// create invisible widget to use for the clipboard
sWidget = gtk_invisible_new();
// add the clipboard pointer to the widget so we can get it.
gtk_object_set_data(GTK_OBJECT(sWidget), "cb", this);
NS_ADDREF_THIS();
// Handle selection requests if we called gtk_selection_add_target:
gtk_signal_connect(GTK_OBJECT(sWidget), "selection_get",
GTK_SIGNAL_FUNC(nsClipboard::SelectionGetCB),
nsnull);
// When someone else takes the selection away:
gtk_signal_connect(GTK_OBJECT(sWidget), "selection_clear_event",
GTK_SIGNAL_FUNC(nsClipboard::SelectionClearCB),
nsnull);
// Set up the paste handler:
gtk_signal_connect(GTK_OBJECT(sWidget), "selection_received",
GTK_SIGNAL_FUNC(nsClipboard::SelectionReceivedCB),
nsnull);
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsClipboard::SetNativeClipboardData()
{
mIgnoreEmptyNotification = PR_TRUE;
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::SetNativeClipboardData()\n");
#endif /* DEBUG_CLIPBOARD */
// make sure we have a good transferable
if (nsnull == mTransferable) {
printf("nsClipboard::SetNativeClipboardData(): no transferable!\n");
return NS_ERROR_FAILURE;
}
// are we already the owner?
if (gdk_selection_owner_get(GDK_SELECTION_PRIMARY) == sWidget->window)
{
// if so, clear all the targets
__gtk_selection_target_list_remove(sWidget);
// gtk_selection_remove_all(sWidget);
}
// we arn't already the owner, so we will become it
gint have_selection = gtk_selection_owner_set(sWidget,
GDK_SELECTION_PRIMARY,
GDK_CURRENT_TIME);
if (have_selection == 0)
return NS_ERROR_FAILURE;
// get flavor list that includes all flavors that can be written (including ones
// obtained through conversion)
nsCOMPtr<nsISupportsArray> flavorList;
nsresult errCode = mTransferable->FlavorsTransferableCanExport ( getter_AddRefs(flavorList) );
if ( NS_FAILED(errCode) )
return NS_ERROR_FAILURE;
PRUint32 cnt;
flavorList->Count(&cnt);
for ( PRUint32 i=0; i<cnt; ++i )
{
nsCOMPtr<nsISupports> genericFlavor;
flavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) );
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericFlavor) );
if ( currentFlavor ) {
nsXPIDLCString flavorStr;
currentFlavor->ToString(getter_Copies(flavorStr));
gint format = GetFormat(flavorStr);
// add these types as selection targets
RegisterFormat(format);
}
}
mIgnoreEmptyNotification = PR_FALSE;
return NS_OK;
}
void nsClipboard::AddTarget(GdkAtom aAtom)
{
gtk_selection_add_target(sWidget,
GDK_SELECTION_PRIMARY,
aAtom, aAtom);
}
gint nsClipboard::GetFormat(const char* aMimeStr)
{
gint type = TARGET_NONE;
nsCAutoString mimeStr ( CBufDescriptor(NS_CONST_CAST(char*,aMimeStr), PR_TRUE, PL_strlen(aMimeStr)+1) );
#ifdef DEBUG_CLIPBOARD
g_print(" nsClipboard::GetFormat(%s)\n", aMimeStr);
#endif
if (mimeStr.Equals(kTextMime)) {
type = TARGET_TEXT_PLAIN;
} else if (mimeStr.Equals("STRING")) {
type = TARGET_TEXT_PLAIN;
} else if (mimeStr.Equals(kXIFMime)) {
type = TARGET_TEXT_XIF;
} else if (mimeStr.Equals(kUnicodeMime)) {
type = TARGET_TEXT_UNICODE;
} else if (mimeStr.Equals(kHTMLMime)) {
type = TARGET_TEXT_HTML;
} else if (mimeStr.Equals(kAOLMailMime)) {
type = TARGET_AOLMAIL;
} else if (mimeStr.Equals(kPNGImageMime)) {
type = TARGET_IMAGE_PNG;
} else if (mimeStr.Equals(kJPEGImageMime)) {
type = TARGET_IMAGE_JPEG;
} else if (mimeStr.Equals(kGIFImageMime)) {
type = TARGET_IMAGE_GIF;
}
#ifdef WE_DO_DND
else if (mimeStr.Equals(kDropFilesMime)) {
format = CF_HDROP;
} else {
format = ::RegisterClipboardFormat(aMimeStr);
}
#endif
return type;
}
void nsClipboard::RegisterFormat(gint format)
{
#ifdef DEBUG_CLIPBOARD
g_print(" nsClipboard::RegisterFormat(%s)\n", gdk_atom_name(sSelTypes[format]));
#endif
/* when doing the selection_add_target, each case should have the same last parameter
which matches the case match */
switch(format)
{
case TARGET_TEXT_PLAIN:
// text/plain (default)
AddTarget(sSelTypes[format]);
// STRING (what X uses)
AddTarget(GDK_SELECTION_TYPE_STRING);
break;
case TARGET_TEXT_XIF:
// text/xif (default)
AddTarget(sSelTypes[format]);
break;
case TARGET_TEXT_UNICODE:
// text/unicode (default)
AddTarget(sSelTypes[format]);
// UTF8 (what X uses)
AddTarget(sSelTypes[TARGET_UTF8]);
break;
case TARGET_TEXT_HTML:
// text/html (default)
AddTarget(sSelTypes[format]);
break;
case TARGET_AOLMAIL:
// text/aolmail (default)
AddTarget(sSelTypes[format]);
break;
case TARGET_IMAGE_PNG:
// image/png (default)
AddTarget(sSelTypes[format]);
break;
case TARGET_IMAGE_JPEG:
// image/jpeg (default)
AddTarget(sSelTypes[format]);
break;
case TARGET_IMAGE_GIF:
// image/gif (default)
AddTarget(sSelTypes[format]);
break;
default:
// if we don't match something above, then just add it like its something we know about...
AddTarget(sSelTypes[format]);
}
}
PRBool nsClipboard::DoRealConvert(GdkAtom type)
{
#ifdef DEBUG_CLIPBOARD
g_print(" nsClipboard::DoRealConvert(%li)\n {\n", type);
#endif
int e = 0;
// Set a flag saying that we're blocking waiting for the callback:
mBlocking = PR_TRUE;
//
// ask X what kind of data we can get
//
#ifdef DEBUG_CLIPBOARD
g_print(" Doing real conversion of atom type '%s'\n", gdk_atom_name(type));
#endif
gtk_selection_convert(sWidget,
GDK_SELECTION_PRIMARY,
type,
GDK_CURRENT_TIME);
// Now we need to wait until the callback comes in ...
// i is in case we get a runaway (yuck).
#ifdef DEBUG_CLIPBOARD
printf(" Waiting for the callback... mBlocking = %d\n", mBlocking);
#endif /* DEBUG_CLIPBOARD */
for (e=0; mBlocking == PR_TRUE && e < 1000; ++e)
{
gtk_main_iteration_do(PR_TRUE);
}
#ifdef DEBUG_CLIPBOARD
g_print(" }\n");
#endif
if (mSelectionData.length > 0)
return PR_TRUE;
return PR_FALSE;
}
/* return PR_TRUE if we have converted or PR_FALSE if we havn't and need to keep being called */
PRBool nsClipboard::DoConvert(gint format)
{
#ifdef DEBUG_CLIPBOARD
g_print(" nsClipboard::DoConvert(%s)\n", gdk_atom_name(sSelTypes[format]));
#endif
/* when doing the selection_add_target, each case should have the same last parameter
which matches the case match */
PRBool r = PR_FALSE;
switch(format)
{
case TARGET_TEXT_PLAIN:
r = DoRealConvert(sSelTypes[format]);
if (r) return r;
r = DoRealConvert(GDK_SELECTION_TYPE_STRING);
if (r) return r;
break;
case TARGET_TEXT_XIF:
r = DoRealConvert(sSelTypes[format]);
if (r) return r;
break;
case TARGET_TEXT_UNICODE:
r = DoRealConvert(sSelTypes[format]);
if (r) return r;
r = DoRealConvert(sSelTypes[TARGET_UTF8]);
if (r) return r;
break;
case TARGET_TEXT_HTML:
r = DoRealConvert(sSelTypes[format]);
if (r) return r;
break;
case TARGET_AOLMAIL:
r = DoRealConvert(sSelTypes[format]);
if (r) return r;
break;
case TARGET_IMAGE_PNG:
r = DoRealConvert(sSelTypes[format]);
if (r) return r;
break;
case TARGET_IMAGE_JPEG:
r = DoRealConvert(sSelTypes[format]);
if (r) return r;
break;
case TARGET_IMAGE_GIF:
r = DoRealConvert(sSelTypes[format]);
if (r) return r;
break;
default:
g_print("DoConvert called with bogus format\n");
}
return r;
}
//-------------------------------------------------------------------------
//
// The blocking Paste routine
//
//-------------------------------------------------------------------------
NS_IMETHODIMP
nsClipboard::GetNativeClipboardData(nsITransferable * aTransferable)
{
#ifdef DEBUG_CLIPBOARD
printf("nsClipboard::GetNativeClipboardData()\n");
#endif /* DEBUG_CLIPBOARD */
// make sure we have a good transferable
if (nsnull == aTransferable) {
printf(" GetNativeClipboardData: Transferable is null!\n");
return NS_ERROR_FAILURE;
}
// get flavor list that includes all acceptable flavors (including ones obtained through
// conversion)
nsCOMPtr<nsISupportsArray> flavorList;
nsresult errCode = aTransferable->FlavorsTransferableCanImport ( getter_AddRefs(flavorList) );
if ( NS_FAILED(errCode) )
return NS_ERROR_FAILURE;
// Walk through flavors and see which flavor matches the one being pasted:
PRUint32 cnt;
flavorList->Count(&cnt);
nsCAutoString foundFlavor;
for ( PRUint32 i = 0; i < cnt; ++i ) {
nsCOMPtr<nsISupports> genericFlavor;
flavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) );
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericFlavor) );
if ( currentFlavor ) {
nsXPIDLCString flavorStr;
currentFlavor->ToString ( getter_Copies(flavorStr) );
gint format = GetFormat(flavorStr);
if (DoConvert(format)) {
foundFlavor = flavorStr;
break;
}
}
}
#ifdef DEBUG_CLIPBOARD
printf(" Got the callback: '%s', %d\n",
mSelectionData.data, mSelectionData.length);
#endif /* DEBUG_CLIPBOARD */
// We're back from the callback, no longer blocking:
mBlocking = PR_FALSE;
//
// Now we have data in mSelectionData.data.
// We just have to copy it to the transferable.
//
#if 0
// pinkerton - we have the flavor already from above, so we don't need
// to re-derrive it.
nsString *name = new nsString((const char*)gdk_atom_name(mSelectionData.type));
int format = GetFormat(*name);
df->SetString((const char*)gdk_atom_name(sSelTypes[format]));
#endif
nsCOMPtr<nsISupports> genericDataWrapper;
nsPrimitiveHelpers::CreatePrimitiveForData ( foundFlavor, mSelectionData.data, mSelectionData.length, getter_AddRefs(genericDataWrapper) );
aTransferable->SetTransferData(foundFlavor,
genericDataWrapper,
mSelectionData.length);
//delete name;
// transferable is now copying the data, so we can free it.
// g_free(mSelectionData.data);
mSelectionData.data = nsnull;
mSelectionData.length = 0;
return NS_OK;
}
/**
* Called when the data from a paste comes in (recieved from gdk_selection_convert)
*
* @param aWidget the widget
* @param aSelectionData gtk selection stuff
* @param aTime time the selection was requested
*/
void
nsClipboard::SelectionReceivedCB (GtkWidget *aWidget,
GtkSelectionData *aSelectionData,
guint aTime)
{
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::SelectionReceivedCB\n {\n");
#endif /* DEBUG_CLIPBOARD */
nsClipboard *cb =(nsClipboard *)gtk_object_get_data(GTK_OBJECT(aWidget),
"cb");
if (!cb)
{
g_print("no clipboard found.. this is bad.\n");
return;
}
cb->SelectionReceiver(aWidget, aSelectionData);
#ifdef DEBUG_CLIPBOARD
g_print(" }\n");
#endif
}
/**
* local method (called from nsClipboard::SelectionReceivedCB)
*
* @param aWidget the widget
* @param aSelectionData gtk selection stuff
*/
void
nsClipboard::SelectionReceiver (GtkWidget *aWidget,
GtkSelectionData *aSD)
{
gint type;
mBlocking = PR_FALSE;
if (aSD->length < 0)
{
printf(" Error retrieving selection: length was %d\n",
aSD->length);
return;
}
type = TARGET_NONE;
for (int i=0; i < TARGET_LAST; i++)
{
if (sSelTypes[i] == aSD->type)
{
type = i;
break;
}
}
switch (type)
{
case GDK_TARGET_STRING:
case TARGET_UTF8:
case TARGET_TEXT_PLAIN:
case TARGET_TEXT_XIF:
case TARGET_TEXT_UNICODE:
case TARGET_TEXT_HTML:
#ifdef DEBUG_CLIPBOARD
g_print(" Copying mSelectionData pointer -- ");
#endif
mSelectionData = *aSD;
mSelectionData.data = g_new(guchar, aSD->length + 1);
#ifdef DEBUG_CLIPBOARD
g_print(" Data = %s\n Length = %i\n", aSD->data, aSD->length);
#endif
memcpy(mSelectionData.data,
aSD->data,
aSD->length);
// Null terminate in case anyone cares,
// and so we can print the string for debugging:
mSelectionData.data[aSD->length] = '\0';
mSelectionData.length = aSD->length;
return;
default:
mSelectionData = *aSD;
mSelectionData.data = g_new(guchar, aSD->length + 1);
memcpy(mSelectionData.data,
aSD->data,
aSD->length);
mSelectionData.length = aSD->length;
return;
}
}
/**
* Some platforms support deferred notification for putting data on the clipboard
* This method forces the data onto the clipboard in its various formats
* This may be used if the application going away.
*
* @result NS_OK if successful.
*/
NS_IMETHODIMP nsClipboard::ForceDataToClipboard()
{
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::ForceDataToClipboard()\n");
#endif /* DEBUG_CLIPBOARD */
// make sure we have a good transferable
if (nsnull == mTransferable) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
nsClipboard::HasDataMatchingFlavors(nsISupportsArray* aFlavorList, PRBool * outResult)
{
*outResult = PR_TRUE; // say we always do.
return NS_OK;
}
/**
* This is the callback which is called when another app
* requests the selection.
*
* @param widget The widget
* @param aSelectionData Selection data
* @param info Value passed in from the callback init
* @param time Time when the selection request came in
*/
void nsClipboard::SelectionGetCB(GtkWidget *widget,
GtkSelectionData *aSelectionData,
guint aInfo,
guint aTime)
{
#ifdef DEBUG_CLIPBOARD
printf("nsClipboard::SelectionGetCB\n");
#endif /* DEBUG_CLIPBOARD */
nsClipboard *cb = (nsClipboard *)gtk_object_get_data(GTK_OBJECT(widget),
"cb");
void *clipboardData;
PRUint32 dataLength;
nsresult rv;
// Make sure we have a transferable:
if (!cb->mTransferable) {
printf("Clipboard has no transferable!\n");
return;
}
#ifdef DEBUG_CLIPBOARD
g_print(" aInfo == %d -", aInfo);
#endif
char* dataFlavor = nsnull;
// switch aInfo (atom) to our enum
int type = (int)aInfo;
for (int i=0; i < TARGET_LAST; i++)
{
if (sSelTypes[i] == aInfo)
{
type = i;
break;
}
}
switch(type)
{
case GDK_TARGET_STRING:
case TARGET_TEXT_PLAIN:
dataFlavor = kTextMime;
break;
case TARGET_TEXT_XIF:
dataFlavor = kXIFMime;
break;
case TARGET_TEXT_UNICODE:
case TARGET_UTF8:
dataFlavor = kUnicodeMime;
break;
case TARGET_TEXT_HTML:
dataFlavor = kHTMLMime;
break;
case TARGET_AOLMAIL:
dataFlavor = kAOLMailMime;
break;
case TARGET_IMAGE_PNG:
dataFlavor = kPNGImageMime;
break;
case TARGET_IMAGE_JPEG:
dataFlavor = kJPEGImageMime;
break;
case TARGET_IMAGE_GIF:
dataFlavor = kGIFImageMime;
break;
default:
{
/* handle outside things */
}
}
#ifdef DEBUG_CLIPBOARD
g_print("- aInfo is for %s\n", gdk_atom_name(aInfo));
#endif
// Get data out of transferable.
nsCOMPtr<nsISupports> genericDataWrapper;
rv = cb->mTransferable->GetTransferData(dataFlavor,
getter_AddRefs(genericDataWrapper),
&dataLength);
nsPrimitiveHelpers::CreateDataFromPrimitive ( dataFlavor, genericDataWrapper, &clipboardData, dataLength );
if (NS_SUCCEEDED(rv) && clipboardData && dataLength > 0) {
size_t size = 1;
// find the number of bytes in the data for the below thing
// size_t size = sizeof((void*)((unsigned char)clipboardData[0]));
// g_print("************ ***************** ******************* %i\n", size);
gtk_selection_data_set(aSelectionData,
aInfo, size*8,
(unsigned char *)clipboardData,
dataLength);
nsCRT::free ( NS_REINTERPRET_CAST(char*, clipboardData) );
}
else
printf("Transferable didn't support the data flavor\n");
}
/**
* Called when another app requests selection ownership
*
* @param aWidget the widget
* @param aEvent the GdkEvent for the selection
* @param aData value passed in from the callback init
*/
void nsClipboard::SelectionClearCB(GtkWidget *aWidget,
GdkEventSelection *aEvent,
gpointer aData)
{
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::SelectionClearCB\n");
#endif /* DEBUG_CLIPBOARD */
nsClipboard *cb = (nsClipboard *)gtk_object_get_data(GTK_OBJECT(aWidget),
"cb");
cb->EmptyClipboard();
}
/**
* The routine called when another app asks for the content of the selection
*
* @param aWidget the widget
* @param aSelectionData gtk selection stuff
* @param aData value passed in from the callback init
*/
void
nsClipboard::SelectionRequestCB (GtkWidget *aWidget,
GtkSelectionData *aSelectionData,
gpointer aData)
{
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::SelectionRequestCB\n");
#endif /* DEBUG_CLIPBOARD */
}
/**
* ...
*
* @param aWidget the widget
* @param aSelectionData gtk selection stuff
* @param aData value passed in from the callback init
*/
void
nsClipboard::SelectionNotifyCB (GtkWidget *aWidget,
GtkSelectionData *aSelectionData,
gpointer aData)
{
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::SelectionNotifyCB\n");
#endif /* DEBUG_CLIPBOARD */
}

View File

@@ -0,0 +1,132 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsClipboard_h__
#define nsClipboard_h__
#include "nsBaseClipboard.h"
#include <gtk/gtk.h>
#include <gtk/gtkinvisible.h>
class nsITransferable;
class nsIClipboardOwner;
class nsIWidget;
/**
* Native Gtk Clipboard wrapper
*/
class nsClipboard : public nsBaseClipboard
{
public:
nsClipboard();
virtual ~nsClipboard();
// nsIClipboard
NS_IMETHOD ForceDataToClipboard();
NS_IMETHOD HasDataMatchingFlavors(nsISupportsArray* aFlavorList, PRBool * outResult);
// invisible widget. also used by dragndrop
static GtkWidget *sWidget;
protected:
NS_IMETHOD SetNativeClipboardData();
NS_IMETHOD GetNativeClipboardData(nsITransferable * aTransferable);
PRBool mIgnoreEmptyNotification;
void AddTarget(GdkAtom aAtom);
gint GetFormat(const char* aMimeStr);
void RegisterFormat(gint format);
PRBool DoRealConvert(GdkAtom type);
PRBool DoConvert(gint format);
void Init(void);
// Used for communicating pasted data
// from the asynchronous X routines back to a blocking paste:
GtkSelectionData mSelectionData;
PRBool mBlocking;
void SelectionReceiver(GtkWidget *aWidget,
GtkSelectionData *aSD);
/**
* This is the callback which is called when another app
* requests the selection.
*
* @param widget The widget
* @param aSelectionData Selection data
* @param info Value passed in from the callback init
* @param time Time when the selection request came in
*/
static void SelectionGetCB(GtkWidget *aWidget,
GtkSelectionData *aSelectionData,
guint /*info*/,
guint /*time*/);
/**
* Called when another app requests selection ownership
*
* @param aWidget the widget
* @param aEvent the GdkEvent for the selection
* @param aData value passed in from the callback init
*/
static void SelectionClearCB(GtkWidget *aWidget,
GdkEventSelection *aEvent,
gpointer aData);
/**
* The routine called when another app asks for the content of the selection
*
* @param aWidget the widget
* @param aSelectionData gtk selection stuff
* @param aData value passed in from the callback init
*/
static void SelectionRequestCB(GtkWidget *aWidget,
GtkSelectionData *aSelectionData,
gpointer data);
/**
* Called when the data from a paste comes in
*
* @param aWidget the widget
* @param aSelectionData gtk selection stuff
* @param aTime time the selection was requested
*/
static void SelectionReceivedCB(GtkWidget *aWidget,
GtkSelectionData *aSelectionData,
guint aTime);
static void SelectionNotifyCB(GtkWidget *aWidget,
GtkSelectionData *aSelectionData,
gpointer aData);
};
#endif // nsClipboard_h__

View File

@@ -0,0 +1,357 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsComboBox.h"
#include "nsGUIEvent.h"
#include "nsString.h"
#define DBG 0
#define INITIAL_MAX_ITEMS 128
#define ITEMS_GROWSIZE 128
NS_IMPL_ADDREF_INHERITED(nsComboBox, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsComboBox, nsWidget)
NS_IMPL_QUERY_INTERFACE3(nsComboBox, nsIComboBox, nsIListWidget, nsIWidget)
//-------------------------------------------------------------------------
//
// nsComboBox constructor
//
//-------------------------------------------------------------------------
nsComboBox::nsComboBox() : nsWidget(), nsIListWidget(), nsIComboBox()
{
NS_INIT_REFCNT();
mMultiSelect = PR_FALSE;
mItems = nsnull;
mNumItems = 0;
}
//-------------------------------------------------------------------------
//
// nsComboBox:: destructor
//
//-------------------------------------------------------------------------
nsComboBox::~nsComboBox()
{
if (mItems) {
for (GList *items = mItems; items; items = (GList*) g_list_next(items)){
g_free(items->data);
}
g_list_free(mItems);
}
gtk_widget_destroy(mCombo);
}
void nsComboBox::InitCallbacks(char * aName)
{
InstallButtonPressSignal(mWidget);
InstallButtonReleaseSignal(mWidget);
InstallEnterNotifySignal(mWidget);
InstallLeaveNotifySignal(mWidget);
// These are needed so that the events will go to us and not our parent.
AddToEventMask(mWidget,
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_ENTER_NOTIFY_MASK |
GDK_EXPOSURE_MASK |
GDK_FOCUS_CHANGE_MASK |
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_POINTER_MOTION_MASK);
}
//-------------------------------------------------------------------------
//
// initializer
//
//-------------------------------------------------------------------------
NS_METHOD nsComboBox::SetMultipleSelection(PRBool aMultipleSelections)
{
mMultiSelect = aMultipleSelections;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// AddItemAt
//
//-------------------------------------------------------------------------
NS_METHOD nsComboBox::AddItemAt(nsString &aItem, PRInt32 aPosition)
{
NS_ALLOC_STR_BUF(val, aItem, 256);
mItems = g_list_insert( mItems, g_strdup(val), aPosition );
mNumItems++;
if (mCombo) {
gtk_combo_set_popdown_strings( GTK_COMBO( mCombo ), mItems );
}
NS_FREE_STR_BUF(val);
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Finds an item at a postion
//
//-------------------------------------------------------------------------
PRInt32 nsComboBox::FindItem(nsString &aItem, PRInt32 aStartPos)
{
NS_ALLOC_STR_BUF(val, aItem, 256);
int i;
PRInt32 inx = -1;
GList *items = g_list_nth(mItems, aStartPos);
for(i=0; items != NULL; items = (GList *) g_list_next(items), i++ )
{
if(!strcmp(val, (gchar *) items->data))
{
inx = i;
break;
}
}
NS_FREE_STR_BUF(val);
return inx;
}
//-------------------------------------------------------------------------
//
// CountItems - Get Item Count
//
//-------------------------------------------------------------------------
PRInt32 nsComboBox::GetItemCount()
{
return (PRInt32)mNumItems;
}
//-------------------------------------------------------------------------
//
// Removes an Item at a specified location
//
//-------------------------------------------------------------------------
PRBool nsComboBox::RemoveItemAt(PRInt32 aPosition)
{
if (aPosition >= 0 && aPosition < mNumItems) {
g_free(g_list_nth(mItems, aPosition)->data);
mItems = g_list_remove_link(mItems, g_list_nth(mItems, aPosition));
mNumItems--;
if (mCombo) {
gtk_combo_set_popdown_strings(GTK_COMBO( mCombo ), mItems);
}
return PR_TRUE;
}
else
return PR_FALSE;
}
//-------------------------------------------------------------------------
//
// Removes an Item at a specified location
//
//-------------------------------------------------------------------------
PRBool nsComboBox::GetItemAt(nsString& anItem, PRInt32 aPosition)
{
if (aPosition >= 0 && aPosition < mNumItems) {
anItem = (gchar *) g_list_nth(mItems, aPosition)->data;
return PR_TRUE;
}
return PR_FALSE;
}
//-------------------------------------------------------------------------
//
// Gets the selected of selected item
//
//-------------------------------------------------------------------------
NS_METHOD nsComboBox::GetSelectedItem(nsString& aItem)
{
aItem.Truncate();
if (mCombo) {
aItem = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(mCombo)->entry));
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Gets the list of selected otems
//
//-------------------------------------------------------------------------
PRInt32 nsComboBox::GetSelectedIndex()
{
nsString nsstring;
GetSelectedItem(nsstring);
return FindItem(nsstring, 0);
}
//-------------------------------------------------------------------------
//
// SelectItem
//
//-------------------------------------------------------------------------
NS_METHOD nsComboBox::SelectItem(PRInt32 aPosition)
{
GList *pos;
if (!mItems)
return NS_ERROR_FAILURE;
pos = g_list_nth(mItems, aPosition);
if (!pos)
return NS_ERROR_FAILURE;
if (mCombo) {
gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(mCombo)->entry),
(gchar *) pos->data);
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// GetSelectedCount
//
//-------------------------------------------------------------------------
PRInt32 nsComboBox::GetSelectedCount()
{
if (!mMultiSelect) {
PRInt32 inx = GetSelectedIndex();
return (inx == -1? 0 : 1);
} else {
return 0;
}
}
//-------------------------------------------------------------------------
//
// GetSelectedIndices
//
//-------------------------------------------------------------------------
NS_METHOD nsComboBox::GetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize)
{
// this is an error
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
//
// Deselect
//
//-------------------------------------------------------------------------
NS_METHOD nsComboBox::Deselect()
{
if (mMultiSelect) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Create the native GtkCombo widget
//
//-------------------------------------------------------------------------
NS_METHOD nsComboBox::CreateNative(GtkObject *parentWindow)
{
mWidget = ::gtk_event_box_new();
::gtk_widget_set_name(mWidget, "nsComboBox");
mCombo = ::gtk_combo_new();
gtk_widget_show(mCombo);
/* make the stuff uneditable */
gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(mCombo)->entry), PR_FALSE);
gtk_signal_connect(GTK_OBJECT(mCombo),
"destroy",
GTK_SIGNAL_FUNC(DestroySignal),
this);
gtk_signal_connect(GTK_OBJECT(GTK_COMBO(mCombo)->popwin),
"unmap",
GTK_SIGNAL_FUNC(UnmapSignal),
this);
gtk_container_add(GTK_CONTAINER(mWidget), mCombo);
return NS_OK;
}
void
nsComboBox::OnDestroySignal(GtkWidget* aGtkWidget)
{
if (aGtkWidget == mCombo) {
mCombo = nsnull;
}
else {
nsWidget::OnDestroySignal(aGtkWidget);
}
}
gint
nsComboBox::UnmapSignal(GtkWidget* aGtkWidget, nsComboBox* aCombo)
{
if (!aCombo) return PR_FALSE;
aCombo->OnUnmapSignal(aGtkWidget);
return PR_TRUE;
}
void
nsComboBox::OnUnmapSignal(GtkWidget * aWidget)
{
if (!aWidget) return;
// Generate a NS_CONTROL_CHANGE event and send it to the frame
nsGUIEvent event;
event.eventStructType = NS_GUI_EVENT;
nsPoint point(0,0);
InitEvent(event, NS_CONTROL_CHANGE, &point);
DispatchWindowEvent(&event);
}
//-------------------------------------------------------------------------
//
// Get handle for style
//
//-------------------------------------------------------------------------
/*virtual*/
void nsComboBox::SetFontNative(GdkFont *aFont)
{
GtkStyle *style = gtk_style_copy(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0))->style);
// gtk_style_copy ups the ref count of the font
gdk_font_unref (style->font);
style->font = aFont;
gdk_font_ref(style->font);
gtk_widget_set_style(GTK_BIN (mWidget)->child, style);
gtk_style_unref(style);
}

View File

@@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsComboBox_h__
#define nsComboBox_h__
#include "nsWidget.h"
#include "nsIComboBox.h"
/**
* Native GTK+ Listbox wrapper
*/
class nsComboBox : public nsWidget,
public nsIListWidget,
public nsIComboBox
{
public:
nsComboBox();
virtual ~nsComboBox();
NS_DECL_ISUPPORTS_INHERITED
// nsIComboBox interface
NS_IMETHOD AddItemAt(nsString &aItem, PRInt32 aPosition);
virtual PRInt32 FindItem(nsString &aItem, PRInt32 aStartPos);
virtual PRInt32 GetItemCount();
virtual PRBool RemoveItemAt(PRInt32 aPosition);
virtual PRBool GetItemAt(nsString& anItem, PRInt32 aPosition);
NS_IMETHOD GetSelectedItem(nsString& aItem);
virtual PRInt32 GetSelectedIndex();
NS_IMETHOD SelectItem(PRInt32 aPosition);
NS_IMETHOD Deselect() ;
// nsIComboBox interface
NS_IMETHOD SetMultipleSelection(PRBool aMultipleSelections);
PRInt32 GetSelectedCount();
NS_IMETHOD GetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize);
virtual void SetFontNative(GdkFont *aFont);
protected:
NS_IMETHOD CreateNative(GtkObject *parentWindow);
virtual void InitCallbacks(char * aName = nsnull);
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
virtual void OnUnmapSignal(GtkWidget* aWidget);
static gint UnmapSignal(GtkWidget* aGtkWidget, nsComboBox* aCombo);
GtkWidget *mCombo; /* workaround for gtkcombo bug */
GList *mItems;
PRBool mMultiSelect;
int mNumItems;
};
#endif // nsComboBox_h__

View File

@@ -0,0 +1,744 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsContextMenu.h"
#include "nsIComponentManager.h"
#include "nsIDOMElement.h"
#include "nsIDOMNode.h"
#include "nsIMenuBar.h"
#include "nsIMenuItem.h"
#include "nsIMenuListener.h"
#include "nsString.h"
#include "nsGtkEventHandler.h"
#include "nsCOMPtr.h"
#include "nsWidgetsCID.h"
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
static NS_DEFINE_CID(kMenuItemCID, NS_MENUITEM_CID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
//-------------------------------------------------------------------------
nsresult nsContextMenu::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
*aInstancePtr = NULL;
if (aIID.Equals(nsIMenu::GetIID())) {
*aInstancePtr = (void*)(nsIMenu*) this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*)(nsISupports*)(nsIMenu*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(nsIMenuListener::GetIID())) {
*aInstancePtr = (void*)(nsIMenuListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
//-------------------------------------------------------------------------
NS_IMPL_ADDREF(nsContextMenu)
NS_IMPL_RELEASE(nsContextMenu)
//-------------------------------------------------------------------------
//
// nsContextMenu constructor
//
//-------------------------------------------------------------------------
nsContextMenu::nsContextMenu()
{
NS_INIT_REFCNT();
mNumMenuItems = 0;
mMenu = nsnull;
mParent = nsnull;
mListener = nsnull;
mConstructCalled = PR_FALSE;
mDOMNode = nsnull;
mWebShell = nsnull;
mDOMElement = nsnull;
mAlignment = "topleft";
mAnchorAlignment = "none";
}
//-------------------------------------------------------------------------
//
// nsContextMenu destructor
//
//-------------------------------------------------------------------------
nsContextMenu::~nsContextMenu()
{
}
//-------------------------------------------------------------------------
//
// Create the proper widget
//
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::Create(nsISupports *aParent,
const nsString& anAlignment,
const nsString& anAnchorAlignment)
{
if(aParent)
{
nsIWidget *parent = nsnull;
aParent->QueryInterface(nsIWidget::GetIID(), (void**) &parent);
if(parent)
{
mParent = parent;
NS_RELEASE(parent);
}
}
mAlignment = anAlignment;
mAnchorAlignment = anAnchorAlignment;
mMenu = gtk_menu_new();
gtk_signal_connect (GTK_OBJECT (mMenu), "map",
GTK_SIGNAL_FUNC(menu_map_handler),
this);
gtk_signal_connect (GTK_OBJECT (mMenu), "unmap",
GTK_SIGNAL_FUNC(menu_unmap_handler),
this);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::GetParent(nsISupports*& aParent)
{
aParent = nsnull;
if (nsnull != mParent) {
return mParent->QueryInterface(kISupportsIID,
(void**)&aParent);
}
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::AddItem(nsISupports * aItem)
{
if(aItem)
{
nsIMenuItem * menuitem = nsnull;
aItem->QueryInterface(nsIMenuItem::GetIID(),
(void**)&menuitem);
if(menuitem)
{
AddMenuItem(menuitem); // nsMenu now owns this
NS_RELEASE(menuitem);
}
else
{
nsIMenu * menu = nsnull;
aItem->QueryInterface(nsIMenu::GetIID(),
(void**)&menu);
if(menu)
{
AddMenu(menu); // nsMenu now owns this
NS_RELEASE(menu);
}
}
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::AddMenuItem(nsIMenuItem * aMenuItem)
{
GtkWidget *widget;
void *voidData;
aMenuItem->GetNativeData(voidData);
widget = GTK_WIDGET(voidData);
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
// XXX add aMenuItem to internal data structor list
// Need to be adding an nsISupports *, not nsIMenuItem *
nsISupports * supports = nsnull;
aMenuItem->QueryInterface(kISupportsIID,
(void**)&supports);
{
mMenuItemVoidArray.AppendElement(supports);
mNumMenuItems++;
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::AddMenu(nsIMenu * aMenu)
{
nsString Label;
GtkWidget *newmenu=nsnull;
char *labelStr;
void *voidData=NULL;
aMenu->GetLabel(Label);
labelStr = Label.ToNewCString();
// Create nsMenuItem
nsIMenuItem * pnsMenuItem = nsnull;
nsresult rv = nsComponentManager::CreateInstance(kMenuItemCID,
nsnull,
nsIMenuItem::GetIID(),
(void**)&pnsMenuItem);
if (NS_OK == rv) {
nsISupports * supports = nsnull;
QueryInterface(kISupportsIID, (void**) &supports);
pnsMenuItem->Create(supports, labelStr, PR_FALSE); //PR_TRUE);
NS_RELEASE(supports);
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
AddItem(supports); // Parent should now own menu item
NS_RELEASE(supports);
void * menuitem = nsnull;
pnsMenuItem->GetNativeData(menuitem);
voidData = NULL;
aMenu->GetNativeData(&voidData);
newmenu = GTK_WIDGET(voidData);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), newmenu);
NS_RELEASE(pnsMenuItem);
}
nsCRT::free(labelStr);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::AddSeparator()
{
// Create nsMenuItem
nsIMenuItem * pnsMenuItem = nsnull;
nsresult rv = nsComponentManager::CreateInstance(
kMenuItemCID, nsnull, nsIMenuItem::GetIID(), (void**)&pnsMenuItem);
if (NS_OK == rv) {
nsString tmp = "separator";
nsISupports * supports = nsnull;
QueryInterface(kISupportsIID, (void**) &supports);
pnsMenuItem->Create(supports, tmp, PR_TRUE);
NS_RELEASE(supports);
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
AddItem(supports); // Parent should now own menu item
NS_RELEASE(supports);
NS_RELEASE(pnsMenuItem);
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::GetItemCount(PRUint32 &aCount)
{
// this should be right.. does it need to be +1 ?
aCount = g_list_length(GTK_MENU_SHELL(mMenu)->children);
//g_print("nsMenu::GetItemCount = %i\n", aCount);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::GetItemAt(const PRUint32 aCount, nsISupports *& aMenuItem)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::InsertItemAt(const PRUint32 aCount, nsISupports * aMenuItem)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::InsertSeparator(const PRUint32 aCount)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::RemoveItem(const PRUint32 aCount)
{
#if 0
// this may work here better than Removeall(), but i'm not sure how to test this one
nsISupports *item = mMenuItemVoidArray[aPos];
delete item;
mMenuItemVoidArray.RemoveElementAt(aPos);
#endif
/*
gtk_menu_shell_remove (GTK_MENU_SHELL (mMenu), item);
nsCRT::free(labelStr);
voidData = NULL;
aMenu->GetNativeData(&voidData);
newmenu = GTK_WIDGET(voidData);
gtk_menu_item_remove_submenu (GTK_MENU_ITEM (item));
*/
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::RemoveAll()
{
//g_print("nsMenu::RemoveAll()\n");
#undef DEBUG_pavlov
#ifdef DEBUG_pavlov
// this doesn't work quite right, but this is about all that should really be needed
int i=0;
nsIMenu *menu = nsnull;
nsIMenuItem *menuitem = nsnull;
nsISupports *item = nsnull;
for (i=mMenuItemVoidArray.Count(); i>0; i--)
{
item = (nsISupports*)mMenuItemVoidArray[i-1];
if(nsnull != item)
{
if (NS_OK == item->QueryInterface(nsIMenuItem::GetIID(), (void**)&menuitem))
{
// we do this twice because we have to do it once for QueryInterface,
// then we want to get rid of it.
// g_print("remove nsMenuItem\n");
NS_RELEASE(menuitem);
NS_RELEASE(item);
menuitem = nsnull;
} else if (NS_OK == item->QueryInterface(nsIMenu::GetIID(), (void**)&menu)) {
#ifdef NOISY_MENUS
g_print("remove nsMenu\n");
#endif
NS_RELEASE(menu);
NS_RELEASE(item);
menu = nsnull;
}
// mMenuItemVoidArray.RemoveElementAt(i-1);
}
}
mMenuItemVoidArray.Clear();
return NS_OK;
#else
for (int i = mMenuItemVoidArray.Count(); i > 0; i--) {
if(nsnull != mMenuItemVoidArray[i-1]) {
nsIMenuItem * menuitem = nsnull;
((nsISupports*)mMenuItemVoidArray[i-1])->QueryInterface(nsIMenuItem::GetIID(),
(void**)&menuitem);
if(menuitem) {
void *gtkmenuitem = nsnull;
menuitem->GetNativeData(gtkmenuitem);
if (gtkmenuitem) {
gtk_widget_ref(GTK_WIDGET(gtkmenuitem));
//gtk_widget_destroy(GTK_WIDGET(gtkmenuitem));
g_print("%p, %p\n",
GTK_WIDGET(GTK_CONTAINER(GTK_MENU_SHELL(GTK_MENU(mMenu)))),
GTK_WIDGET(GTK_WIDGET(gtkmenuitem)->parent));
gtk_container_remove(GTK_CONTAINER(GTK_MENU_SHELL(GTK_MENU(mMenu))),
GTK_WIDGET(gtkmenuitem));
}
} else {
nsIMenu * menu= nsnull;
((nsISupports*)mMenuItemVoidArray[i-1])->QueryInterface(nsIMenu::GetIID(),
(void**)&menu);
if(menu)
{
void * gtkmenu = nsnull;
menu->GetNativeData(&gtkmenu);
if(gtkmenu){
g_print("nsMenu::RemoveAll() trying to remove nsMenu");
//gtk_menu_item_remove_submenu (GTK_MENU_ITEM (item));
}
}
}
}
}
//g_print("end RemoveAll\n");
return NS_OK;
#endif
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::GetNativeData(void ** aData)
{
*aData = (void *)mMenu;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::AddMenuListener(nsIMenuListener * aMenuListener)
{
mListener = aMenuListener;
NS_ADDREF(mListener);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::RemoveMenuListener(nsIMenuListener * aMenuListener)
{
if (aMenuListener == mListener) {
NS_IF_RELEASE(mListener);
}
return NS_OK;
}
//-------------------------------------------------------------------------
// nsIMenuListener interface
//-------------------------------------------------------------------------
nsEventStatus nsContextMenu::MenuItemSelected(const nsMenuEvent & aMenuEvent)
{
if (nsnull != mListener) {
mListener->MenuSelected(aMenuEvent);
}
return nsEventStatus_eIgnore;
}
void menu_popup_position(GtkMenu *menu,
gint *x,
gint *y,
gpointer data)
{
nsContextMenu *cm = (nsContextMenu*)data;
*x = cm->GetX();
*y = cm->GetY();
}
nsEventStatus nsContextMenu::MenuSelected(const nsMenuEvent & aMenuEvent)
{
MenuConstruct(aMenuEvent,
mParent,
mDOMNode,
mWebShell);
//GtkWidget *parent = GTK_WIDGET(mParent->GetNativeData(NS_NATIVE_WIDGET));
gtk_menu_popup (GTK_MENU(mMenu),
(GtkWidget*)nsnull, (GtkWidget*)nsnull,
menu_popup_position,
this, 1, GDK_CURRENT_TIME);
/*
if (nsnull != mListener) {
mListener->MenuSelected(aMenuEvent);
}
*/
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsIMenuItem * nsContextMenu::FindMenuItem(nsIContextMenu * aMenu, PRUint32 aId)
{
return nsnull;
}
//-------------------------------------------------------------------------
nsEventStatus nsContextMenu::MenuDeselected(const nsMenuEvent & aMenuEvent)
{
if (nsnull != mListener) {
mListener->MenuDeselected(aMenuEvent);
}
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsContextMenu::MenuConstruct(const nsMenuEvent &aMenuEvent,
nsIWidget *aParentWindow,
void *menuNode,
void *aWebShell)
{
//g_print("nsMenu::MenuConstruct called \n");
if(menuNode){
SetDOMNode((nsIDOMNode*)menuNode);
}
if(!aWebShell){
aWebShell = mWebShell;
}
// First open the menu.
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
if (domElement)
domElement->SetAttribute("open", "true");
// Begin menuitem inner loop
nsCOMPtr<nsIDOMNode> menuitemNode;
((nsIDOMNode*)mDOMNode)->GetFirstChild(getter_AddRefs(menuitemNode));
unsigned short menuIndex = 0;
while (menuitemNode) {
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
if (menuitemElement) {
nsString menuitemNodeType;
nsString menuitemName;
menuitemElement->GetNodeName(menuitemNodeType);
if (menuitemNodeType.Equals("menuitem")) {
// LoadMenuItem
LoadMenuItem(this,
menuitemElement,
menuitemNode,
menuIndex,
(nsIWebShell*)aWebShell);
} else if (menuitemNodeType.Equals("separator")) {
AddSeparator();
} else if (menuitemNodeType.Equals("menu")) {
// Load a submenu
LoadSubMenu(this, menuitemElement, menuitemNode);
}
}
++menuIndex;
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
} // end menu item innner loop
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsContextMenu::MenuDestruct(const nsMenuEvent & aMenuEvent)
{
// Close the node.
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
if (domElement)
domElement->RemoveAttribute("open");
//g_print("nsMenu::MenuDestruct called \n");
mConstructCalled = PR_FALSE;
RemoveAll();
return nsEventStatus_eIgnore;
}
//----------------------------------------
void nsContextMenu::LoadMenuItem(nsIMenu *pParentMenu,
nsIDOMElement *menuitemElement,
nsIDOMNode *menuitemNode,
unsigned short menuitemIndex,
nsIWebShell *aWebShell)
{
static const char* NS_STRING_TRUE = "true";
nsString disabled;
nsString menuitemName;
nsString menuitemCmd;
menuitemElement->GetAttribute(nsAutoString("disabled"), disabled);
menuitemElement->GetAttribute(nsAutoString("name"), menuitemName);
menuitemElement->GetAttribute(nsAutoString("cmd"), menuitemCmd);
// Create nsMenuItem
nsIMenuItem * pnsMenuItem = nsnull;
nsresult rv = nsComponentManager::CreateInstance(kMenuItemCID,
nsnull,
nsIMenuItem::GetIID(),
(void**)&pnsMenuItem);
if (NS_OK == rv) {
pnsMenuItem->Create(pParentMenu, menuitemName, PR_FALSE);
nsISupports * supports = nsnull;
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
pParentMenu->AddItem(supports); // Parent should now own menu item
NS_RELEASE(supports);
if(disabled == NS_STRING_TRUE) {
pnsMenuItem->SetEnabled(PR_FALSE);
}
// Create MenuDelegate - this is the intermediator inbetween
// the DOM node and the nsIMenuItem
// The nsWebShellWindow wacthes for Document changes and then notifies the
// the appropriate nsMenuDelegate object
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(menuitemNode));
if (!domElement) {
//return NS_ERROR_FAILURE;
return;
}
nsAutoString cmdAtom("onclick");
nsString cmdName;
domElement->GetAttribute(cmdAtom, cmdName);
pnsMenuItem->SetCommand(cmdName);
// DO NOT use passed in webshell because of messed up windows dynamic loading
// code.
pnsMenuItem->SetWebShell(mWebShell);
pnsMenuItem->SetDOMElement(domElement);
NS_RELEASE(pnsMenuItem);
}
return;
}
//----------------------------------------
void nsContextMenu::LoadSubMenu(nsIMenu *pParentMenu,
nsIDOMElement *menuElement,
nsIDOMNode *menuNode)
{
nsString menuName;
menuElement->GetAttribute(nsAutoString("name"), menuName);
//printf("Creating Menu [%s] \n", menuName.ToNewCString()); // this leaks
// Create nsMenu
nsIMenu * pnsMenu = nsnull;
nsresult rv = nsComponentManager::CreateInstance(kMenuCID,
nsnull,
nsIMenu::GetIID(),
(void**)&pnsMenu);
if (NS_OK == rv) {
// Call Create
nsISupports * supports = nsnull;
pParentMenu->QueryInterface(kISupportsIID, (void**) &supports);
pnsMenu->Create(supports, menuName);
NS_RELEASE(supports); // Balance QI
// Set nsMenu Name
pnsMenu->SetLabel(menuName);
supports = nsnull;
pnsMenu->QueryInterface(kISupportsIID, (void**) &supports);
pParentMenu->AddItem(supports); // parent takes ownership
NS_RELEASE(supports);
pnsMenu->SetWebShell(mWebShell);
pnsMenu->SetDOMNode(menuNode);
/*
// Begin menuitem inner loop
unsigned short menuIndex = 0;
nsCOMPtr<nsIDOMNode> menuitemNode;
menuNode->GetFirstChild(getter_AddRefs(menuitemNode));
while (menuitemNode) {
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
if (menuitemElement) {
nsString menuitemNodeType;
menuitemElement->GetNodeName(menuitemNodeType);
#ifdef DEBUG_saari
printf("Type [%s] %d\n", menuitemNodeType.ToNewCString(), menuitemNodeType.Equals("separator"));
#endif
if (menuitemNodeType.Equals("menuitem")) {
// Load a menuitem
LoadMenuItem(pnsMenu, menuitemElement, menuitemNode, menuIndex, mWebShell);
} else if (menuitemNodeType.Equals("separator")) {
pnsMenu->AddSeparator();
} else if (menuitemNodeType.Equals("menu")) {
// Add a submenu
LoadSubMenu(pnsMenu, menuitemElement, menuitemNode);
}
}
++menuIndex;
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
} // end menu item innner loop
*/
}
}
//----------------------------------------
void nsContextMenu::LoadMenuItem(nsIContextMenu *pParentMenu,
nsIDOMElement *menuitemElement,
nsIDOMNode *menuitemNode,
unsigned short menuitemIndex,
nsIWebShell *aWebShell)
{
}
//----------------------------------------
void nsContextMenu::LoadSubMenu(nsIContextMenu *pParentMenu,
nsIDOMElement *menuElement,
nsIDOMNode *menuNode)
{
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::SetLocation(PRInt32 aX, PRInt32 aY)
{
mX = aX;
mY = aY;
return NS_OK;
}
// local methods
gint nsContextMenu::GetX(void)
{
return mX;
}
gint nsContextMenu::GetY(void)
{
return mY;
}
// end silly local methods
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::SetDOMNode(nsIDOMNode *aMenuNode)
{
mDOMNode = aMenuNode;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::SetDOMElement(nsIDOMElement *aMenuElement)
{
mDOMElement = aMenuElement;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::SetWebShell(nsIWebShell *aWebShell)
{
mWebShell = aWebShell;
return NS_OK;
}

View File

@@ -0,0 +1,139 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsContextMenu_h__
#define nsContextMenu_h__
#include "nsIContextMenu.h"
#include "nsISupportsArray.h"
#include "nsVoidArray.h"
#include "nsIDOMElement.h"
#include "nsIWebShell.h"
class nsIMenuListener;
/**
* Native Win32 button wrapper
*/
class nsContextMenu : public nsIContextMenu, public nsIMenuListener
{
public:
nsContextMenu();
virtual ~nsContextMenu();
NS_DECL_ISUPPORTS
//nsIMenuListener interface
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuConstruct(const nsMenuEvent & aMenuEvent,
nsIWidget * aParentWindow,
void * menubarNode,
void * aWebShell);
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
// nsIMenu Methods
NS_IMETHOD Create(nsISupports * aParent,
const nsString& anAlignment,
const nsString& aAnchorAlign);
NS_IMETHOD GetParent(nsISupports *&aParent);
NS_IMETHOD AddItem(nsISupports * aItem);
NS_IMETHOD AddSeparator();
NS_IMETHOD GetItemCount(PRUint32 &aCount);
NS_IMETHOD GetItemAt(const PRUint32 aPos, nsISupports *& aMenuItem);
NS_IMETHOD InsertItemAt(const PRUint32 aPos, nsISupports * aMenuItem);
NS_IMETHOD RemoveItem(const PRUint32 aPos);
NS_IMETHOD RemoveAll();
NS_IMETHOD GetNativeData(void** aData);
NS_IMETHOD AddMenuListener(nsIMenuListener * aMenuListener);
NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener);
//
NS_IMETHOD AddMenuItem(nsIMenuItem * aMenuItem);
NS_IMETHOD AddMenu(nsIMenu * aMenu);
NS_IMETHOD InsertSeparator(const PRUint32 aCount);
NS_IMETHOD SetDOMNode(nsIDOMNode * menuNode);
NS_IMETHOD SetDOMElement(nsIDOMElement * menuElement);
NS_IMETHOD SetWebShell(nsIWebShell * aWebShell);
NS_IMETHOD SetLocation(PRInt32 aX, PRInt32 aY);
gint GetX(void);
gint GetY(void);
protected:
nsIMenuBar * GetMenuBar(nsIMenu * aMenu);
nsIWidget * GetParentWidget();
char* GetACPString(nsString& aStr);
void LoadMenuItem(nsIMenu * pParentMenu,
nsIDOMElement * menuitemElement,
nsIDOMNode * menuitemNode,
unsigned short menuitemIndex,
nsIWebShell * aWebShell);
void LoadSubMenu(nsIMenu * pParentMenu,
nsIDOMElement * menuElement,
nsIDOMNode * menuNode);
void LoadMenuItem(nsIContextMenu * pParentMenu,
nsIDOMElement * menuitemElement,
nsIDOMNode * menuitemNode,
unsigned short menuitemIndex,
nsIWebShell * aWebShell);
void LoadSubMenu(nsIContextMenu * pParentMenu,
nsIDOMElement * menuElement,
nsIDOMNode * menuNode);
nsIMenuItem * FindMenuItem(nsIContextMenu * aMenu, PRUint32 aId);
nsString mLabel;
PRUint32 mNumMenuItems;
GtkWidget *mMenu;
nsVoidArray mMenuItemVoidArray;
nsIWidget *mParent;
nsIMenuListener * mListener;
PRBool mConstructCalled;
nsIDOMNode * mDOMNode;
nsIWebShell * mWebShell;
nsIDOMElement * mDOMElement;
nsString mAlignment;
nsString mAnchorAlignment;
PRInt32 mX;
PRInt32 mY;
};
#endif // nsContextMenu_h__

View File

@@ -0,0 +1,592 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsDragService.h"
#include "nsITransferable.h"
#include "nsString.h"
#include "nsClipboard.h"
#include "nsIRegion.h"
#include "nsVoidArray.h"
#include "nsISupportsPrimitives.h"
#include "nsPrimitiveHelpers.h"
#include "nsCOMPtr.h"
#include "nsXPIDLString.h"
#include "nsWidgetsCID.h"
NS_IMPL_ADDREF_INHERITED(nsDragService, nsBaseDragService)
NS_IMPL_RELEASE_INHERITED(nsDragService, nsBaseDragService)
NS_IMPL_QUERY_INTERFACE2(nsDragService, nsIDragService, nsIDragSession)
#define DEBUG_DRAG 1
//-------------------------------------------------------------------------
//
// DragService constructor
//
//-------------------------------------------------------------------------
nsDragService::nsDragService()
{
NS_INIT_REFCNT();
mWidget = nsnull;
mNumFlavors = 0;
}
//-------------------------------------------------------------------------
//
// DragService destructor
//
//-------------------------------------------------------------------------
nsDragService::~nsDragService()
{
}
enum {
TARGET_STRING,
TARGET_ROOTWIN
};
static GtkTargetEntry target_table[] = {
{ "STRING", 0, TARGET_STRING },
{ "text/plain", 0, TARGET_STRING },
{ "application/x-rootwin-drop", 0, TARGET_ROOTWIN }
};
static guint n_targets = sizeof(target_table) / sizeof(target_table[0]);
NS_IMETHODIMP nsDragService::StartDragSession()
{
printf("nsDragService::StartDragSession()\n");
nsBaseDragService::StartDragSession();
/*
gtk_drag_source_set(mWidget,
GDK_MODIFIER_MASK,
targetlist,
mNumFlavors,
action);
*/
gtk_drag_source_set(mWidget,
GDK_MODIFIER_MASK,
target_table,
n_targets,
mActionType);
return NS_OK;
}
NS_IMETHODIMP nsDragService::EndDragSession()
{
printf("nsDragService::EndDragSession()\n");
nsBaseDragService::EndDragSession();
gtk_drag_source_unset(mWidget);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::InvokeDragSession (nsISupportsArray *aTransferableArray,
nsIScriptableRegion *aRegion,
PRUint32 aActionType)
{
mWidget = gtk_get_event_widget(gtk_get_current_event());
// add the flavors from the transferables. Cache this array for the send data proc
GtkTargetList *targetlist = RegisterDragItemsAndFlavors(aTransferableArray);
switch (aActionType)
{
case DRAGDROP_ACTION_NONE:
mActionType = GDK_ACTION_DEFAULT;
break;
case DRAGDROP_ACTION_COPY:
mActionType = GDK_ACTION_COPY;
break;
case DRAGDROP_ACTION_MOVE:
mActionType = GDK_ACTION_MOVE;
break;
case DRAGDROP_ACTION_LINK:
mActionType = GDK_ACTION_LINK;
break;
}
StartDragSession();
// XXX 3rd param ??? & last param should be a real event...
gtk_drag_begin(mWidget, targetlist, mActionType, 1, gtk_get_current_event());
#if 0
// we have to synthesize the native event because we may be called from JavaScript
// through XPConnect. In that case, we only have a DOM event and no way to
// get to the native event. As a consequence, we just always fake it.
Point globalMouseLoc;
::GetMouse(&globalMouseLoc);
::LocalToGlobal(&globalMouseLoc);
WindowPtr theWindow = nsnull;
if ( ::FindWindow(globalMouseLoc, &theWindow) != inContent ) {
// debugging sanity check
#ifdef NS_DEBUG
DebugStr("\pAbout to start drag, but FindWindow() != inContent; g");
#endif
}
EventRecord theEvent;
theEvent.what = mouseDown;
theEvent.message = reinterpret_cast<UInt32>(theWindow);
theEvent.when = 0;
theEvent.where = globalMouseLoc;
theEvent.modifiers = 0;
RgnHandle theDragRgn = ::NewRgn();
BuildDragRegion ( aDragRgn, globalMouseLoc, theDragRgn );
// register drag send proc which will call us back when asked for the actual
// flavor data (instead of placing it all into the drag manager)
::SetDragSendProc ( theDragRef, sDragSendDataUPP, this );
// start the drag. Be careful, mDragRef will be invalid AFTER this call (it is
// reset by the dragTrackingHandler).
::TrackDrag ( theDragRef, &theEvent, theDragRgn );
// clean up after ourselves
::DisposeRgn ( theDragRgn );
result = ::DisposeDrag ( theDragRef );
NS_ASSERTION ( result == noErr, "Error disposing drag" );
mDragRef = 0L;
mDataItems = nsnull;
return NS_OK;
#endif
return NS_OK;
}
GtkTargetList *
nsDragService::RegisterDragItemsAndFlavors(nsISupportsArray *inArray)
{
unsigned int numDragItems = 0;
inArray->Count(&numDragItems);
GtkTargetList *targetlist;
targetlist = gtk_target_list_new(nsnull, numDragItems);
for (unsigned int i = 0; i < numDragItems; ++i)
{
nsCOMPtr<nsISupports> genericItem;
inArray->GetElementAt (i, getter_AddRefs(genericItem));
nsCOMPtr<nsITransferable> currItem (do_QueryInterface(genericItem));
if (currItem)
{
nsCOMPtr<nsISupportsArray> flavorList;
if (NS_SUCCEEDED(currItem->FlavorsTransferableCanExport(getter_AddRefs(flavorList))))
{
flavorList->Count (&mNumFlavors);
for (PRUint32 flavorIndex = 0; flavorIndex < mNumFlavors; ++flavorIndex)
{
nsCOMPtr<nsISupports> genericWrapper;
flavorList->GetElementAt ( flavorIndex, getter_AddRefs(genericWrapper) );
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericWrapper) );
if ( currentFlavor )
{
nsXPIDLCString flavorStr;
currentFlavor->ToString ( getter_Copies(flavorStr) );
// register native flavors
GdkAtom atom = gdk_atom_intern(flavorStr, PR_TRUE);
gtk_target_list_add(targetlist, atom, 1, atom);
}
} // foreach flavor in item
} // if valid flavor list
} // if item is a transferable
} // foreach drag item
return targetlist;
}
/* return PR_TRUE if we have converted or PR_FALSE if we havn't and need to keep being called */
PRBool nsDragService::DoConvert(GdkAtom type)
{
#ifdef DEBUG_DRAG
g_print(" nsDragService::DoRealConvert(%li)\n {\n", type);
#endif
int e = 0;
// Set a flag saying that we're blocking waiting for the callback:
mBlocking = PR_TRUE;
//
// ask X what kind of data we can get
//
#ifdef DEBUG_DRAG
g_print(" Doing real conversion of atom type '%s'\n", gdk_atom_name(type));
#endif
gtk_selection_convert(mWidget,
GDK_SELECTION_PRIMARY,
type,
GDK_CURRENT_TIME);
// Now we need to wait until the callback comes in ...
// i is in case we get a runaway (yuck).
#ifdef DEBUG_DRAG
printf(" Waiting for the callback... mBlocking = %d\n", mBlocking);
#endif /* DEBUG_CLIPBOARD */
for (e=0; mBlocking == PR_TRUE && e < 1000; ++e)
{
gtk_main_iteration_do(PR_TRUE);
}
#ifdef DEBUG_DRAG
g_print(" }\n");
#endif
if (mSelectionData.length > 0)
return PR_TRUE;
return PR_FALSE;
}
#if 0
/**
* Called when the data from a drag comes in (recieved from gdk_selection_convert)
*
* @param aWidget the widget
* @param aSelectionData gtk selection stuff
* @param aTime time the selection was requested
*/
void
nsDragService::SelectionReceivedCB (GtkWidget *aWidget,
GdkDragContext *aContext,
gint aX,
gint aY,
GtkSelectionData *aSelectionData,
guint aInfo,
guint aTime)
{
#ifdef DEBUG_DRAG
printf(" nsDragService::SelectionReceivedCB\n {\n");
#endif
nsDragService *ds =(nsDragSession *)gtk_object_get_data(GTK_OBJECT(aWidget),
"ds");
if (!cb)
{
g_print("no dragservice found.. this is bad.\n");
return;
}
ds->SelectionReceiver(aWidget, aSelectionData);
#ifdef DEBUG_DRAG
g_print(" }\n");
#endif
}
/**
* local method (called from nsClipboard::SelectionReceivedCB)
*
* @param aWidget the widget
* @param aSelectionData gtk selection stuff
*/
void
nsDragService::SelectionReceiver (GtkWidget *aWidget,
GtkSelectionData *aSD)
{
gint type;
mBlocking = PR_FALSE;
if (aSD->length < 0)
{
printf(" Error retrieving selection: length was %d\n",
aSD->length);
return;
}
switch (type)
{
case GDK_TARGET_STRING:
case TARGET_COMPOUND_TEXT:
case TARGET_TEXT_PLAIN:
case TARGET_TEXT_XIF:
case TARGET_TEXT_UNICODE:
case TARGET_TEXT_HTML:
#ifdef DEBUG_CLIPBOARD
g_print(" Copying mSelectionData pointer -- ");
#endif
mSelectionData = *aSD;
mSelectionData.data = g_new(guchar, aSD->length + 1);
#ifdef DEBUG_CLIPBOARD
g_print(" Data = %s\n Length = %i\n", aSD->data, aSD->length);
#endif
memcpy(mSelectionData.data,
aSD->data,
aSD->length);
// Null terminate in case anyone cares,
// and so we can print the string for debugging:
mSelectionData.data[aSD->length] = '\0';
mSelectionData.length = aSD->length;
return;
default:
mSelectionData = *aSD;
mSelectionData.data = g_new(guchar, aSD->length + 1);
memcpy(mSelectionData.data,
aSD->data,
aSD->length);
mSelectionData.length = aSD->length;
return;
}
}
#endif
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::GetNumDropItems (PRUint32 * aNumItems)
{
*aNumItems = 0;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::GetData (nsITransferable * aTransferable, PRUint32 anItem)
{
#ifdef DEBUG_DRAG
printf("nsClipboard::GetNativeClipboardData()\n");
#endif /* DEBUG_CLIPBOARD */
// make sure we have a good transferable
if (!aTransferable) {
printf(" GetData: Transferable is null!\n");
return NS_ERROR_FAILURE;
}
// get flavor list that includes all acceptable flavors (including ones obtained through
// conversion)
nsCOMPtr<nsISupportsArray> flavorList;
nsresult errCode = aTransferable->FlavorsTransferableCanImport ( getter_AddRefs(flavorList) );
if ( NS_FAILED(errCode) )
return NS_ERROR_FAILURE;
// Walk through flavors and see which flavor matches the one being pasted:
PRUint32 cnt;
flavorList->Count(&cnt);
nsCAutoString foundFlavor;
for ( PRUint32 i = 0; i < cnt; ++i ) {
nsCOMPtr<nsISupports> genericFlavor;
flavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) );
nsCOMPtr<nsISupportsString> currentFlavor (do_QueryInterface(genericFlavor));
if ( currentFlavor ) {
nsXPIDLCString flavorStr;
currentFlavor->ToString(getter_Copies(flavorStr));
if (DoConvert(gdk_atom_intern(flavorStr, 1))) {
foundFlavor = flavorStr;
break;
}
}
}
#ifdef DEBUG_CLIPBOARD
printf(" Got the callback: '%s', %d\n",
mSelectionData.data, mSelectionData.length);
#endif /* DEBUG_CLIPBOARD */
// We're back from the callback, no longer blocking:
mBlocking = PR_FALSE;
//
// Now we have data in mSelectionData.data.
// We just have to copy it to the transferable.
//
#if 0
// pinkerton - we have the flavor already from above, so we don't need
// to re-derrive it.
nsString *name = new nsString((const char*)gdk_atom_name(mSelectionData.type));
int format = GetFormat(*name);
df->SetString((const char*)gdk_atom_name(sSelTypes[format]));
#endif
nsCOMPtr<nsISupports> genericDataWrapper;
nsPrimitiveHelpers::CreatePrimitiveForData ( foundFlavor, mSelectionData.data, mSelectionData.length, getter_AddRefs(genericDataWrapper) );
aTransferable->SetTransferData(foundFlavor,
genericDataWrapper,
mSelectionData.length);
//delete name;
// transferable is now copying the data, so we can free it.
// g_free(mSelectionData.data);
mSelectionData.data = nsnull;
mSelectionData.length = 0;
gtk_drag_source_unset(mWidget);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval)
{
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::GetCurrentSession (nsIDragSession **aSession)
{
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
void
nsDragService::DragLeave (GtkWidget *widget,
GdkDragContext *context,
guint time)
{
g_print("leave\n");
//gHaveDrag = PR_FALSE;
}
//-------------------------------------------------------------------------
PRBool
nsDragService::DragMotion(GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time)
{
g_print("drag motion\n");
GtkWidget *source_widget;
#if 0
if (!gHaveDrag) {
gHaveDrag = PR_TRUE;
}
#endif
source_widget = gtk_drag_get_source_widget (context);
g_print("motion, source %s\n", source_widget ?
gtk_type_name (GTK_OBJECT (source_widget)->klass->type) :
"unknown");
gdk_drag_status (context, context->suggested_action, time);
return PR_TRUE;
}
//-------------------------------------------------------------------------
PRBool
nsDragService::DragDrop(GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time)
{
g_print("drop\n");
//gHaveDrag = PR_FALSE;
if (context->targets){
gtk_drag_get_data (widget, context,
GPOINTER_TO_INT (context->targets->data),
time);
return PR_TRUE;
}
return PR_FALSE;
}
//-------------------------------------------------------------------------
void
nsDragService::DragDataReceived (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *data,
guint info,
guint time)
{
if ((data->length >= 0) && (data->format == 8)) {
g_print ("Received \"%s\"\n", (gchar *)data->data);
gtk_drag_finish (context, PR_TRUE, PR_FALSE, time);
return;
}
gtk_drag_finish (context, PR_FALSE, PR_FALSE, time);
}
//-------------------------------------------------------------------------
void
nsDragService::DragDataGet(GtkWidget *widget,
GdkDragContext *context,
GtkSelectionData *selection_data,
guint info,
guint time,
gpointer data)
{
gtk_selection_data_set (selection_data,
selection_data->target,
8, (guchar *)"I'm Data!", 9);
}
//-------------------------------------------------------------------------
void
nsDragService::DragDataDelete(GtkWidget *widget,
GdkDragContext *context,
gpointer data)
{
g_print ("Delete the data!\n");
}

View File

@@ -0,0 +1,109 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsDragService_h__
#define nsDragService_h__
#include "nsBaseDragService.h"
#include <gtk/gtk.h>
/**
* Native GTK DragService wrapper
*/
class nsDragService : public nsBaseDragService
{
public:
nsDragService();
virtual ~nsDragService();
NS_DECL_ISUPPORTS_INHERITED
// nsIDragService
NS_IMETHOD InvokeDragSession (nsISupportsArray * anArrayTransferables,
nsIScriptableRegion * aRegion, PRUint32 aActionType);
NS_IMETHOD GetCurrentSession (nsIDragSession ** aSession);
// nsIDragSession
NS_IMETHOD GetData (nsITransferable * aTransferable, PRUint32 anItem);
NS_IMETHOD GetNumDropItems (PRUint32 * aNumItems);
NS_IMETHOD IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval);
NS_IMETHOD StartDragSession();
NS_IMETHOD EndDragSession();
GtkTargetList *RegisterDragItemsAndFlavors(nsISupportsArray *inArray);
protected:
PRBool DoConvert(GdkAtom type);
static PRBool gHaveDrag;
static void DragLeave(GtkWidget *widget,
GdkDragContext *context,
guint time);
static PRBool DragMotion(GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time);
static PRBool DragDrop(GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time);
static void DragDataReceived(GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *data,
guint info,
guint time);
static void DragDataGet(GtkWidget *widget,
GdkDragContext *context,
GtkSelectionData *selection_data,
guint info,
guint time,
gpointer data);
static void DragDataDelete(GtkWidget *widget,
GdkDragContext *context,
gpointer data);
private:
GdkDragAction mActionType;
PRUint32 mNumFlavors;
GtkWidget *mWidget;
GdkDragContext *mDragContext;
GtkSelectionData mSelectionData;
PRBool mBlocking;
};
#endif // nsDragService_h__

View File

@@ -0,0 +1,304 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Mozilla browser.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsCOMPtr.h"
#include "nsIComponentManager.h"
#include "nsFilePicker.h"
NS_IMPL_ISUPPORTS1(nsFilePicker, nsIFilePicker)
//-------------------------------------------------------------------------
//
// nsFilePicker constructor
//
//-------------------------------------------------------------------------
nsFilePicker::nsFilePicker()
{
NS_INIT_REFCNT();
mWidget = nsnull;
mDisplayDirectory = nsnull;
mFilterMenu = nsnull;
mOptionMenu = nsnull;
mNumberOfFilters = 0;
}
//-------------------------------------------------------------------------
//
// nsFilePicker destructor
//
//-------------------------------------------------------------------------
nsFilePicker::~nsFilePicker()
{
if (mFilterMenu)
{
GtkWidget *menu_item;
GList *list = g_list_first(GTK_MENU_SHELL(mFilterMenu)->children);
for (;list; list = list->next)
{
menu_item = GTK_WIDGET(list->data);
gchar *data = (gchar*)gtk_object_get_data(GTK_OBJECT(menu_item), "filters");
if (data)
nsCRT::free(data);
}
}
gtk_widget_destroy(mWidget);
}
static void file_ok_clicked(GtkWidget *w, PRBool *ret)
{
g_print("user hit ok\n");
*ret = PR_TRUE;
gtk_main_quit();
}
static void file_cancel_clicked(GtkWidget *w, PRBool *ret)
{
g_print("user hit cancel\n");
*ret = PR_FALSE;
gtk_main_quit();
}
static void filter_item_activated(GtkWidget *w, gpointer data)
{
// nsFilePicker *f = (nsFilePicker*)data;
gchar *foo = (gchar*)gtk_object_get_data(GTK_OBJECT(w), "filters");
g_print("filter_item_activated(): %s\n", foo);
}
//-------------------------------------------------------------------------
//
// Show - Display the file dialog
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::Show(PRInt16 *retval)
{
NS_ENSURE_ARG_POINTER(retval);
PRBool ret;
if (mWidget) {
// make things shorter
GtkFileSelection *fs = GTK_FILE_SELECTION(mWidget);
if (mNumberOfFilters != 0)
{
gtk_option_menu_set_menu(GTK_OPTION_MENU(mOptionMenu), mFilterMenu);
}
else
gtk_widget_hide(mOptionMenu);
#if 0
if (mDisplayDirectory)
gtk_file_selection_complete(fs, "/");
#endif
// gtk_window_set_modal(GTK_WINDOW(mWidget), PR_TRUE);
gtk_widget_show(mWidget);
// handle close, destroy, etc on the dialog
gtk_signal_connect(GTK_OBJECT(fs->ok_button), "clicked",
GTK_SIGNAL_FUNC(file_ok_clicked),
&ret);
gtk_signal_connect(GTK_OBJECT(fs->cancel_button), "clicked",
GTK_SIGNAL_FUNC(file_cancel_clicked),
&ret);
// start new loop. ret is set in the above callbacks.
gtk_main();
}
else {
ret = PR_FALSE;
}
if (ret)
*retval = returnOK;
else
*retval = returnCancel;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set the list of filters
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::SetFilterList(PRInt32 aNumberOfFilters,
const PRUnichar **aTitles,
const PRUnichar **filters)
{
#if 0
GtkWidget *menu_item;
mNumberOfFilters = aNumberOfFilters;
mTitles = aTitles;
mFilters = aFilters;
mFilterMenu = gtk_menu_new();
for(unsigned int i=0; i < aNumberOfFilters; i++)
{
// we need *.{htm, html, xul, etc}
char *foo = aTitles[i].ToNewCString();
char *filters = aFilters[i].ToNewCString();
printf("%20s %s\n", foo, filters);
menu_item = gtk_menu_item_new_with_label(nsAutoCString(aTitles[i]));
gtk_object_set_data(GTK_OBJECT(menu_item), "filters", filters);
gtk_signal_connect(GTK_OBJECT(menu_item),
"activate",
GTK_SIGNAL_FUNC(filter_item_activated),
this);
gtk_menu_append(GTK_MENU(mFilterMenu), menu_item);
gtk_widget_show(menu_item);
nsCRT::free(foo);
}
#endif
return NS_OK;
}
NS_IMETHODIMP nsFilePicker::GetFile(nsIFileSpec **aFile)
{
NS_ENSURE_ARG_POINTER(*aFile);
if (mWidget) {
gchar *fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION(mWidget));
nsCOMPtr<nsIFileSpec> fileSpec(do_CreateInstance("component://netscape/filespec"));
NS_ENSURE_TRUE(fileSpec, NS_ERROR_FAILURE);
fileSpec->SetNativePath(fn);
*aFile = fileSpec;
NS_ADDREF(*aFile);
}
return NS_OK;
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::GetSelectedFilter(PRInt32 *aType)
{
NS_ENSURE_ARG_POINTER(aType);
*aType = mSelectedType;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get the file + path
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::SetDefaultString(const PRUnichar *aString)
{
if (mWidget) {
gtk_file_selection_set_filename(GTK_FILE_SELECTION(mWidget),
(const gchar*)nsAutoCString(aString));
}
return NS_OK;
}
NS_IMETHODIMP nsFilePicker::GetDefaultString(PRUnichar **aString)
{
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
//
// Set the display directory
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::SetDisplayDirectory(nsIFileSpec *aDirectory)
{
mDisplayDirectory = aDirectory;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get the display directory
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::GetDisplayDirectory(nsIFileSpec **aDirectory)
{
*aDirectory = mDisplayDirectory;
NS_IF_ADDREF(*aDirectory);
return NS_OK;
}
NS_IMETHODIMP nsFilePicker::Create(nsIDOMWindow *aParent,
const PRUnichar *aTitle,
PRInt16 aMode)
{
return nsBaseFilePicker::Create(aParent, aTitle, aMode);
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::CreateNative(nsIWidget *aParent,
const PRUnichar *aTitle,
PRInt16 aMode)
{
mWidget = gtk_file_selection_new((const gchar *)nsAutoCString(aTitle));
gtk_signal_connect(GTK_OBJECT(mWidget),
"destroy",
GTK_SIGNAL_FUNC(DestroySignal),
this);
gtk_button_box_set_layout(GTK_BUTTON_BOX(GTK_FILE_SELECTION(mWidget)->button_area), GTK_BUTTONBOX_SPREAD);
mOptionMenu = gtk_option_menu_new();
gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(mWidget)->main_vbox), mOptionMenu, PR_FALSE, PR_FALSE, 0);
gtk_widget_show(mOptionMenu);
// Hide the file column for the folder case.
if (aMode == nsIFilePicker::modeGetFolder) {
gtk_widget_hide((GTK_FILE_SELECTION(mWidget)->file_list)->parent);
}
return NS_OK;
}
gint
nsFilePicker::DestroySignal(GtkWidget * aGtkWidget,
nsFilePicker* aWidget)
{
aWidget->OnDestroySignal(aGtkWidget);
return TRUE;
}
void
nsFilePicker::OnDestroySignal(GtkWidget* aGtkWidget)
{
if (aGtkWidget == mWidget) {
mWidget = nsnull;
}
}

View File

@@ -0,0 +1,68 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Mozilla browser.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#ifndef nsFilePicker_h__
#define nsFilePicker_h__
#include "nsBaseFilePicker.h"
#include <gtk/gtk.h>
/**
* Native GTK FileSelector wrapper
*/
class nsFilePicker : public nsBaseFilePicker
{
public:
nsFilePicker();
virtual ~nsFilePicker();
NS_DECL_ISUPPORTS
NS_DECL_NSIFILEPICKER
protected:
/* method from nsBaseFilePicker */
NS_IMETHOD CreateNative(nsIWidget *aParent,
const PRUnichar *aTitle,
PRInt16 aMode);
static gint DestroySignal(GtkWidget * aGtkWidget,
nsFilePicker* aWidget);
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
GtkWidget *mWidget;
GtkWidget *mOptionMenu;
GtkWidget *mFilterMenu;
PRUint32 mNumberOfFilters;
const nsString* mTitles;
const nsString* mFilters;
nsString mDefault;
nsIFileSpec *mDisplayDirectory;
PRInt16 mSelectedType;
};
#endif // nsFilePicker_h__

View File

@@ -0,0 +1,322 @@
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsFileWidget.h"
#include "nsIToolkit.h"
NS_IMPL_ISUPPORTS1(nsFileWidget, nsIFileWidget)
//-------------------------------------------------------------------------
//
// nsFileWidget constructor
//
//-------------------------------------------------------------------------
nsFileWidget::nsFileWidget() : nsIFileWidget()
{
NS_INIT_REFCNT();
mWidget = nsnull;
mDisplayDirectory = nsnull;
mFilterMenu = nsnull;
mOptionMenu = nsnull;
mNumberOfFilters = 0;
}
//-------------------------------------------------------------------------
//
// nsFileWidget destructor
//
//-------------------------------------------------------------------------
nsFileWidget::~nsFileWidget()
{
if (mFilterMenu)
{
GtkWidget *menu_item;
GList *list = g_list_first(GTK_MENU_SHELL(mFilterMenu)->children);
for (;list; list = list->next)
{
menu_item = GTK_WIDGET(list->data);
gchar *data = (gchar*)gtk_object_get_data(GTK_OBJECT(menu_item), "filters");
if (data)
nsCRT::free(data);
}
}
gtk_widget_destroy(mWidget);
}
static void file_ok_clicked(GtkWidget *w, PRBool *ret)
{
g_print("user hit ok\n");
*ret = PR_TRUE;
gtk_main_quit();
}
static void file_cancel_clicked(GtkWidget *w, PRBool *ret)
{
g_print("user hit cancel\n");
*ret = PR_FALSE;
gtk_main_quit();
}
static void filter_item_activated(GtkWidget *w, gpointer data)
{
// nsFileWidget *f = (nsFileWidget*)data;
gchar *foo = (gchar*)gtk_object_get_data(GTK_OBJECT(w), "filters");
g_print("filter_item_activated(): %s\n", foo);
}
//-------------------------------------------------------------------------
//
// Show - Display the file dialog
//
//-------------------------------------------------------------------------
PRBool nsFileWidget::Show()
{
PRBool ret;
if (mWidget) {
// make things shorter
GtkFileSelection *fs = GTK_FILE_SELECTION(mWidget);
if (mNumberOfFilters != 0)
{
gtk_option_menu_set_menu(GTK_OPTION_MENU(mOptionMenu), mFilterMenu);
}
else
gtk_widget_hide(mOptionMenu);
#if 0
if (mDisplayDirectory)
gtk_file_selection_complete(fs, "/");
#endif
// gtk_window_set_modal(GTK_WINDOW(mWidget), PR_TRUE);
gtk_widget_show(mWidget);
// handle close, destroy, etc on the dialog
gtk_signal_connect(GTK_OBJECT(fs->ok_button), "clicked",
GTK_SIGNAL_FUNC(file_ok_clicked),
&ret);
gtk_signal_connect(GTK_OBJECT(fs->cancel_button), "clicked",
GTK_SIGNAL_FUNC(file_cancel_clicked),
&ret);
// start new loop. ret is set in the above callbacks.
gtk_main();
}
else {
ret = PR_FALSE;
}
return ret;
}
//-------------------------------------------------------------------------
//
// Set the list of filters
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFileWidget::SetFilterList(PRUint32 aNumberOfFilters,
const nsString aTitles[],
const nsString aFilters[])
{
GtkWidget *menu_item;
mNumberOfFilters = aNumberOfFilters;
mTitles = aTitles;
mFilters = aFilters;
mFilterMenu = gtk_menu_new();
for(unsigned int i=0; i < aNumberOfFilters; i++)
{
// we need *.{htm, html, xul, etc}
char *foo = aTitles[i].ToNewCString();
char *filters = aFilters[i].ToNewCString();
printf("%20s %s\n", foo, filters);
menu_item = gtk_menu_item_new_with_label(nsAutoCString(aTitles[i]));
gtk_object_set_data(GTK_OBJECT(menu_item), "filters", filters);
gtk_signal_connect(GTK_OBJECT(menu_item),
"activate",
GTK_SIGNAL_FUNC(filter_item_activated),
this);
gtk_menu_append(GTK_MENU(mFilterMenu), menu_item);
gtk_widget_show(menu_item);
nsCRT::free(foo);
}
return NS_OK;
}
NS_IMETHODIMP nsFileWidget::GetFile(nsFileSpec& aFile)
{
if (mWidget) {
gchar *fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION(mWidget));
aFile = fn; // Put the filename into the nsFileSpec instance.
}
return NS_OK;
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFileWidget::GetSelectedType(PRInt16& theType)
{
theType = mSelectedType;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get the file + path
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFileWidget::SetDefaultString(const nsString& aString)
{
if (mWidget) {
gtk_file_selection_set_filename(GTK_FILE_SELECTION(mWidget),
(const gchar*)nsAutoCString(aString));
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set the display directory
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFileWidget::SetDisplayDirectory(const nsFileSpec& aDirectory)
{
mDisplayDirectory = aDirectory;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get the display directory
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFileWidget::GetDisplayDirectory(nsFileSpec& aDirectory)
{
aDirectory = mDisplayDirectory;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFileWidget::Create(nsIWidget *aParent,
const nsString& aTitle,
nsFileDlgMode aMode,
nsIDeviceContext *aContext,
nsIAppShell *aAppShell,
nsIToolkit *aToolkit,
void *aInitData)
{
mMode = aMode;
mTitle.SetLength(0);
mTitle.Append(aTitle);
mWidget = gtk_file_selection_new((const gchar *)nsAutoCString(aTitle));
gtk_signal_connect(GTK_OBJECT(mWidget),
"destroy",
GTK_SIGNAL_FUNC(DestroySignal),
this);
gtk_button_box_set_layout(GTK_BUTTON_BOX(GTK_FILE_SELECTION(mWidget)->button_area), GTK_BUTTONBOX_SPREAD);
mOptionMenu = gtk_option_menu_new();
gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(mWidget)->main_vbox), mOptionMenu, PR_FALSE, PR_FALSE, 0);
gtk_widget_show(mOptionMenu);
// Hide the file column for the folder case.
if (aMode == eMode_getfolder) {
gtk_widget_hide((GTK_FILE_SELECTION(mWidget)->file_list)->parent);
}
return NS_OK;
}
gint
nsFileWidget::DestroySignal(GtkWidget * aGtkWidget,
nsFileWidget* aWidget)
{
aWidget->OnDestroySignal(aGtkWidget);
return TRUE;
}
void
nsFileWidget::OnDestroySignal(GtkWidget* aGtkWidget)
{
if (aGtkWidget == mWidget) {
mWidget = nsnull;
}
}
nsFileDlgResults nsFileWidget::GetFile(nsIWidget *aParent,
const nsString &promptString,
nsFileSpec &theFileSpec)
{
Create(aParent, promptString, eMode_load, nsnull, nsnull);
if (Show() == PR_TRUE)
{
GetFile(theFileSpec);
return nsFileDlgResults_OK;
}
return nsFileDlgResults_Cancel;
}
nsFileDlgResults nsFileWidget::GetFolder(nsIWidget *aParent,
const nsString &promptString,
nsFileSpec &theFileSpec)
{
Create(aParent, promptString, eMode_getfolder, nsnull, nsnull);
if (Show() == PR_TRUE)
{
GetFile(theFileSpec);
return nsFileDlgResults_OK;
}
return nsFileDlgResults_Cancel;
}
nsFileDlgResults nsFileWidget::PutFile(nsIWidget *aParent,
const nsString &promptString,
nsFileSpec &theFileSpec)
{
Create(aParent, promptString, eMode_save, nsnull, nsnull);
if (Show() == PR_TRUE)
{
GetFile(theFileSpec);
return nsFileDlgResults_OK;
}
return nsFileDlgResults_Cancel;
}

View File

@@ -0,0 +1,102 @@
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsFileWidget_h__
#define nsFileWidget_h__
#include "nsIWidget.h"
#include "nsIFileWidget.h"
#include <gtk/gtk.h>
class nsIToolkit;
/**
* Native GTK FileSelector wrapper
*/
class nsFileWidget : public nsIFileWidget
{
public:
nsFileWidget();
virtual ~nsFileWidget();
NS_DECL_ISUPPORTS
// nsIWidget interface
NS_IMETHOD Create(nsIWidget *aParent,
const nsString& aTitle,
nsFileDlgMode aMode,
nsIDeviceContext *aContext = nsnull,
nsIAppShell *aAppShell = nsnull,
nsIToolkit *aToolkit = nsnull,
void *aInitData = nsnull);
// nsIFileWidget part
virtual PRBool Show();
NS_IMETHOD GetFile(nsFileSpec& aFile);
NS_IMETHOD SetDefaultString(const nsString& aFile);
NS_IMETHOD SetFilterList(PRUint32 aNumberOfFilters,
const nsString aTitles[],
const nsString aFilters[]);
NS_IMETHOD GetDisplayDirectory(nsFileSpec& aDirectory);
NS_IMETHOD SetDisplayDirectory(const nsFileSpec& aDirectory);
virtual nsFileDlgResults GetFile(nsIWidget *aParent,
const nsString &promptString,
nsFileSpec &theFileSpec);
virtual nsFileDlgResults GetFolder(nsIWidget *aParent,
const nsString &promptString,
nsFileSpec &theFileSpec);
virtual nsFileDlgResults PutFile(nsIWidget *aParent,
const nsString &promptString,
nsFileSpec &theFileSpec);
NS_IMETHOD GetSelectedType(PRInt16& theType);
protected:
static gint DestroySignal(GtkWidget * aGtkWidget,
nsFileWidget* aWidget);
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
GtkWidget *mWidget;
nsString mTitle;
GtkWidget *mOptionMenu;
GtkWidget *mFilterMenu;
nsFileDlgMode mMode;
PRUint32 mNumberOfFilters;
const nsString* mTitles;
const nsString* mFilters;
nsString mDefault;
nsFileSpec mDisplayDirectory;
PRInt16 mSelectedType;
};
#endif // nsFileWidget_h__

View File

@@ -0,0 +1,395 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsFontRetrieverService.h"
#include "nsIWidget.h"
#include <ctype.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include "X11/Xlib.h"
#include "X11/Xutil.h"
#include "nsFont.h"
#include "nsVoidArray.h"
#include "nsFontSizeIterator.h"
NS_IMPL_ISUPPORTS2(nsFontRetrieverService, nsIFontRetrieverService, nsIFontNameIterator)
//----------------------------------------------------------
nsFontRetrieverService::nsFontRetrieverService()
{
NS_INIT_REFCNT();
mFontList = nsnull;
mSizeIter = nsnull;
mNameIterInx = 0;
}
//----------------------------------------------------------
nsFontRetrieverService::~nsFontRetrieverService()
{
if (nsnull != mFontList) {
for (PRInt32 i=0;i<mFontList->Count();i++) {
FontInfo * font = (FontInfo *)mFontList->ElementAt(i);
if (font->mSizes) {
delete font->mSizes;
}
delete font;
}
delete mFontList;
}
NS_IF_RELEASE(mSizeIter);
}
//----------------------------------------------------------
//-- nsIFontRetrieverService
//----------------------------------------------------------
NS_IMETHODIMP nsFontRetrieverService::CreateFontNameIterator( nsIFontNameIterator** aIterator )
{
if (nsnull == aIterator) {
return NS_ERROR_FAILURE;
}
if (nsnull == mFontList) {
LoadFontList();
}
*aIterator = this;
NS_ADDREF_THIS();
return NS_OK;
}
//----------------------------------------------------------
NS_IMETHODIMP nsFontRetrieverService::CreateFontSizeIterator( const nsString & aFontName,
nsIFontSizeIterator** aIterator )
{
// save value in case someone externally is using it
PRInt32 saveIterInx = mNameIterInx;
PRBool found = PR_FALSE;
Reset();
do {
nsAutoString name;
Get(&name);
if (name.Equals(aFontName)) {
found = PR_TRUE;
break;
}
} while (Advance() == NS_OK);
if (found) {
if (nsnull == mSizeIter) {
mSizeIter = new nsFontSizeIterator();
}
NS_ASSERTION( nsnull != mSizeIter, "nsFontSizeIterator instance pointer is null");
*aIterator = (nsIFontSizeIterator *)mSizeIter;
NS_ADDREF(mSizeIter);
FontInfo * fontInfo = (FontInfo *)mFontList->ElementAt(mNameIterInx);
mSizeIter->SetFontInfo(fontInfo);
mNameIterInx = saveIterInx;
return NS_OK;
}
mNameIterInx = saveIterInx;
return NS_ERROR_FAILURE;
}
//----------------------------------------------------------
//-- nsIFontNameIterator
//----------------------------------------------------------
NS_IMETHODIMP nsFontRetrieverService::Reset()
{
mNameIterInx = 0;
return NS_OK;
}
//----------------------------------------------------------
NS_IMETHODIMP nsFontRetrieverService::Get( nsString* aFontName )
{
if (mNameIterInx < mFontList->Count()) {
FontInfo * fontInfo = (FontInfo *)mFontList->ElementAt(mNameIterInx);
*aFontName = fontInfo->mName;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
//----------------------------------------------------------
NS_IMETHODIMP nsFontRetrieverService::Advance()
{
if (mNameIterInx < mFontList->Count()-1) {
mNameIterInx++;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
//------------------------------
static FontInfo * GetFontInfo(nsVoidArray * aFontList, char * aName)
{
nsAutoString name(aName);
PRInt32 i;
PRInt32 cnt = aFontList->Count();
for (i=0;i<cnt;i++) {
FontInfo * fontInfo = (FontInfo *)aFontList->ElementAt(i);
if (fontInfo->mName.Equals(name)) {
return fontInfo;
}
}
FontInfo * fontInfo = new FontInfo();
fontInfo->mName = aName;
//printf("Adding [%s]\n", aName);fflush(stdout);
fontInfo->mIsScalable = PR_FALSE; // X fonts aren't scalable right??
fontInfo->mSizes = nsnull;
aFontList->AppendElement(fontInfo);
return fontInfo;
}
//------------------------------
static void AddSizeToFontInfo(FontInfo * aFontInfo, PRInt32 aSize)
{
nsVoidArray * sizes;
if (nsnull == aFontInfo->mSizes) {
sizes = new nsVoidArray();
aFontInfo->mSizes = sizes;
} else {
sizes = aFontInfo->mSizes;
}
PRInt32 i;
PRInt32 cnt = sizes->Count();
for (i=0;i<cnt;i++) {
PRInt32 size = (int)sizes->ElementAt(i);
if (size == aSize) {
return;
}
}
sizes->AppendElement((void *)aSize);
}
//---------------------------------------------------
// XXX - Hack - Parts of this will need to be reworked
//
// This method does brute force parcing for 4 different formats:
//
// 1) The format -*-*-*-*-*-* etc.
// -misc-fixed-medium-r-normal--13-120-75-75-c-80-iso8859-8
//
// 2) Name-size format
// lucidasans-10
//
// 3) Name-style-size
// lucidasans-bold-10
//
// 4) Name only (implicit size)
// 6x13
//
//--------------------------------------------------
NS_IMETHODIMP nsFontRetrieverService::LoadFontList()
{
char * pattern = "*";
int nnames = 1024;
int available = nnames+1;
int i;
char **fonts;
XFontStruct *info;
if (nsnull == mFontList) {
mFontList = new nsVoidArray();
if (nsnull == mFontList) {
return NS_ERROR_FAILURE;
}
}
/* Get list of fonts matching pattern */
for (;;) {
// the following line is VERY slow to return
fonts = XListFontsWithInfo(GDK_DISPLAY(), pattern, nnames,
&available, &info);
if (fonts == NULL || available < nnames)
break;
XFreeFontInfo(fonts, info, available);
nnames = available * 2;
}
if (fonts == NULL) {
fprintf(stderr, "pattern \"%s\" unmatched\n", pattern);
return NS_ERROR_FAILURE;
}
#if 0 // debug
// print out all the retrieved fonts
printf("-----------------------------\n");
for (i=0; i<available; i++) {
printf("[%s]i\n", fonts[i]);
}
printf("-----------------------------\n");
#endif
// this code assumes all like fonts are grouped together
// currentName is the current name of the font we are gathering
// sizes for, when the name changes we create a new FontInfo object
// but it also takes into account fonts of similar names when it
// goes to add then and disregards duplicates
char buffer[1024];
char currentName[1024];
FontInfo * font = nsnull;
currentName[0] = 0;
for (i=0; i<available; i++) {
// This is kind of lame, but it will have to do for now
strcpy(buffer, fonts[i]);
// Start by checking to see if the name begins with a dash
char * ptr = buffer;
if (buffer[0] == '-') { //Format #1
PRInt32 cnt = 0;
// skip first two '-'
do {
if (*ptr == '-') cnt++;
ptr++;
} while (cnt < 2);
// find the dash at the end of the name
char * end = strchr(ptr, '-');
if (end) {
*end = 0;
// Check to see if we need to create a new FontInfo obj
// and set the currentName var to this guys font name
if (strcmp(currentName, ptr) || NULL == font) {
font = GetFontInfo(mFontList, ptr);
strcpy(currentName, ptr);
}
if (nsnull == font->mSizes) {
font->mSizes = new nsVoidArray();
}
ptr = end+1; // skip past the dash that was set to zero
cnt = 0;
// now skip ahead 4 dashes
do {
if (*ptr == '-') cnt++;
ptr++;
} while (cnt < 4);
// find the dash after the size
end = strchr(ptr, '-');
if (end) {
*end = 0;
PRInt32 size;
sscanf(ptr, "%d", &size);
AddSizeToFontInfo(font, size);
}
}
} else { // formats 2,3,4
// no leading dash means the start of the
// buffer is the start of the name
// this checks for a dash at the end of the font name
// which means there is a size at the end
char * end = strchr(buffer, '-');
if (end) { // Format 2,3
*end = 0;
// Check to see if we need to create a new FontInfo obj
// and set the currentName var to this guys font name
if (strcmp(currentName, buffer) || NULL == font) {
font = GetFontInfo(mFontList, buffer);
strcpy(currentName, buffer);
}
end++; // advance past the dash
// check to see if we have a number
ptr = end;
if (isalpha(*ptr)) { // Format 3
// skip until next dash
end = strchr(ptr, '-');
if (end) {
*end = 0;
ptr = end+1;
}
}
PRInt32 size;
// yes, it has a dash at the end so it must have the size
// check to see if the size is terminated by a dash
// it shouldn't be
char * end2 = strchr(ptr, '-');
if (end2) *end2 = 0; // put terminator at the dash
sscanf(end, "%d", &size);
AddSizeToFontInfo(font, size);
} else { // Format #4
// The font has an implicit size,
// so there is nothing to parse for size
// so we can't really do much here
// Check to see if we need to create a new FontInfo obj
// and set the currentName var to this guys font name
if (strcmp(currentName, buffer) || NULL == font) {
font = GetFontInfo(mFontList, buffer);
strcpy(currentName, buffer);
}
}
}
}
XFreeFontInfo(fonts, info, available);
return NS_OK;
}
//----------------------------------------------------------
NS_IMETHODIMP nsFontRetrieverService::IsFontScalable(const nsString & aFontName,
PRBool* aResult )
{
// save value in case someone externally is using it
PRInt32 saveIterInx = mNameIterInx;
PRBool found = PR_FALSE;
Reset();
do {
nsAutoString name;
Get(&name);
if (name.Equals(aFontName)) {
found = PR_TRUE;
break;
}
} while (Advance() == NS_OK);
if (found) {
FontInfo * fontInfo = (FontInfo *)mFontList->ElementAt(mNameIterInx);
*aResult = fontInfo->mIsScalable;
mNameIterInx = saveIterInx;
return NS_OK;
}
mNameIterInx = saveIterInx;
return NS_ERROR_FAILURE;
}

View File

@@ -0,0 +1,65 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef __nsFontRetrieverService
#define __nsFontRetrieverService
#include "nsIFontRetrieverService.h"
#include "nsIFontNameIterator.h"
class nsVoidArray;
class nsFontSizeIterator;
class nsFontRetrieverService: public nsIFontRetrieverService,
public nsIFontNameIterator
{
public:
nsFontRetrieverService();
virtual ~nsFontRetrieverService();
NS_DECL_ISUPPORTS
// nsIFontRetrieverService
NS_IMETHOD CreateFontNameIterator( nsIFontNameIterator** aIterator );
NS_IMETHOD CreateFontSizeIterator( const nsString & aFontName, nsIFontSizeIterator** aIterator );
NS_IMETHOD IsFontScalable( const nsString & aFontName, PRBool* aResult );
// nsIFontNameIterator
NS_IMETHOD Reset();
NS_IMETHOD Get( nsString* aFontName );
NS_IMETHOD Advance();
protected:
NS_IMETHOD LoadFontList();
nsVoidArray * mFontList;
PRInt32 mNameIterInx;
nsFontSizeIterator * mSizeIter;
};
#endif

View File

@@ -0,0 +1,88 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsFontSizeIterator.h"
#include "nsFont.h"
#include "nsVoidArray.h"
NS_IMPL_ADDREF(nsFontSizeIterator)
NS_IMPL_RELEASE(nsFontSizeIterator)
NS_IMPL_QUERY_INTERFACE(nsFontSizeIterator, nsIFontSizeIterator::GetIID())
//----------------------------------------------------------
nsFontSizeIterator::nsFontSizeIterator()
{
NS_INIT_REFCNT();
mFontInfo = nsnull;
mSizeIterInx = 0;
}
//----------------------------------------------------------
nsFontSizeIterator::~nsFontSizeIterator()
{
}
///----------------------------------------------------------
//-- nsIFontNameIterator
//----------------------------------------------------------
NS_IMETHODIMP nsFontSizeIterator::Reset()
{
mSizeIterInx = 0;
return NS_OK;
}
//----------------------------------------------------------
NS_IMETHODIMP nsFontSizeIterator::Get( double* aFontSize )
{
if (nsnull != mFontInfo->mSizes &&
mFontInfo->mSizes->Count() > 0 &&
mSizeIterInx < mFontInfo->mSizes->Count()) {
PRUint32 size = (PRUint32)mFontInfo->mSizes->ElementAt(mSizeIterInx);
*aFontSize = (double)size;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
//----------------------------------------------------------
NS_IMETHODIMP nsFontSizeIterator::Advance()
{
if (nsnull != mFontInfo->mSizes &&
mFontInfo->mSizes->Count() > 0 &&
mSizeIterInx < mFontInfo->mSizes->Count()-2) {
mSizeIterInx++;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
//----------------------------------------------------------
NS_IMETHODIMP nsFontSizeIterator::SetFontInfo( FontInfo * aFontInfo )
{
mFontInfo = aFontInfo;
return NS_OK;
}

View File

@@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
@@ -20,31 +20,40 @@
* Contributor(s):
*/
#ifndef nsSupportsArrayEnumerator_h___
#define nsSupportsArrayEnumerator_h___
#ifndef __nsFontSizeIterator
#define __nsFontSizeIterator
#include "nsIEnumerator.h"
#include "nsIFontSizeIterator.h"
#include "nsString.h"
class nsISupportsArray;
class nsVoidArray;
class NS_COM nsSupportsArrayEnumerator : public nsIBidirectionalEnumerator {
typedef struct {
nsString mName;
PRBool mIsScalable;
nsVoidArray * mSizes;
} FontInfo;
class nsFontSizeIterator: public nsIFontSizeIterator {
public:
nsFontSizeIterator();
virtual ~nsFontSizeIterator();
NS_DECL_ISUPPORTS
nsSupportsArrayEnumerator(nsISupportsArray* array);
virtual ~nsSupportsArrayEnumerator();
// nsIFontSizeIterator
NS_IMETHOD Reset();
NS_IMETHOD Get( double* aFontSize );
NS_IMETHOD Advance();
// nsIEnumerator methods:
NS_DECL_NSIENUMERATOR
// nsIBidirectionalEnumerator methods:
NS_DECL_NSIBIDIRECTIONALENUMERATOR
// Native impl
NS_IMETHOD SetFontInfo( FontInfo * aFontInfo );
protected:
nsISupportsArray* mArray;
PRInt32 mCursor;
FontInfo * mFontInfo;
PRInt32 mSizeIterInx; // current index of iter
};
#endif // __nsSupportsArrayEnumerator_h
#endif

View File

@@ -0,0 +1,967 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsWidget.h"
#include "nsWindow.h"
#include "nsScrollbar.h"
#include "nsIFileWidget.h"
#include "nsGUIEvent.h"
#include "nsIMenu.h"
#include "nsIMenuItem.h"
#include "nsIMenuListener.h"
#include "nsTextWidget.h"
#include "nsICharsetConverterManager.h"
#include "nsIPlatformCharset.h"
#include "nsIServiceManager.h"
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
#include "stdio.h"
#include "ctype.h"
#include "gtk/gtk.h"
#include "nsGtkEventHandler.h"
#include <gdk/gdkkeysyms.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#ifdef DEBUG_pavlov
//#define DEBUG_EVENTS 1
#endif
struct EventInfo {
nsWidget *widget; // the widget
nsRect *rect; // the rect
};
//==============================================================
void InitAllocationEvent(GtkAllocation *aAlloc,
gpointer p,
nsSizeEvent &anEvent,
PRUint32 aEventType)
{
anEvent.message = aEventType;
anEvent.widget = (nsWidget *) p;
anEvent.eventStructType = NS_SIZE_EVENT;
if (aAlloc != nsnull) {
// HACK
// nsRect *foo = new nsRect(aAlloc->x, aAlloc->y, aAlloc->width, aAlloc->height);
nsRect *foo = new nsRect(0, 0, aAlloc->width, aAlloc->height);
anEvent.windowSize = foo;
// anEvent.point.x = aAlloc->x;
// anEvent.point.y = aAlloc->y;
// HACK
anEvent.point.x = 0;
anEvent.point.y = 0;
anEvent.mWinWidth = aAlloc->width;
anEvent.mWinHeight = aAlloc->height;
}
anEvent.time = PR_IntervalNow();
}
//==============================================================
void InitConfigureEvent(GdkEventConfigure *aConf,
gpointer p,
nsSizeEvent &anEvent,
PRUint32 aEventType)
{
anEvent.message = aEventType;
anEvent.widget = (nsWidget *) p;
anEvent.eventStructType = NS_SIZE_EVENT;
if (aConf != nsnull) {
/* do we accually need to alloc a new rect, or can we just set the
current one */
nsRect *foo = new nsRect(aConf->x, aConf->y, aConf->width, aConf->height);
anEvent.windowSize = foo;
anEvent.point.x = aConf->x;
anEvent.point.y = aConf->y;
anEvent.mWinWidth = aConf->width;
anEvent.mWinHeight = aConf->height;
}
// this usually returns 0
anEvent.time = 0;
}
//==============================================================
void InitExposeEvent(GdkEventExpose *aGEE,
gpointer p,
nsPaintEvent &anEvent,
PRUint32 aEventType)
{
anEvent.message = aEventType;
anEvent.widget = (nsWidget *) p;
anEvent.eventStructType = NS_PAINT_EVENT;
if (aGEE != nsnull)
{
#ifdef DEBUG_EVENTS
g_print("expose event: x = %i , y = %i , w = %i , h = %i\n",
aGEE->area.x, aGEE->area.y,
aGEE->area.width, aGEE->area.height);
#endif
anEvent.point.x = aGEE->area.x;
anEvent.point.y = aGEE->area.y;
nsRect *rect = new nsRect(aGEE->area.x, aGEE->area.y,
aGEE->area.width, aGEE->area.height);
anEvent.rect = rect;
anEvent.time = gdk_event_get_time((GdkEvent*)aGEE);
}
}
//=============================================================
void UninitExposeEvent(GdkEventExpose *aGEE,
gpointer p,
nsPaintEvent &anEvent,
PRUint32 aEventType)
{
if (aGEE != nsnull) {
delete anEvent.rect;
}
}
struct nsKeyConverter {
int vkCode; // Platform independent key code
int keysym; // GDK keysym key code
};
//
// Netscape keycodes are defined in widget/public/nsGUIEvent.h
// GTK keycodes are defined in <gdk/gdkkeysyms.h>
//
struct nsKeyConverter nsKeycodes[] = {
{ NS_VK_CANCEL, GDK_Cancel },
{ NS_VK_BACK, GDK_BackSpace },
{ NS_VK_TAB, GDK_Tab },
{ NS_VK_TAB, GDK_ISO_Left_Tab },
{ NS_VK_CLEAR, GDK_Clear },
{ NS_VK_RETURN, GDK_Return },
{ NS_VK_SHIFT, GDK_Shift_L },
{ NS_VK_SHIFT, GDK_Shift_R },
{ NS_VK_CONTROL, GDK_Control_L },
{ NS_VK_CONTROL, GDK_Control_R },
{ NS_VK_ALT, GDK_Alt_L },
{ NS_VK_ALT, GDK_Alt_R },
{ NS_VK_PAUSE, GDK_Pause },
{ NS_VK_CAPS_LOCK, GDK_Caps_Lock },
{ NS_VK_ESCAPE, GDK_Escape },
{ NS_VK_SPACE, GDK_space },
{ NS_VK_PAGE_UP, GDK_Page_Up },
{ NS_VK_PAGE_DOWN, GDK_Page_Down },
{ NS_VK_END, GDK_End },
{ NS_VK_HOME, GDK_Home },
{ NS_VK_LEFT, GDK_Left },
{ NS_VK_UP, GDK_Up },
{ NS_VK_RIGHT, GDK_Right },
{ NS_VK_DOWN, GDK_Down },
{ NS_VK_PRINTSCREEN, GDK_Print },
{ NS_VK_INSERT, GDK_Insert },
{ NS_VK_DELETE, GDK_Delete },
{ NS_VK_MULTIPLY, GDK_KP_Multiply },
{ NS_VK_ADD, GDK_KP_Add },
{ NS_VK_SEPARATOR, GDK_KP_Separator },
{ NS_VK_SUBTRACT, GDK_KP_Subtract },
{ NS_VK_DECIMAL, GDK_KP_Decimal },
{ NS_VK_DIVIDE, GDK_KP_Divide },
{ NS_VK_RETURN, GDK_KP_Enter },
// NS doesn't have dash or equals distinct from the numeric keypad ones,
// so we'll use those for now. See bug 17008:
{ NS_VK_SUBTRACT, GDK_minus },
{ NS_VK_EQUALS, GDK_equal },
// and we don't have a single-quote symbol either:
{ NS_VK_QUOTE, GDK_apostrophe },
{ NS_VK_COMMA, GDK_comma },
{ NS_VK_PERIOD, GDK_period },
{ NS_VK_SLASH, GDK_slash },
{ NS_VK_BACK_SLASH, GDK_backslash },
{ NS_VK_BACK_QUOTE, GDK_grave },
{ NS_VK_OPEN_BRACKET, GDK_bracketleft },
{ NS_VK_CLOSE_BRACKET, GDK_bracketright },
{ NS_VK_QUOTE, GDK_quotedbl },
// Some shifted keys, see bug 15463.
// These should be subject to different keyboard mappings;
// how do we do that in gtk?
{ NS_VK_SEMICOLON, GDK_colon },
{ NS_VK_BACK_QUOTE, GDK_asciitilde },
{ NS_VK_COMMA, GDK_less },
{ NS_VK_PERIOD, GDK_greater },
{ NS_VK_SLASH, GDK_question },
{ NS_VK_1, GDK_exclam },
{ NS_VK_2, GDK_at },
{ NS_VK_3, GDK_numbersign },
{ NS_VK_4, GDK_dollar },
{ NS_VK_5, GDK_percent },
{ NS_VK_6, GDK_asciicircum },
{ NS_VK_7, GDK_ampersand },
{ NS_VK_8, GDK_asterisk },
{ NS_VK_9, GDK_parenleft },
{ NS_VK_0, GDK_parenright },
{ NS_VK_SUBTRACT, GDK_underscore },
{ NS_VK_EQUALS, GDK_plus }
};
void nsGtkWidget_InitNSKeyEvent(int aEventType, nsKeyEvent& aKeyEvent,
GtkWidget *w, gpointer p, GdkEventKey * event);
//==============================================================
// Input keysym is in gtk format; output is in NS_VK format
int nsPlatformToDOMKeyCode(GdkEventKey *aGEK)
{
int i;
int length = sizeof(nsKeycodes) / sizeof(struct nsKeyConverter);
int keysym = aGEK->keyval;
// First, try to handle alphanumeric input, not listed in nsKeycodes:
// most likely, more letters will be getting typed in than things in
// the key list, so we will look through these first.
// since X has different key symbols for upper and lowercase letters and
// mozilla does not, convert gdk's to mozilla's
if (keysym >= GDK_a && keysym <= GDK_z)
return keysym - GDK_a + NS_VK_A;
if (keysym >= GDK_A && keysym <= GDK_Z)
return keysym - GDK_A + NS_VK_A;
// numbers
if (keysym >= GDK_0 && keysym <= GDK_9)
return keysym - GDK_0 + NS_VK_0;
// keypad numbers
if (keysym >= GDK_KP_0 && keysym <= GDK_KP_9)
return keysym - GDK_KP_0 + NS_VK_NUMPAD0;
// misc other things
for (i = 0; i < length; i++) {
if (nsKeycodes[i].keysym == keysym)
return(nsKeycodes[i].vkCode);
}
// function keys
if (keysym >= GDK_F1 && keysym <= GDK_F24)
return keysym - GDK_F1 + NS_VK_F1;
#if defined(DEBUG_akkana) || defined(DEBUG_ftang)
printf("No match in nsPlatformToDOMKeyCode: keysym is 0x%x, string is %s\n", keysym, aGEK->string);
#endif
return((int)0);
}
//==============================================================
PRUint32 nsConvertCharCodeToUnicode(GdkEventKey* aGEK)
{
// For control chars, GDK sets string to be the actual ascii value.
// Map that to what nsKeyEvent wants, which currently --
// TEMPORARILY (the spec has changed and will be switched over
// when the tree opens for M11) --
// is the ascii for the actual event (e.g. 1 for control-a).
// This is only true for control chars; for alt chars, send the
// ascii for the key, i.e. a for alt-a.
if (aGEK->state & GDK_CONTROL_MASK)
{
if (aGEK->state & GDK_SHIFT_MASK)
return aGEK->string[0] + 'A' - 1;
else
return aGEK->string[0] + 'a' - 1;
}
// For now (obviously this will need to change for IME),
// only set a char code if the result is printable:
if (!isprint(aGEK->string[0]))
return 0;
// ALT keys in gdk give the upper case character in string,
// but we want the lower case char in char code
// unless shift was also pressed.
if (((aGEK->state & GDK_MOD1_MASK))
&& !(aGEK->state & GDK_SHIFT_MASK)
&& isupper(aGEK->string[0]))
return tolower(aGEK->string[0]);
//
// placeholder for something a little more interesting and correct
//
return aGEK->string[0];
}
//==============================================================
void InitKeyEvent(GdkEventKey *aGEK,
gpointer p,
nsKeyEvent &anEvent,
PRUint32 aEventType)
{
anEvent.message = aEventType;
anEvent.widget = (nsWidget *) p;
anEvent.eventStructType = NS_KEY_EVENT;
if (aGEK != nsnull) {
anEvent.keyCode = nsPlatformToDOMKeyCode(aGEK);
anEvent.charCode = 0;
anEvent.time = aGEK->time;
anEvent.isShift = (aGEK->state & GDK_SHIFT_MASK) ? PR_TRUE : PR_FALSE;
anEvent.isControl = (aGEK->state & GDK_CONTROL_MASK) ? PR_TRUE : PR_FALSE;
anEvent.isAlt = (aGEK->state & GDK_MOD1_MASK) ? PR_TRUE : PR_FALSE;
// XXX
anEvent.isMeta = PR_FALSE; //(aGEK->state & GDK_MOD2_MASK) ? PR_TRUE : PR_FALSE;
anEvent.point.x = 0;
anEvent.point.y = 0;
}
}
void InitKeyPressEvent(GdkEventKey *aGEK,
gpointer p,
nsKeyEvent &anEvent)
{
//
// init the basic event fields
//
anEvent.eventStructType = NS_KEY_EVENT;
anEvent.message = NS_KEY_PRESS;
anEvent.widget = (nsWidget*)p;
if (aGEK!=nsnull)
{
anEvent.isShift = (aGEK->state & GDK_SHIFT_MASK) ? PR_TRUE : PR_FALSE;
anEvent.isControl = (aGEK->state & GDK_CONTROL_MASK) ? PR_TRUE : PR_FALSE;
anEvent.isAlt = (aGEK->state & GDK_MOD1_MASK) ? PR_TRUE : PR_FALSE;
// XXX
anEvent.isMeta = PR_FALSE; //(aGEK->state & GDK_MOD2_MASK) ? PR_TRUE : PR_FALSE;
if(aGEK->length)
anEvent.charCode = nsConvertCharCodeToUnicode(aGEK);
else
anEvent.charCode = 0;
if (anEvent.charCode) {
anEvent.keyCode = 0;
anEvent.isShift = PR_FALSE;
} else
anEvent.keyCode = nsPlatformToDOMKeyCode(aGEK);
#if defined(DEBUG_akkana) || defined(DEBUG_pavlov) || defined (DEBUG_ftang)
printf("Key Press event: keyCode = 0x%x, char code = '%c'",
anEvent.keyCode, anEvent.charCode);
if (anEvent.isShift)
printf(" [shift]");
if (anEvent.isControl)
printf(" [ctrl]");
if (anEvent.isAlt)
printf(" [alt]");
if (anEvent.isMeta)
printf(" [meta]");
printf("\n");
#endif
anEvent.time = aGEK->time;
anEvent.point.x = 0;
anEvent.point.y = 0;
}
}
//=============================================================
void UninitKeyEvent(GdkEventKey *aGEK,
gpointer p,
nsKeyEvent &anEvent,
PRUint32 aEventType)
{
}
/*==============================================================
==============================================================
=============================================================
==============================================================*/
void handle_size_allocate(GtkWidget *w, GtkAllocation *alloc, gpointer p)
{
nsWindow *widget = (nsWindow *)p;
nsSizeEvent event;
InitAllocationEvent(alloc, p, event, NS_SIZE);
NS_ADDREF(widget);
widget->OnResize(event);
NS_RELEASE(widget);
delete event.windowSize;
}
gint handle_expose_event(GtkWidget *w, GdkEventExpose *event, gpointer p)
{
if (event->type == GDK_NO_EXPOSE)
return PR_FALSE;
nsPaintEvent pevent;
InitExposeEvent(event, p, pevent, NS_PAINT);
nsWindow *win = (nsWindow *)p;
win->AddRef();
win->OnExpose(pevent);
win->Release();
UninitExposeEvent(event, p, pevent, NS_PAINT);
return PR_TRUE;
}
//==============================================================
void menu_item_activate_handler(GtkWidget *w, gpointer p)
{
// g_print("menu_item_activate_handler\n");
nsIMenuListener *menuListener = nsnull;
nsIMenuItem *menuItem = (nsIMenuItem *)p;
if (menuItem != nsnull) {
nsMenuEvent mevent;
mevent.message = NS_MENU_SELECTED;
mevent.eventStructType = NS_MENU_EVENT;
mevent.point.x = 0;
mevent.point.y = 0;
// mevent.widget = menuItem;
mevent.widget = nsnull;
menuItem->GetCommand(mevent.mCommand);
mevent.mMenuItem = menuItem;
mevent.time = PR_IntervalNow();
// FIXME - THIS SHOULD WORK. FIX EVENTS FOR XP CODE!!!!! (pav)
// nsEventStatus status;
// mevent.widget->DispatchEvent((nsGUIEvent *)&mevent, status);
menuItem->QueryInterface(nsIMenuListener::GetIID(), (void**)&menuListener);
if(menuListener) {
menuListener->MenuItemSelected(mevent);
NS_IF_RELEASE(menuListener);
}
}
}
//==============================================================
void menu_map_handler(GtkWidget *w, gpointer p)
{
nsIMenuListener *menuListener = nsnull;
nsIMenu *menu = (nsIMenu *)p;
if (menu != nsnull) {
nsMenuEvent mevent;
mevent.message = NS_MENU_SELECTED;
mevent.eventStructType = NS_MENU_EVENT;
mevent.point.x = 0;
mevent.point.y = 0;
mevent.widget = nsnull;
mevent.time = PR_IntervalNow();
menu->QueryInterface(nsIMenuListener::GetIID(), (void**)&menuListener);
if(menuListener) {
menuListener->MenuConstruct(
mevent,
nsnull, //parent window
nsnull, //menuNode
nsnull ); // webshell
NS_IF_RELEASE(menuListener);
}
}
}
//==============================================================
void menu_unmap_handler(GtkWidget *w, gpointer p)
{
nsIMenuListener *menuListener = nsnull;
nsIMenu *menu = (nsIMenu *)p;
if (menu != nsnull) {
nsMenuEvent mevent;
mevent.message = NS_MENU_SELECTED;
mevent.eventStructType = NS_MENU_EVENT;
mevent.point.x = 0;
mevent.point.y = 0;
mevent.widget = nsnull;
mevent.time = PR_IntervalNow();
menu->QueryInterface(nsIMenuListener::GetIID(), (void**)&menuListener);
if(menuListener) {
menuListener->MenuDestruct(mevent);
NS_IF_RELEASE(menuListener);
}
}
}
//==============================================================
void handle_scrollbar_value_changed(GtkAdjustment *adj, gpointer p)
{
nsScrollbar *widget = (nsScrollbar*) p;
nsScrollbarEvent sevent;
sevent.message = NS_SCROLLBAR_POS;
sevent.widget = (nsWidget *) p;
sevent.eventStructType = NS_SCROLLBAR_EVENT;
GdkWindow *win = (GdkWindow *)widget->GetNativeData(NS_NATIVE_WINDOW);
gdk_window_get_pointer(win, &sevent.point.x, &sevent.point.y, nsnull);
widget->AddRef();
widget->OnScroll(sevent, adj->value);
widget->Release();
/* FIXME we need to set point.* from the event stuff. */
#if 0
nsWindow * widgetWindow = (nsWindow *) p ;
XmScrollBarCallbackStruct * cbs = (XmScrollBarCallbackStruct*) call_data;
sevent.widget = (nsWindow *) p;
if (cbs->event != nsnull) {
sevent.point.x = cbs->event->xbutton.x;
sevent.point.y = cbs->event->xbutton.y;
} else {
sevent.point.x = 0;
sevent.point.y = 0;
}
sevent.time = 0; //XXX Implement this
switch (cbs->reason) {
case XmCR_INCREMENT:
sevent.message = NS_SCROLLBAR_LINE_NEXT;
break;
case XmCR_DECREMENT:
sevent.message = NS_SCROLLBAR_LINE_PREV;
break;
case XmCR_PAGE_INCREMENT:
sevent.message = NS_SCROLLBAR_PAGE_NEXT;
break;
case XmCR_PAGE_DECREMENT:
sevent.message = NS_SCROLLBAR_PAGE_PREV;
break;
case XmCR_DRAG:
sevent.message = NS_SCROLLBAR_POS;
break;
case XmCR_VALUE_CHANGED:
sevent.message = NS_SCROLLBAR_POS;
break;
default:
break;
}
#endif
}
static gint composition_start(GdkEventKey *aEvent, nsWindow *aWin,
nsEventStatus *aStatus) {
nsCompositionEvent compEvent;
compEvent.widget = (nsWidget*)aWin;
compEvent.point.x = 0;
compEvent.point.y = 0;
compEvent.time = aEvent->time;
compEvent.message = NS_COMPOSITION_START;
compEvent.eventStructType = NS_COMPOSITION_START;
compEvent.compositionMessage = NS_COMPOSITION_START;
aWin->DispatchEvent(&compEvent, *aStatus);
// set SpotLocation
aWin->SetXICSpotLocation(compEvent.theReply.mCursorPosition);
return PR_TRUE;
}
static gint composition_draw(GdkEventKey *aEvent, nsWindow *aWin,
nsIUnicodeDecoder *aDecoder,
nsEventStatus *aStatus) {
if (!aWin->mIMECompositionUniString) {
aWin->mIMECompositionUniStringSize = 128;
aWin->mIMECompositionUniString =
new PRUnichar[aWin->mIMECompositionUniStringSize];
}
PRUnichar *uniChar;
PRInt32 uniCharSize;
PRInt32 srcLen = aEvent->length;
for (;;) {
uniChar = aWin->mIMECompositionUniString;
uniCharSize = aWin->mIMECompositionUniStringSize - 1;
aDecoder->Convert((char*)aEvent->string, &srcLen, uniChar, &uniCharSize);
if (srcLen == aEvent->length &&
uniCharSize < aWin->mIMECompositionUniStringSize - 1) {
break;
}
aWin->mIMECompositionUniStringSize += 32;
aWin->mIMECompositionUniString =
new PRUnichar[aWin->mIMECompositionUniStringSize];
}
aWin->mIMECompositionUniString[uniCharSize] = 0;
nsTextEvent textEvent;
textEvent.message = NS_TEXT_EVENT;
textEvent.widget = (nsWidget*)aWin;
textEvent.time = aEvent->time;
textEvent.point.x = 0;
textEvent.point.y = 0;
textEvent.theText = aWin->mIMECompositionUniString;
textEvent.rangeCount = 0;
textEvent.rangeArray = nsnull;
textEvent.isShift = (aEvent->state & GDK_SHIFT_MASK) ? PR_TRUE : PR_FALSE;
textEvent.isControl = (aEvent->state & GDK_CONTROL_MASK) ? PR_TRUE : PR_FALSE;
textEvent.isAlt = (aEvent->state & GDK_MOD1_MASK) ? PR_TRUE : PR_FALSE;
// XXX
textEvent.isMeta = PR_FALSE; //(aEvent->state & GDK_MOD2_MASK) ? PR_TRUE : PR_FALSE;
textEvent.eventStructType = NS_TEXT_EVENT;
aWin->DispatchEvent(&textEvent, *aStatus);
aWin->SetXICSpotLocation(textEvent.theReply.mCursorPosition);
return True;
}
static gint composition_end(GdkEventKey *aEvent, nsWindow *aWin,
nsEventStatus *aStatus) {
nsCompositionEvent compEvent;
compEvent.widget = (nsWidget*)aWin;
compEvent.point.x = 0;
compEvent.point.y = 0;
compEvent.time = aEvent->time;
compEvent.message = NS_COMPOSITION_END;
compEvent.eventStructType = NS_COMPOSITION_END;
compEvent.compositionMessage = NS_COMPOSITION_END;
aWin->DispatchEvent(&compEvent, *aStatus);
return PR_TRUE;
}
static nsIUnicodeDecoder*
open_unicode_decoder(void) {
nsresult result = NS_ERROR_FAILURE;
nsIUnicodeDecoder *decoder = nsnull;
NS_WITH_SERVICE(nsIPlatformCharset, platform, NS_PLATFORMCHARSET_PROGID,
&result);
if (platform && NS_SUCCEEDED(result)) {
nsAutoString charset("");
result = platform->GetCharset(kPlatformCharsetSel_Menu, charset);
if (NS_FAILED(result) || (charset.Length() == 0)) {
charset = "ISO-8859-1"; // default
}
nsICharsetConverterManager* manager = nsnull;
nsresult res = nsServiceManager::
GetService(kCharsetConverterManagerCID,
nsCOMTypeInfo<nsICharsetConverterManager>::GetIID(),
(nsISupports**)&manager);
if (manager && NS_SUCCEEDED(res)) {
manager->GetUnicodeDecoder(&charset, &decoder);
nsServiceManager::ReleaseService(kCharsetConverterManagerCID, manager);
}
}
return decoder;
}
// GTK's text widget already does XIM, so we don't want to do this again
gint handle_key_press_event_for_text(GtkObject *w, GdkEventKey* event,
gpointer p)
{
nsKeyEvent kevent;
nsTextWidget* win = (nsTextWidget*)p;
// work around for annoying things.
if (event->keyval == GDK_Tab)
if (event->state & GDK_CONTROL_MASK)
if (event->state & GDK_MOD1_MASK)
return PR_FALSE;
// Don't pass shift, control and alt as key press events
if (event->keyval == GDK_Shift_L
|| event->keyval == GDK_Shift_R
|| event->keyval == GDK_Control_L
|| event->keyval == GDK_Control_R)
return PR_TRUE;
win->AddRef();
InitKeyEvent(event, p, kevent, NS_KEY_DOWN);
win->OnKey(kevent);
//
// Second, dispatch the Key event as a key press event w/ a Unicode
// character code. Note we have to check for modifier keys, since
// gtk returns a character value for them
//
InitKeyPressEvent(event,p, kevent);
win->OnKey(kevent);
win->Release();
if (w)
{
gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_press_event");
}
return PR_TRUE;
}
// GTK's text widget already does XIM, so we don't want to do this again
gint handle_key_release_event_for_text(GtkObject *w, GdkEventKey* event,
gpointer p)
{
nsKeyEvent kevent;
nsTextWidget* win = (nsTextWidget*)p;
// Don't pass shift, control and alt as key release events
if (event->keyval == GDK_Shift_L
|| event->keyval == GDK_Shift_R
|| event->keyval == GDK_Control_L
|| event->keyval == GDK_Control_R)
return PR_TRUE;
InitKeyEvent(event, p, kevent, NS_KEY_UP);
win->AddRef();
win->OnKey(kevent);
win->Release();
if (w)
{
gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_release_event");
}
return PR_TRUE;
}
//==============================================================
gint handle_key_press_event(GtkObject *w, GdkEventKey* event, gpointer p)
{
nsKeyEvent kevent;
nsWindow* win = (nsWindow*)p;
// work around for annoying things.
if (event->keyval == GDK_Tab)
if (event->state & GDK_CONTROL_MASK)
if (event->state & GDK_MOD1_MASK)
return PR_FALSE;
// Don't pass shift, control and alt as key press events
if (event->keyval == GDK_Shift_L
|| event->keyval == GDK_Shift_R
|| event->keyval == GDK_Control_L
|| event->keyval == GDK_Control_R)
return PR_TRUE;
win->AddRef();
//
// First, dispatch the Key event as a virtual key down event
//
InitKeyEvent(event, p, kevent, NS_KEY_DOWN);
win->OnKey(kevent);
//
// Second, dispatch the Key event as a key press event w/ a Unicode
// character code. Note we have to check for modifier keys, since
// gtk returns a character value for them
//
if (event->length) {
static nsIUnicodeDecoder *decoder = nsnull;
if (!decoder) {
decoder = open_unicode_decoder();
}
if (decoder && (!kevent.keyCode)) {
nsEventStatus status;
composition_start(event, win, &status);
composition_draw(event, win, decoder, &status);
composition_end(event, win, &status);
} else {
InitKeyPressEvent(event,p, kevent);
win->OnKey(kevent);
nsEventStatus status;
composition_start(event, win, &status);
composition_end(event, win, &status);
}
} else { // for Home/End/Up/Down/Left/Right/PageUp/PageDown key
InitKeyPressEvent(event,p, kevent);
win->OnKey(kevent);
}
win->Release();
if (w)
{
gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_press_event");
}
return PR_TRUE;
}
//==============================================================
gint handle_key_release_event(GtkObject *w, GdkEventKey* event, gpointer p)
{
// Don't pass shift, control and alt as key release events
if (event->keyval == GDK_Shift_L
|| event->keyval == GDK_Shift_R
|| event->keyval == GDK_Control_L
|| event->keyval == GDK_Control_R)
return PR_TRUE;
nsKeyEvent kevent;
InitKeyEvent(event, p, kevent, NS_KEY_UP);
nsWindow * win = (nsWindow *) p;
win->AddRef();
win->OnKey(kevent);
win->Release();
if (w)
{
gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_release_event");
}
return PR_TRUE;
}
//==============================================================
void
handle_gdk_event (GdkEvent *event, gpointer data)
{
GtkObject *object = nsnull;
if (event->any.window)
gdk_window_get_user_data (event->any.window, (void **)&object);
if (object != nsnull &&
GDK_IS_SUPERWIN (object))
{
// It was an event on one of our superwindows
nsWindow *window = (nsWindow *)gtk_object_get_data (object, "nsWindow");
if (gtk_grab_get_current () != nsnull)
{
// A GTK+ grab is in effect. Rewrite the event to point to
// our toplevel, and pass it through.
// XXX: We should actually translate the coordinates
gdk_window_unref (event->any.window);
event->any.window = GTK_WIDGET (window->GetMozArea())->window;
gdk_window_ref (event->any.window);
}
else
{
// Handle it ourselves.
switch (event->type)
{
case GDK_KEY_PRESS:
handle_key_press_event (NULL, &event->key, window);
break;
case GDK_KEY_RELEASE:
handle_key_release_event (NULL, &event->key, window);
break;
default:
window->HandleEvent (event);
}
return;
}
}
gtk_main_do_event (event);
}
//==============================================================
void
handle_xlib_shell_event(GdkSuperWin *superwin, XEvent *event, gpointer p)
{
nsWindow *window = (nsWindow *)p;
switch(event->xany.type) {
case ConfigureNotify:
window->HandleXlibConfigureNotifyEvent(event);
break;
default:
break;
}
}
//==============================================================
void
handle_xlib_bin_event(GdkSuperWin *superwin, XEvent *event, gpointer p)
{
nsWindow *window = (nsWindow *)p;
switch(event->xany.type) {
case Expose:
window->HandleXlibExposeEvent(event);
break;
case ButtonPress:
case ButtonRelease:
window->HandleXlibButtonEvent((XButtonEvent *)event);
break;
case MotionNotify:
window->HandleXlibMotionNotifyEvent((XMotionEvent *) event);
break;
case EnterNotify:
case LeaveNotify:
window->HandleXlibCrossingEvent((XCrossingEvent *) event);
break;
default:
break;
}
}
//==============================================================
gint nsGtkWidget_FSBCancel_Callback(GtkWidget *w, gpointer p)
{
#if 0
nsWindow *widgetWindow = (nsWindow*)gtk_object_get_user_data(GTK_OBJECT(w));
nsFileWidget * widgetWindow = (nsFileWidget *) p ;
if (p != nsnull) {
widgetWindow->OnCancel();
}
#endif
return PR_FALSE;
}
//==============================================================
gint nsGtkWidget_FSBOk_Callback(GtkWidget *w, gpointer p)
{
#if 0
nsWindow *widgetWindow = (nsWindow*)gtk_object_get_user_data(GTK_OBJECT(w));
nsFileWidget * widgetWindow = (nsFileWidget *) p;
if (p != nsnull) {
widgetWindow->OnOk();
}
#endif
return PR_FALSE;
}

View File

@@ -0,0 +1,72 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef __nsGtkEventHandler_h
#define __nsGtkEventHandler_h
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include "gdksuperwin.h"
class nsIWidget;
class nsIMenuItem;
class nsIMenu;
gint handle_configure_event(GtkWidget *w, GdkEventConfigure *conf, gpointer p);
void handle_size_allocate(GtkWidget *w, GtkAllocation *alloc, gpointer p);
gint handle_expose_event(GtkWidget *w, GdkEventExpose *event, gpointer p);
gint handle_key_release_event_for_text(GtkObject *w, GdkEventKey* event, gpointer p);
gint handle_key_press_event_for_text(GtkObject *w, GdkEventKey* event, gpointer p);
gint handle_key_release_event(GtkObject *w, GdkEventKey* event, gpointer p);
gint handle_key_press_event(GtkObject *w, GdkEventKey* event, gpointer p);
void handle_scrollbar_value_changed(GtkAdjustment *adjustment, gpointer p);
void menu_item_activate_handler(GtkWidget *w, gpointer p);
void menu_map_handler(GtkWidget *w, gpointer p);
void menu_unmap_handler(GtkWidget *w, gpointer p);
//----------------------------------------------------
gint nsGtkWidget_FSBCancel_Callback(GtkWidget *w, gpointer p);
gint nsGtkWidget_FSBOk_Callback(GtkWidget *w, gpointer p);
//----------------------------------------------------
gint CheckButton_Toggle_Callback(GtkWidget *w, gpointer p);
gint nsGtkWidget_RadioButton_ArmCallback(GtkWidget *w, gpointer p);
gint nsGtkWidget_RadioButton_DisArmCallback(GtkWidget *w, gpointer p);
gint nsGtkWidget_Text_Callback(GtkWidget *w, GdkEventKey* event, gpointer p);
gint nsGtkWidget_Expose_Callback(GtkWidget *w, gpointer p);
gint nsGtkWidget_Refresh_Callback(gpointer call_data);
void handle_xlib_shell_event(GdkSuperWin *superwin, XEvent *event, gpointer p);
void handle_xlib_bin_event(GdkSuperWin *superwin, XEvent *event, gpointer p);
void handle_gdk_event (GdkEvent *event, gpointer data);
#endif // __nsGtkEventHandler.h

View File

@@ -0,0 +1,213 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <unistd.h>
#include <string.h>
#include "nsGtkUtils.h"
#include <gdk/gdkx.h>
#include <gdk/gdkprivate.h>
#if defined(__osf__) && !defined(_XOPEN_SOURCE_EXTENDED)
/*
** DEC's compiler requires _XOPEN_SOURCE_EXTENDED to be defined in
** order for it to see the prototype for usleep in unistd.h, but if
** we define that the build breaks long before getting here. So
** put the prototype here explicitly.
*/
int usleep(useconds_t);
#endif
#if defined(__QNX__)
#define usleep(s) sleep(s)
#endif
//////////////////////////////////////////////////////////////////
#if 0
/* staitc */ gint
nsGtkUtils::gdk_query_pointer(GdkWindow * window,
gint * x_out,
gint * y_out)
{
g_return_val_if_fail(NULL != window, FALSE);
g_return_val_if_fail(NULL != x_out, FALSE);
g_return_val_if_fail(NULL != y_out, FALSE);
Window root;
Window child;
int rootx, rooty;
int winx = 0;
int winy = 0;
unsigned int xmask = 0;
gint result = FALSE;
*x_out = -1;
*y_out = -1;
result = XQueryPointer(GDK_WINDOW_XDISPLAY(window),
GDK_WINDOW_XWINDOW(window),
&root,
&child,
&rootx,
&rooty,
&winx,
&winy,
&xmask);
if (result)
{
*x_out = rootx;
*y_out = rooty;
}
return result;
}
#endif
//////////////////////////////////////////////////////////////////
/* static */ void
nsGtkUtils::gtk_widget_set_color(GtkWidget * widget,
GtkRcFlags flags,
GtkStateType state,
GdkColor * color)
{
GtkRcStyle * rc_style;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (color != NULL);
g_return_if_fail (flags == 0);
rc_style = (GtkRcStyle *) gtk_object_get_data (GTK_OBJECT (widget),
"modify-style");
if (!rc_style)
{
rc_style = gtk_rc_style_new ();
gtk_widget_modify_style (widget, rc_style);
gtk_object_set_data (GTK_OBJECT (widget), "modify-style", rc_style);
}
if (flags & GTK_RC_FG)
{
rc_style->color_flags[state] = GtkRcFlags(rc_style->color_flags[state] | GTK_RC_FG);
rc_style->fg[state] = *color;
}
if (flags & GTK_RC_BG)
{
rc_style->color_flags[state] = GtkRcFlags(rc_style->color_flags[state] | GTK_RC_BG);
rc_style->bg[state] = *color;
}
if (flags & GTK_RC_TEXT)
{
rc_style->color_flags[state] = GtkRcFlags(rc_style->color_flags[state] | GTK_RC_TEXT);
rc_style->text[state] = *color;
}
if (flags & GTK_RC_BASE)
{
rc_style->color_flags[state] = GtkRcFlags(rc_style->color_flags[state] | GTK_RC_BASE);
rc_style->base[state] = *color;
}
}
//////////////////////////////////////////////////////////////////
/* static */ GdkModifierType
nsGtkUtils::gdk_keyboard_get_modifiers()
{
GdkModifierType m = (GdkModifierType) 0;
gdk_window_get_pointer(NULL,NULL,NULL,&m);
return m;
}
//////////////////////////////////////////////////////////////////
/* static */ void
nsGtkUtils::gdk_window_flash(GdkWindow * aGdkWindow,
unsigned int aTimes,
unsigned long aInterval,
GdkRectangle * aArea)
{
gint x;
gint y;
gint width;
gint height;
guint i;
GdkGC * gc = 0;
GdkColor white;
gdk_window_get_geometry(aGdkWindow,
NULL,
NULL,
&width,
&height,
NULL);
gdk_window_get_origin (aGdkWindow,
&x,
&y);
gc = gdk_gc_new(GDK_ROOT_PARENT());
white.pixel = WhitePixel(gdk_display,DefaultScreen(gdk_display));
gdk_gc_set_foreground(gc,&white);
gdk_gc_set_function(gc,GDK_XOR);
gdk_gc_set_subwindow(gc,GDK_INCLUDE_INFERIORS);
/*
* If an area is given, use that. Notice how out of whack coordinates
* and dimentsions are not checked!!!
*/
if (aArea)
{
x += aArea->x;
y += aArea->y;
width = aArea->width;
height = aArea->height;
}
/*
* Need to do this twice so that the XOR effect can replace
* the original window contents.
*/
for (i = 0; i < aTimes * 2; i++)
{
gdk_draw_rectangle(GDK_ROOT_PARENT(),
gc,
TRUE,
x,
y,
width,
height);
gdk_flush();
usleep(aInterval);
}
gdk_gc_destroy(gc);
}
//////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,85 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef __nsGtkUtils_h
#define __nsGtkUtils_h
#include <gtk/gtk.h>
struct nsGtkUtils
{
//
// Wrapper for XQueryPointer
//
#if 0
static gint gdk_query_pointer(GdkWindow * window,
gint * x_out,
gint * y_out);
#endif
//
// Change a widget's background
//
// flags isa bit mask of the following bits:
//
// GTK_RC_FG
// GTK_RC_BG
// GTK_RC_TEXT
// GTK_RC_BASE
//
// state is an enum:
//
// GTK_STATE_NORMAL,
// GTK_STATE_ACTIVE,
// GTK_STATE_PRELIGHT,
// GTK_STATE_SELECTED,
// GTK_STATE_INSENSITIVE
//
static void gtk_widget_set_color(GtkWidget * widget,
GtkRcFlags flags,
GtkStateType state,
GdkColor * color);
/**
* Return the current keyboard modifier state.
*
* @return the current keyboard modifier state.
*
*/
static GdkModifierType gdk_keyboard_get_modifiers();
/**
* Flash an area within a GDK window (or the whole window)
*
* @param aGdkWindow The GDK window to flash.
* @param aTimes Number of times to flash the area.
* @param aInterval Interval between flashes in milliseconds.
* @param aArea The area to flash. The whole window if NULL.
*
*/
static void gdk_window_flash(GdkWindow * aGdkWindow,
unsigned int aTimes,
unsigned long aInterval,
GdkRectangle * aArea);
};
#endif // __nsGtkEventHandler.h

View File

@@ -0,0 +1,141 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsLabel.h"
#include "nsString.h"
NS_IMPL_ADDREF_INHERITED(nsLabel, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsLabel, nsWidget)
NS_IMPL_QUERY_INTERFACE2(nsLabel, nsILabel, nsIWidget)
//-------------------------------------------------------------------------
//
// nsLabel constructor
//
//-------------------------------------------------------------------------
nsLabel::nsLabel() : nsWidget(), nsILabel()
{
NS_INIT_REFCNT();
mAlignment = eAlign_Left;
}
//-------------------------------------------------------------------------
//
// nsLabel destructor
//
//-------------------------------------------------------------------------
nsLabel::~nsLabel()
{
}
//-------------------------------------------------------------------------
//
// Create the nativeLabel widget
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsLabel::CreateNative(GtkObject *parentWindow)
{
unsigned char alignment = GetNativeAlignment();
mWidget = gtk_label_new("");
gtk_widget_set_name(mWidget, "nsLabel");
gtk_misc_set_alignment(GTK_MISC(mWidget), 0.0, alignment);
return NS_OK;
}
//-------------------------------------------------------------------------
//
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsLabel::PreCreateWidget(nsWidgetInitData *aInitData)
{
if (nsnull != aInitData) {
nsLabelInitData* data = (nsLabelInitData *) aInitData;
mAlignment = data->mAlignment;
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set alignment
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsLabel::SetAlignment(nsLabelAlignment aAlignment)
{
GtkJustification align;
mAlignment = aAlignment;
align = GetNativeAlignment();
gtk_misc_set_alignment(GTK_MISC(mWidget), 0.0, align);
return NS_OK;
}
//-------------------------------------------------------------------------
//
//
//
//-------------------------------------------------------------------------
GtkJustification nsLabel::GetNativeAlignment()
{
switch (mAlignment) {
case eAlign_Right : return GTK_JUSTIFY_RIGHT;
case eAlign_Left : return GTK_JUSTIFY_LEFT;
case eAlign_Center: return GTK_JUSTIFY_CENTER;
default :
return GTK_JUSTIFY_LEFT;
}
return GTK_JUSTIFY_LEFT;
}
//-------------------------------------------------------------------------
//
// Set this button label
//
//-------------------------------------------------------------------------
NS_METHOD nsLabel::SetLabel(const nsString& aText)
{
NS_ALLOC_STR_BUF(label, aText, 256);
gtk_label_set(GTK_LABEL(mWidget), label);
NS_FREE_STR_BUF(label);
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get this button label
//
//-------------------------------------------------------------------------
NS_METHOD nsLabel::GetLabel(nsString& aBuffer)
{
char * text;
gtk_label_get(GTK_LABEL(mWidget), &text);
aBuffer.SetLength(0);
aBuffer.Append(text);
return NS_OK;
}

View File

@@ -20,32 +20,43 @@
* Contributor(s):
*/
#ifndef nsByteBuffer_h__
#define nsByteBuffer_h__
#ifndef nsLabel_h__
#define nsLabel_h__
#include "nsIByteBuffer.h"
#include "nsWidget.h"
#include "nsILabel.h"
/**
* Native GTK+ Label wrapper
*/
class nsLabel : public nsWidget,
public nsILabel
{
class ByteBufferImpl : public nsIByteBuffer {
public:
ByteBufferImpl(void);
virtual ~ByteBufferImpl();
NS_DECL_ISUPPORTS
nsLabel();
virtual ~nsLabel();
static NS_METHOD
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
NS_DECL_ISUPPORTS_INHERITED
NS_IMETHOD Init(PRUint32 aBufferSize);
NS_IMETHOD_(PRUint32) GetLength(void) const;
NS_IMETHOD_(PRUint32) GetBufferSize(void) const;
NS_IMETHOD_(char*) GetBuffer() const;
NS_IMETHOD_(PRBool) Grow(PRUint32 aNewSize);
NS_IMETHOD_(PRInt32) Fill(nsresult* aErrorCode, nsIInputStream* aStream,
PRUint32 aKeep);
// nsILabel part
NS_IMETHOD SetLabel(const nsString &aText);
NS_IMETHOD GetLabel(nsString &aBuffer);
NS_IMETHOD SetAlignment(nsLabelAlignment aAlignment);
NS_IMETHOD PreCreateWidget(nsWidgetInitData *aInitData);
virtual PRBool OnMove(PRInt32 aX, PRInt32 aY) { return PR_FALSE; }
virtual PRBool OnResize(nsRect &aRect) { return PR_FALSE; }
protected:
NS_METHOD CreateNative(GtkObject *parentWindow);
GtkJustification GetNativeAlignment();
nsLabelAlignment mAlignment;
char* mBuffer;
PRUint32 mSpace;
PRUint32 mLength;
};
#endif // nsByteBuffer_h__
#endif // nsLabel_h__

View File

@@ -0,0 +1,394 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsListBox.h"
#include "nsString.h"
NS_IMPL_ADDREF_INHERITED(nsListBox, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsListBox, nsWidget)
NS_IMPL_QUERY_INTERFACE3(nsListBox, nsIListBox, nsIListWidget, nsIWidget)
//-------------------------------------------------------------------------
//
// nsListBox constructor
//
//-------------------------------------------------------------------------
nsListBox::nsListBox() : nsWidget(), nsIListWidget(), nsIListBox()
{
NS_INIT_REFCNT();
mMultiSelect = PR_FALSE;
mCList = nsnull;
}
//-------------------------------------------------------------------------
//
// nsListBox:: destructor
//
//-------------------------------------------------------------------------
nsListBox::~nsListBox()
{
}
void nsListBox::InitCallbacks(char * aName)
{
InstallButtonPressSignal(mCList);
InstallButtonReleaseSignal(mCList);
InstallEnterNotifySignal(mCList);
InstallLeaveNotifySignal(mCList);
// These are needed so that the events will go to us and not our parent.
AddToEventMask(mCList,
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_ENTER_NOTIFY_MASK |
GDK_EXPOSURE_MASK |
GDK_FOCUS_CHANGE_MASK |
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_POINTER_MOTION_MASK);
}
//-------------------------------------------------------------------------
//
// initializer
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsListBox::SetMultipleSelection(PRBool aMultipleSelections)
{
mMultiSelect = aMultipleSelections;
if (mCList) {
if (mMultiSelect)
gtk_clist_set_selection_mode(GTK_CLIST(mCList), GTK_SELECTION_MULTIPLE);
else
gtk_clist_set_selection_mode(GTK_CLIST(mCList), GTK_SELECTION_BROWSE);
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// AddItemAt
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsListBox::AddItemAt(nsString &aItem, PRInt32 aPosition)
{
if (mCList) {
gchar *text[2];
const nsAutoCString tempStr(aItem);
text[0] = (gchar*)(const char *)tempStr;
text[1] = (gchar*)NULL;
gtk_clist_insert(GTK_CLIST(mCList), (int)aPosition, text);
// XXX Im not sure using the string address is the right thing to
// store in the row data.
gtk_clist_set_row_data(GTK_CLIST(mCList), aPosition, (gpointer)&aItem);
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Finds an item at a postion
//
//-------------------------------------------------------------------------
PRInt32 nsListBox::FindItem(nsString &aItem, PRInt32 aStartPos)
{
int i = -1;
if (mCList) {
i = gtk_clist_find_row_from_data(GTK_CLIST(mCList), (gpointer)&aItem);
if (i < aStartPos) {
i = -1;
}
}
return i;
}
//-------------------------------------------------------------------------
//
// CountItems - Get Item Count
//
//-------------------------------------------------------------------------
PRInt32 nsListBox::GetItemCount()
{
if (mCList) {
return GTK_CLIST(mCList)->rows;
}
else {
return 0;
}
}
//-------------------------------------------------------------------------
//
// Removes an Item at a specified location
//
//-------------------------------------------------------------------------
PRBool nsListBox::RemoveItemAt(PRInt32 aPosition)
{
if (mCList) {
gtk_clist_remove(GTK_CLIST(mCList), aPosition);
}
return PR_TRUE;
}
//-------------------------------------------------------------------------
//
//
//
//-------------------------------------------------------------------------
PRBool nsListBox::GetItemAt(nsString& anItem, PRInt32 aPosition)
{
PRBool result = PR_FALSE;
anItem.Truncate();
if (mCList) {
char *text = nsnull;
gtk_clist_get_text(GTK_CLIST(mCList),aPosition,0,&text);
if (text) {
anItem.Append(text);
result = PR_TRUE;
}
}
return result;
}
//-------------------------------------------------------------------------
//
// Gets the selected of selected item
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsListBox::GetSelectedItem(nsString& aItem)
{
aItem.Truncate();
if (mCList) {
PRInt32 i=0, idx=-1;
GtkCList *clist = GTK_CLIST(mCList);
GList *list = clist->row_list;
for (i=0; i < clist->rows && idx == -1; i++, list = list->next) {
if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED) {
char *text = nsnull;
gtk_clist_get_text(GTK_CLIST(mCList),i,0,&text);
if (text) {
aItem.Append(text);
}
return NS_OK;
}
}
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Gets the list of selected otems
//
//-------------------------------------------------------------------------
PRInt32 nsListBox::GetSelectedIndex()
{
PRInt32 i=0, idx=-1;
if (mCList) {
if (!mMultiSelect) {
GtkCList *clist = GTK_CLIST(mCList);
GList *list = clist->row_list;
for (i=0; i < clist->rows && idx == -1; i++, list = list->next) {
if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED) {
idx = i;
}
}
} else {
NS_ASSERTION(PR_FALSE, "Multi selection list box does not support GetSelectedIndex()");
}
}
return idx;
}
//-------------------------------------------------------------------------
//
// SelectItem
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsListBox::SelectItem(PRInt32 aPosition)
{
if (mCList) {
gtk_clist_select_row(GTK_CLIST(mCList), aPosition, 0);
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// GetSelectedCount
//
//-------------------------------------------------------------------------
PRInt32 nsListBox::GetSelectedCount()
{
if (mCList) {
if (!GTK_CLIST(mCList)->selection)
return 0;
else
return (PRInt32)g_list_length(GTK_CLIST(mCList)->selection);
}
else {
return 0;
}
}
//-------------------------------------------------------------------------
//
// GetSelectedIndices
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsListBox::GetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize)
{
if (mCList) {
PRInt32 i=0, num = 0;
GtkCList *clist = GTK_CLIST(mCList);
GList *list = clist->row_list;
for (i=0; i < clist->rows && num < aSize; i++, list = list->next) {
if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED) {
aIndices[num] = i;
num++;
}
}
}
else {
PRInt32 i = 0;
for (i = 0; i < aSize; i++) aIndices[i] = 0;
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// SetSelectedIndices
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsListBox::SetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize)
{
if (mCList) {
gtk_clist_unselect_all(GTK_CLIST(mCList));
int i;
for (i=0;i<aSize;i++) {
SelectItem(aIndices[i]);
}
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Deselect
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsListBox::Deselect()
{
if (mCList) {
gtk_clist_unselect_all(GTK_CLIST(mCList));
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set initial parameters
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsListBox::PreCreateWidget(nsWidgetInitData *aInitData)
{
if (nsnull != aInitData) {
nsListBoxInitData* data = (nsListBoxInitData *) aInitData;
mMultiSelect = data->mMultiSelect;
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Create the native widget
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsListBox::CreateNative(GtkObject *parentWindow)
{
// to handle scrolling
mWidget = gtk_scrolled_window_new (nsnull, nsnull);
gtk_widget_set_name(mWidget, "nsListBox");
gtk_container_set_border_width(GTK_CONTAINER(mWidget), 0);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (mWidget),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
mCList = ::gtk_clist_new(1);
gtk_clist_column_titles_hide(GTK_CLIST(mCList));
// Default (it may be changed)
gtk_clist_set_selection_mode(GTK_CLIST(mCList), GTK_SELECTION_BROWSE);
SetMultipleSelection(mMultiSelect);
gtk_widget_show(mCList);
gtk_signal_connect(GTK_OBJECT(mCList),
"destroy",
GTK_SIGNAL_FUNC(DestroySignal),
this);
gtk_container_add (GTK_CONTAINER (mWidget), mCList);
return NS_OK;
}
void
nsListBox::OnDestroySignal(GtkWidget* aGtkWidget)
{
if (aGtkWidget == mCList) {
mCList = nsnull;
}
else {
nsWidget::OnDestroySignal(aGtkWidget);
}
}
//-------------------------------------------------------------------------
//
// set font for listbox
//
//-------------------------------------------------------------------------
/*virtual*/
void nsListBox::SetFontNative(GdkFont *aFont)
{
GtkStyle *style = gtk_style_copy(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0))->style);
// gtk_style_copy ups the ref count of the font
gdk_font_unref (style->font);
style->font = aFont;
gdk_font_ref(style->font);
gtk_widget_set_style(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0)), style);
gtk_style_unref(style);
}

View File

@@ -0,0 +1,70 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsListBox_h__
#define nsListBox_h__
#include "nsWidget.h"
#include "nsIListBox.h"
/**
* Native GTK+ Listbox wrapper
*/
class nsListBox : public nsWidget,
public nsIListWidget,
public nsIListBox
{
public:
nsListBox();
virtual ~nsListBox();
NS_DECL_ISUPPORTS_INHERITED
// nsIListBox interface
NS_IMETHOD PreCreateWidget(nsWidgetInitData *aInitData);
NS_IMETHOD SetMultipleSelection(PRBool aMultipleSelections);
NS_IMETHOD AddItemAt(nsString &aItem, PRInt32 aPosition);
PRInt32 FindItem(nsString &aItem, PRInt32 aStartPos);
PRInt32 GetItemCount();
PRBool RemoveItemAt(PRInt32 aPosition);
PRBool GetItemAt(nsString& anItem, PRInt32 aPosition);
NS_IMETHOD GetSelectedItem(nsString& aItem);
PRInt32 GetSelectedIndex();
PRInt32 GetSelectedCount();
NS_IMETHOD GetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize);
NS_IMETHOD SetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize);
NS_IMETHOD SelectItem(PRInt32 aPosition);
NS_IMETHOD Deselect() ;
virtual void SetFontNative(GdkFont *aFont);
protected:
NS_IMETHOD CreateNative(GtkObject *parentWindow);
virtual void InitCallbacks(char * aName = nsnull);
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
GtkWidget *mCList;
PRBool mMultiSelect;
};
#endif // nsListBox_h__

View File

@@ -0,0 +1,316 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsLookAndFeel.h"
#include <gtk/gtkinvisible.h>
#define GDK_COLOR_TO_NS_RGB(c) \
((nscolor) NS_RGB(c.red, c.green, c.blue))
NS_IMPL_ISUPPORTS1(nsLookAndFeel, nsILookAndFeel)
//-------------------------------------------------------------------------
//
// Query interface implementation
//
//-------------------------------------------------------------------------
nsLookAndFeel::nsLookAndFeel()
{
NS_INIT_REFCNT();
mWidget = gtk_invisible_new();
gtk_widget_ensure_style(mWidget);
mStyle = gtk_widget_get_style(mWidget);
}
nsLookAndFeel::~nsLookAndFeel()
{
gtk_widget_destroy(mWidget);
}
NS_IMETHODIMP nsLookAndFeel::GetColor(const nsColorID aID, nscolor &aColor)
{
nsresult res = NS_OK;
aColor = 0; // default color black
switch (aID) {
case eColor_WindowBackground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_WindowForeground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
break;
case eColor_WidgetBackground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_WidgetForeground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
break;
case eColor_WidgetSelectBackground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_SELECTED]);
break;
case eColor_WidgetSelectForeground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_SELECTED]);
break;
case eColor_Widget3DHighlight:
aColor = NS_RGB(0xa0,0xa0,0xa0);
break;
case eColor_Widget3DShadow:
aColor = NS_RGB(0x40,0x40,0x40);
break;
case eColor_TextBackground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_TextForeground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
break;
case eColor_TextSelectBackground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_SELECTED]);
break;
case eColor_TextSelectForeground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->text[GTK_STATE_SELECTED]);
break;
// css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
case eColor_activeborder:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_activecaption:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_appworkspace:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_background:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_captiontext:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
break;
case eColor_graytext:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_INSENSITIVE]);
break;
case eColor_highlight:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_SELECTED]);
break;
case eColor_highlighttext:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_SELECTED]);
break;
case eColor_inactiveborder:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_inactivecaption:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_INSENSITIVE]);
break;
case eColor_inactivecaptiontext:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_INSENSITIVE]);
break;
case eColor_infobackground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_infotext:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
break;
case eColor_menu:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_menutext:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
break;
case eColor_scrollbar:
break;
case eColor_threedface:
case eColor_buttonface:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_buttonhighlight: // ?
case eColor_threedhighlight:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_ACTIVE]);
break;
case eColor_buttontext:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
break;
case eColor_buttonshadow:
case eColor_threeddarkshadow:
case eColor_threedshadow: // i think these should be the same
aColor = NS_DarkenColor(NS_DarkenColor(NS_DarkenColor(NS_DarkenColor(NS_DarkenColor(GDK_COLOR_TO_NS_RGB(mStyle->light[GTK_STATE_NORMAL]))))));
// aColor = GDK_COLOR_TO_NS_RGB(mStyle->dark[GTK_STATE_NORMAL]); // dark style gives me bright green?!
break;
case eColor_threedlightshadow:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->light[GTK_STATE_NORMAL]);
break;
case eColor_window:
case eColor_windowframe:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_windowtext:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
break;
default:
/* default color is BLACK */
aColor = 0;
res = NS_ERROR_FAILURE;
break;
}
// printf("%i, %i, %i\n", NS_GET_R(aColor), NS_GET_B(aColor), NS_GET_G(aColor));
return res;
}
NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
{
nsresult res = NS_OK;
switch (aID) {
case eMetric_WindowTitleHeight:
aMetric = 0;
break;
case eMetric_WindowBorderWidth:
// aMetric = mStyle->klass->xthickness;
break;
case eMetric_WindowBorderHeight:
// aMetric = mStyle->klass->ythickness;
break;
case eMetric_Widget3DBorder:
// aMetric = 4;
break;
case eMetric_TextFieldHeight:
{
GtkRequisition req;
GtkWidget *text = gtk_entry_new();
// needed to avoid memory leak
gtk_widget_ref(text);
gtk_object_sink(GTK_OBJECT(text));
gtk_widget_size_request(text,&req);
aMetric = req.height;
gtk_widget_destroy(text);
gtk_widget_unref(text);
}
break;
case eMetric_TextFieldBorder:
aMetric = 2;
break;
case eMetric_TextVerticalInsidePadding:
aMetric = 0;
break;
case eMetric_TextShouldUseVerticalInsidePadding:
aMetric = 0;
break;
case eMetric_TextHorizontalInsideMinimumPadding:
aMetric = 15;
break;
case eMetric_TextShouldUseHorizontalInsideMinimumPadding:
aMetric = 1;
break;
case eMetric_ButtonHorizontalInsidePaddingNavQuirks:
aMetric = 10;
break;
case eMetric_ButtonHorizontalInsidePaddingOffsetNavQuirks:
aMetric = 8;
break;
case eMetric_CheckboxSize:
aMetric = 15;
break;
case eMetric_RadioboxSize:
aMetric = 15;
break;
case eMetric_ListShouldUseHorizontalInsideMinimumPadding:
aMetric = 15;
break;
case eMetric_ListHorizontalInsideMinimumPadding:
aMetric = 15;
break;
case eMetric_ListShouldUseVerticalInsidePadding:
aMetric = 1;
break;
case eMetric_ListVerticalInsidePadding:
aMetric = 1;
break;
case eMetric_CaretBlinkTime:
aMetric = 500;
break;
case eMetric_CaretWidthTwips:
aMetric = 20;
break;
default:
aMetric = 0;
res = NS_ERROR_FAILURE;
}
return res;
}
NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricFloatID aID, float & aMetric)
{
nsresult res = NS_OK;
switch (aID) {
case eMetricFloat_TextFieldVerticalInsidePadding:
aMetric = 0.25f;
break;
case eMetricFloat_TextFieldHorizontalInsidePadding:
aMetric = 0.95f; // large number on purpose so minimum padding is used
break;
case eMetricFloat_TextAreaVerticalInsidePadding:
aMetric = 0.40f;
break;
case eMetricFloat_TextAreaHorizontalInsidePadding:
aMetric = 0.40f; // large number on purpose so minimum padding is used
break;
case eMetricFloat_ListVerticalInsidePadding:
aMetric = 0.10f;
break;
case eMetricFloat_ListHorizontalInsidePadding:
aMetric = 0.40f;
break;
case eMetricFloat_ButtonVerticalInsidePadding:
aMetric = 0.25f;
break;
case eMetricFloat_ButtonHorizontalInsidePadding:
aMetric = 0.25f;
break;
default:
aMetric = -1.0;
res = NS_ERROR_FAILURE;
}
return res;
}
#ifdef NS_DEBUG
NS_IMETHODIMP nsLookAndFeel::GetNavSize(const nsMetricNavWidgetID aWidgetID,
const nsMetricNavFontID aFontID,
const PRInt32 aFontSize,
nsSize &aSize)
{
aSize.width = 0;
aSize.height = 0;
return NS_ERROR_NOT_IMPLEMENTED;
}
#endif

View File

@@ -0,0 +1,55 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef __nsLookAndFeel
#define __nsLookAndFeel
#include "nsILookAndFeel.h"
#include <gtk/gtk.h>
class nsLookAndFeel: public nsILookAndFeel {
NS_DECL_ISUPPORTS
public:
nsLookAndFeel();
virtual ~nsLookAndFeel();
NS_IMETHOD GetColor(const nsColorID aID, nscolor &aColor);
NS_IMETHOD GetMetric(const nsMetricID aID, PRInt32 & aMetric);
NS_IMETHOD GetMetric(const nsMetricFloatID aID, float & aMetric);
#ifdef NS_DEBUG
// This method returns the actual (or nearest estimate)
// of the Navigator size for a given form control for a given font
// and font size. This is used in NavQuirks mode to see how closely
// we match its size
NS_IMETHOD GetNavSize(const nsMetricNavWidgetID aWidgetID,
const nsMetricNavFontID aFontID,
const PRInt32 aFontSize,
nsSize &aSize);
#endif
protected:
GtkStyle *mStyle;
GtkWidget *mWidget;
};
#endif

View File

@@ -0,0 +1,792 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsMenu.h"
#include "nsIComponentManager.h"
#include "nsIDOMElement.h"
#include "nsIDOMNode.h"
#include "nsIMenuBar.h"
#include "nsIMenuItem.h"
#include "nsIMenuListener.h"
#include "nsString.h"
#include "nsGtkEventHandler.h"
#include "nsCOMPtr.h"
#include "nsWidgetsCID.h"
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
static NS_DEFINE_CID(kMenuItemCID, NS_MENUITEM_CID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
nsresult nsMenu::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
*aInstancePtr = NULL;
if (aIID.Equals(nsIMenu::GetIID())) {
*aInstancePtr = (void*)(nsIMenu*) this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*)(nsISupports*)(nsIMenu*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(nsIMenuListener::GetIID())) {
*aInstancePtr = (void*)(nsIMenuListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMPL_ADDREF(nsMenu)
NS_IMPL_RELEASE(nsMenu)
//-------------------------------------------------------------------------
//
// nsMenu constructor
//
//-------------------------------------------------------------------------
nsMenu::nsMenu() : nsIMenu()
{
NS_INIT_REFCNT();
mNumMenuItems = 0;
mMenu = nsnull;
mMenuParent = nsnull;
mMenuBarParent = nsnull;
mListener = nsnull;
mConstructCalled = PR_FALSE;
mDOMNode = nsnull;
mWebShell = nsnull;
mDOMElement = nsnull;
mAccessKey = "_";
}
//-------------------------------------------------------------------------
//
// nsMenu destructor
//
//-------------------------------------------------------------------------
nsMenu::~nsMenu()
{
//g_print("nsMenu::~nsMenu() called\n");
NS_IF_RELEASE(mListener);
// Free our menu items
RemoveAll();
gtk_widget_destroy(mMenu);
mMenu = nsnull;
}
//-------------------------------------------------------------------------
//
// Create the proper widget
//-------------------------------------------------------------------------
NS_METHOD nsMenu::Create(nsISupports *aParent, const nsString &aLabel)
{
if(aParent)
{
nsIMenuBar * menubar = nsnull;
aParent->QueryInterface(nsIMenuBar::GetIID(), (void**) &menubar);
if(menubar)
{
mMenuBarParent = menubar;
NS_RELEASE(menubar);
}
else
{
nsIMenu * menu = nsnull;
aParent->QueryInterface(nsIMenu::GetIID(), (void**) &menu);
if(menu)
{
mMenuParent = menu;
NS_RELEASE(menu);
}
}
}
mLabel = aLabel;
mMenu = gtk_menu_new();
gtk_signal_connect (GTK_OBJECT (mMenu), "map",
GTK_SIGNAL_FUNC(menu_map_handler),
this);
gtk_signal_connect (GTK_OBJECT (mMenu), "unmap",
GTK_SIGNAL_FUNC(menu_unmap_handler),
this);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::GetParent(nsISupports*& aParent)
{
aParent = nsnull;
if (nsnull != mMenuParent) {
return mMenuParent->QueryInterface(kISupportsIID,
(void**)&aParent);
} else if (nsnull != mMenuBarParent) {
return mMenuBarParent->QueryInterface(kISupportsIID,
(void**)&aParent);
}
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::GetLabel(nsString &aText)
{
aText = mLabel;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::SetLabel(const nsString &aText)
{
/* we Do GetLabel() when we are adding the menu...
* but we might want to redo this.
*/
mLabel = aText;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::GetAccessKey(nsString &aText)
{
aText = mAccessKey;
char *foo = mAccessKey.ToNewCString();
#ifdef DEBUG_pavlov
g_print("GetAccessKey returns \"%s\"\n", foo);
#endif
nsCRT::free(foo);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::SetAccessKey(const nsString &aText)
{
mAccessKey = aText;
char *foo = mAccessKey.ToNewCString();
#ifdef DEBUG_pavlov
g_print("SetAccessKey setting to \"%s\"\n", foo);
#endif
nsCRT::free(foo);
return NS_OK;
}
//-------------------------------------------------------------------------
/**
* Set enabled state
*
*/
NS_METHOD nsMenu::SetEnabled(PRBool aIsEnabled)
{
return NS_OK;
}
//-------------------------------------------------------------------------
/**
* Get enabled state
*
*/
NS_METHOD nsMenu::GetEnabled(PRBool* aIsEnabled)
{
return NS_OK;
}
//-------------------------------------------------------------------------
/**
* Query if this is the help menu
*
*/
NS_METHOD nsMenu::IsHelpMenu(PRBool* aIsHelpMenu)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::AddItem(nsISupports * aItem)
{
if(aItem)
{
nsIMenuItem * menuitem = nsnull;
aItem->QueryInterface(nsIMenuItem::GetIID(),
(void**)&menuitem);
if(menuitem)
{
AddMenuItem(menuitem); // nsMenu now owns this
NS_RELEASE(menuitem);
}
else
{
nsIMenu * menu = nsnull;
aItem->QueryInterface(nsIMenu::GetIID(),
(void**)&menu);
if(menu)
{
AddMenu(menu); // nsMenu now owns this
NS_RELEASE(menu);
}
}
}
return NS_OK;
}
// local method used by nsMenu::AddItem
//-------------------------------------------------------------------------
NS_METHOD nsMenu::AddMenuItem(nsIMenuItem * aMenuItem)
{
GtkWidget *widget;
void *voidData;
aMenuItem->GetNativeData(voidData);
widget = GTK_WIDGET(voidData);
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
// XXX add aMenuItem to internal data structor list
// Need to be adding an nsISupports *, not nsIMenuItem *
nsISupports * supports = nsnull;
aMenuItem->QueryInterface(kISupportsIID,
(void**)&supports);
{
mMenuItemVoidArray.AppendElement(supports);
mNumMenuItems++;
}
return NS_OK;
}
// local method used by nsMenu::AddItem
//-------------------------------------------------------------------------
NS_METHOD nsMenu::AddMenu(nsIMenu * aMenu)
{
nsString Label;
GtkWidget *newmenu=nsnull;
void *voidData=NULL;
aMenu->GetLabel(Label);
// Create nsMenuItem
nsIMenuItem * pnsMenuItem = nsnull;
nsresult rv = nsComponentManager::CreateInstance(kMenuItemCID,
nsnull,
nsIMenuItem::GetIID(),
(void**)&pnsMenuItem);
if (NS_OK == rv) {
nsISupports * supports = nsnull;
QueryInterface(kISupportsIID, (void**) &supports);
pnsMenuItem->Create(supports, Label, PR_FALSE); //PR_TRUE);
NS_RELEASE(supports);
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
AddItem(supports); // Parent should now own menu item
NS_RELEASE(supports);
void * menuitem = nsnull;
pnsMenuItem->GetNativeData(menuitem);
voidData = NULL;
aMenu->GetNativeData(&voidData);
newmenu = GTK_WIDGET(voidData);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), newmenu);
NS_RELEASE(pnsMenuItem);
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::AddSeparator()
{
// Create nsMenuItem
nsIMenuItem * pnsMenuItem = nsnull;
nsresult rv = nsComponentManager::CreateInstance(
kMenuItemCID, nsnull, nsIMenuItem::GetIID(), (void**)&pnsMenuItem);
if (NS_OK == rv) {
nsString tmp = "menuseparator";
nsISupports * supports = nsnull;
QueryInterface(kISupportsIID, (void**) &supports);
pnsMenuItem->Create(supports, tmp, PR_TRUE);
NS_RELEASE(supports);
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
AddItem(supports); // Parent should now own menu item
NS_RELEASE(supports);
NS_RELEASE(pnsMenuItem);
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::GetItemCount(PRUint32 &aCount)
{
// this should be right.. does it need to be +1 ?
aCount = g_list_length(GTK_MENU_SHELL(mMenu)->children);
//g_print("nsMenu::GetItemCount = %i\n", aCount);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::GetItemAt(const PRUint32 aPos,
nsISupports *&aMenuItem)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::InsertItemAt(const PRUint32 aPos,
nsISupports *aMenuItem)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::RemoveItem(const PRUint32 aPos)
{
#if 0
// this may work here better than Removeall(), but i'm not sure how to test this one
nsISupports *item = mMenuItemVoidArray[aPos];
delete item;
mMenuItemVoidArray.RemoveElementAt(aPos);
#endif
/*
gtk_menu_shell_remove (GTK_MENU_SHELL (mMenu), item);
nsCRT::free(labelStr);
voidData = NULL;
aMenu->GetNativeData(&voidData);
newmenu = GTK_WIDGET(voidData);
gtk_menu_item_remove_submenu (GTK_MENU_ITEM (item));
*/
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::RemoveAll()
{
//g_print("nsMenu::RemoveAll()\n");
#if 0
// this doesn't work quite right, but this is about all that should really be needed
int i=0;
nsIMenu *menu = nsnull;
nsIMenuItem *menuitem = nsnull;
nsISupports *item = nsnull;
for (i=mMenuItemVoidArray.Count(); i>0; i--)
{
item = (nsISupports*)mMenuItemVoidArray[i-1];
if(nsnull != item)
{
if (NS_OK == item->QueryInterface(nsIMenuItem::GetIID(), (void**)&menuitem)) {
// we do this twice because we have to do it once for QueryInterface,
// then we want to get rid of it.
// g_print("remove nsMenuItem\n");
NS_RELEASE(menuitem);
NS_RELEASE(item);
menuitem = nsnull;
} else if (NS_OK == item->QueryInterface(nsIMenu::GetIID(), (void**)&menu)) {
// g_print("remove nsMenu\n");
NS_RELEASE(menu);
NS_RELEASE(item);
menu = nsnull;
}
// mMenuItemVoidArray.RemoveElementAt(i-1);
}
}
mMenuItemVoidArray.Clear();
#else
for (int i = mMenuItemVoidArray.Count(); i > 0; i--) {
if(nsnull != mMenuItemVoidArray[i-1]) {
nsIMenuItem * menuitem = nsnull;
((nsISupports*)mMenuItemVoidArray[i-1])->QueryInterface(nsIMenuItem::GetIID(),
(void**)&menuitem);
if(menuitem) {
void *gtkmenuitem = nsnull;
menuitem->GetNativeData(gtkmenuitem);
if (gtkmenuitem) {
// gtk_widget_ref(GTK_WIDGET(gtkmenuitem));
//gtk_widget_destroy(GTK_WIDGET(gtkmenuitem));
gtk_container_remove (GTK_CONTAINER (mMenu), GTK_WIDGET(gtkmenuitem));
}
} else {
nsIMenu * menu= nsnull;
((nsISupports*)mMenuItemVoidArray[i-1])->QueryInterface(nsIMenu::GetIID(),
(void**)&menu);
if(menu)
{
void * gtkmenu = nsnull;
menu->GetNativeData(&gtkmenu);
if(gtkmenu){
//g_print("gtkmenu removed");
//gtk_menu_item_remove_submenu (GTK_MENU_ITEM (item));
}
}
}
}
}
#endif
//g_print("end RemoveAll\n");
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::GetNativeData(void ** aData)
{
*aData = (void *)mMenu;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::SetNativeData(void * aData)
{
return NS_OK;
}
GtkWidget *nsMenu::GetNativeParent()
{
void * voidData;
if (nsnull != mMenuParent) {
mMenuParent->GetNativeData(&voidData);
} else if (nsnull != mMenuBarParent) {
mMenuBarParent->GetNativeData(voidData);
} else {
return nsnull;
}
return GTK_WIDGET(voidData);
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::AddMenuListener(nsIMenuListener * aMenuListener)
{
mListener = aMenuListener;
NS_ADDREF(mListener);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::RemoveMenuListener(nsIMenuListener * aMenuListener)
{
if (aMenuListener == mListener) {
NS_IF_RELEASE(mListener);
}
return NS_OK;
}
//-------------------------------------------------------------------------
// nsIMenuListener interface
//-------------------------------------------------------------------------
nsEventStatus nsMenu::MenuItemSelected(const nsMenuEvent & aMenuEvent)
{
if (nsnull != mListener) {
mListener->MenuSelected(aMenuEvent);
}
return nsEventStatus_eIgnore;
}
nsEventStatus nsMenu::MenuSelected(const nsMenuEvent & aMenuEvent)
{
if (nsnull != mListener) {
mListener->MenuSelected(aMenuEvent);
}
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenu::MenuDeselected(const nsMenuEvent & aMenuEvent)
{
if (nsnull != mListener) {
mListener->MenuDeselected(aMenuEvent);
}
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenu::MenuConstruct(const nsMenuEvent & aMenuEvent,
nsIWidget * aParentWindow,
void * menuNode,
void * aWebShell)
{
//g_print("nsMenu::MenuConstruct called \n");
if(menuNode){
SetDOMNode((nsIDOMNode*)menuNode);
}
if(!aWebShell){
aWebShell = mWebShell;
}
// First open the menu.
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
if (domElement)
domElement->SetAttribute("open", "true");
/// Now get the kids. Retrieve our menupopup child.
nsCOMPtr<nsIDOMNode> menuPopupNode;
mDOMNode->GetFirstChild(getter_AddRefs(menuPopupNode));
while (menuPopupNode) {
nsCOMPtr<nsIDOMElement> menuPopupElement(do_QueryInterface(menuPopupNode));
if (menuPopupElement) {
nsString menuPopupNodeType;
menuPopupElement->GetNodeName(menuPopupNodeType);
if (menuPopupNodeType.Equals("menupopup"))
break;
}
nsCOMPtr<nsIDOMNode> oldMenuPopupNode(menuPopupNode);
oldMenuPopupNode->GetNextSibling(getter_AddRefs(menuPopupNode));
}
if (!menuPopupNode)
return nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMNode> menuitemNode;
menuPopupNode->GetFirstChild(getter_AddRefs(menuitemNode));
unsigned short menuIndex = 0;
while (menuitemNode) {
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
if (menuitemElement) {
nsString menuitemNodeType;
nsString menuitemName;
menuitemElement->GetNodeName(menuitemNodeType);
if (menuitemNodeType.Equals("menuitem")) {
// LoadMenuItem
LoadMenuItem(this,
menuitemElement,
menuitemNode,
menuIndex,
(nsIWebShell*)aWebShell);
} else if (menuitemNodeType.Equals("menuseparator")) {
AddSeparator();
} else if (menuitemNodeType.Equals("menu")) {
// Load a submenu
LoadSubMenu(this, menuitemElement, menuitemNode);
}
}
++menuIndex;
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
} // end menu item innner loop
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenu::MenuDestruct(const nsMenuEvent & aMenuEvent)
{
// Close the node.
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
if (domElement)
domElement->RemoveAttribute("open");
//g_print("nsMenu::MenuDestruct called \n");
mConstructCalled = PR_FALSE;
RemoveAll();
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
/**
* Set DOMNode
*
*/
NS_METHOD nsMenu::SetDOMNode(nsIDOMNode * aMenuNode)
{
mDOMNode = aMenuNode;
return NS_OK;
}
//-------------------------------------------------------------------------
/**
* Set DOMElement
*
*/
NS_METHOD nsMenu::SetDOMElement(nsIDOMElement * aMenuElement)
{
mDOMElement = aMenuElement;
return NS_OK;
}
//-------------------------------------------------------------------------
/**
* Set WebShell
*
*/
NS_METHOD nsMenu::SetWebShell(nsIWebShell * aWebShell)
{
mWebShell = aWebShell;
return NS_OK;
}
//----------------------------------------
void nsMenu::LoadMenuItem(nsIMenu * pParentMenu,
nsIDOMElement * menuitemElement,
nsIDOMNode * menuitemNode,
unsigned short menuitemIndex,
nsIWebShell * aWebShell)
{
static const char* NS_STRING_TRUE = "true";
nsString disabled;
nsString menuitemName;
nsString menuitemCmd;
menuitemElement->GetAttribute(nsAutoString("disabled"), disabled);
menuitemElement->GetAttribute(nsAutoString("value"), menuitemName);
menuitemElement->GetAttribute(nsAutoString("cmd"), menuitemCmd);
// Create nsMenuItem
nsIMenuItem * pnsMenuItem = nsnull;
nsresult rv = nsComponentManager::CreateInstance(kMenuItemCID,
nsnull,
nsIMenuItem::GetIID(),
(void**)&pnsMenuItem);
if (NS_OK == rv) {
pnsMenuItem->Create(pParentMenu, menuitemName, PR_FALSE);
nsISupports * supports = nsnull;
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
pParentMenu->AddItem(supports); // Parent should now own menu item
NS_RELEASE(supports);
if(disabled == NS_STRING_TRUE ) {
pnsMenuItem->SetEnabled(PR_FALSE);
}
// Create MenuDelegate - this is the intermediator inbetween
// the DOM node and the nsIMenuItem
// The nsWebShellWindow wacthes for Document changes and then notifies the
// the appropriate nsMenuDelegate object
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(menuitemNode));
if (!domElement) {
//return NS_ERROR_FAILURE;
return;
}
nsAutoString cmdAtom("oncommand");
nsString cmdName;
domElement->GetAttribute(cmdAtom, cmdName);
pnsMenuItem->SetCommand(cmdName);
// DO NOT use passed in webshell because of messed up windows dynamic loading
// code.
pnsMenuItem->SetWebShell(mWebShell);
pnsMenuItem->SetDOMElement(domElement);
NS_RELEASE(pnsMenuItem);
}
return;
}
//----------------------------------------
void nsMenu::LoadSubMenu(nsIMenu * pParentMenu,
nsIDOMElement * menuElement,
nsIDOMNode * menuNode)
{
nsString menuName;
menuElement->GetAttribute(nsAutoString("value"), menuName);
//printf("Creating Menu [%s] \n", menuName.ToNewCString()); // this leaks
// Create nsMenu
nsIMenu * pnsMenu = nsnull;
nsresult rv = nsComponentManager::CreateInstance(kMenuCID,
nsnull,
nsIMenu::GetIID(),
(void**)&pnsMenu);
if (NS_OK == rv) {
// Call Create
nsISupports * supports = nsnull;
pParentMenu->QueryInterface(kISupportsIID, (void**) &supports);
pnsMenu->Create(supports, menuName);
NS_RELEASE(supports); // Balance QI
// Set nsMenu Name
pnsMenu->SetLabel(menuName);
supports = nsnull;
pnsMenu->QueryInterface(kISupportsIID, (void**) &supports);
pParentMenu->AddItem(supports); // parent takes ownership
NS_RELEASE(supports);
pnsMenu->SetWebShell(mWebShell);
pnsMenu->SetDOMNode(menuNode);
/*
// Begin menuitem inner loop
unsigned short menuIndex = 0;
nsCOMPtr<nsIDOMNode> menuitemNode;
menuNode->GetFirstChild(getter_AddRefs(menuitemNode));
while (menuitemNode) {
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
if (menuitemElement) {
nsString menuitemNodeType;
menuitemElement->GetNodeName(menuitemNodeType);
#ifdef DEBUG_saari
printf("Type [%s] %d\n", menuitemNodeType.ToNewCString(), menuitemNodeType.Equals("menuseparator"));
#endif
if (menuitemNodeType.Equals("menuitem")) {
// Load a menuitem
LoadMenuItem(pnsMenu, menuitemElement, menuitemNode, menuIndex, mWebShell);
} else if (menuitemNodeType.Equals("menuseparator")) {
pnsMenu->AddSeparator();
} else if (menuitemNodeType.Equals("menu")) {
// Add a submenu
LoadSubMenu(pnsMenu, menuitemElement, menuitemNode);
}
}
++menuIndex;
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
} // end menu item innner loop
*/
}
}

View File

@@ -0,0 +1,120 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsMenu_h__
#define nsMenu_h__
#include "nsIMenu.h"
#include "nsIMenuListener.h"
#include "nsVoidArray.h"
class nsIDOMElement;
class nsIDOMNode;
class nsIMenuBar;
class nsIWebShell;
/**
* Native GTK+ Menu wrapper
*/
class nsMenu : public nsIMenu, public nsIMenuListener
{
public:
nsMenu();
virtual ~nsMenu();
NS_DECL_ISUPPORTS
// nsIMenuListener methods
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuConstruct(
const nsMenuEvent & aMenuEvent,
nsIWidget * aParentWindow,
void * menuNode,
void * aWebShell);
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
NS_IMETHOD Create(nsISupports * aParent, const nsString &aLabel);
// nsIMenu Methods
NS_IMETHOD GetParent(nsISupports *&aParent);
NS_IMETHOD GetLabel(nsString &aText);
NS_IMETHOD SetLabel(const nsString &aText);
NS_IMETHOD GetAccessKey(nsString &aText);
NS_IMETHOD SetAccessKey(const nsString &aText);
NS_IMETHOD AddItem(nsISupports * aItem);
NS_IMETHOD AddMenuItem(nsIMenuItem * aMenuItem);
NS_IMETHOD AddMenu(nsIMenu * aMenu);
NS_IMETHOD AddSeparator();
NS_IMETHOD GetItemCount(PRUint32 &aCount);
NS_IMETHOD GetItemAt(const PRUint32 aPos, nsISupports *& aMenuItem);
NS_IMETHOD InsertItemAt(const PRUint32 aPos, nsISupports * aMenuItem);
NS_IMETHOD RemoveItem(const PRUint32 aPos);
NS_IMETHOD RemoveAll();
NS_IMETHOD GetNativeData(void** aData);
NS_IMETHOD SetNativeData(void* aData);
NS_IMETHOD AddMenuListener(nsIMenuListener * aMenuListener);
NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener);
NS_IMETHOD SetEnabled(PRBool aIsEnabled);
NS_IMETHOD GetEnabled(PRBool* aIsEnabled);
NS_IMETHOD IsHelpMenu(PRBool* aIsHelp);
NS_IMETHOD SetDOMNode(nsIDOMNode * aMenuNode);
NS_IMETHOD SetDOMElement(nsIDOMElement * aMenuElement);
NS_IMETHOD SetWebShell(nsIWebShell * aWebShell);
protected:
void LoadMenuItem(
nsIMenu * pParentMenu,
nsIDOMElement * menuitemElement,
nsIDOMNode * menuitemNode,
unsigned short menuitemIndex,
nsIWebShell * aWebShell);
void LoadSubMenu(
nsIMenu * pParentMenu,
nsIDOMElement * menuElement,
nsIDOMNode * menuNode);
GtkWidget *GetNativeParent();
nsString mLabel;
nsString mAccessKey;
PRUint32 mNumMenuItems;
GtkWidget *mMenu;
nsVoidArray mMenuItemVoidArray;
nsIMenu *mMenuParent;
nsIMenuBar *mMenuBarParent;
nsIMenuListener * mListener;
PRBool mConstructCalled;
nsIDOMNode * mDOMNode;
nsIWebShell * mWebShell;
nsIDOMElement * mDOMElement;
};
#endif // nsMenu_h__

View File

@@ -0,0 +1,354 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsMenuBar.h"
#include "nsMenuItem.h"
#include "nsIComponentManager.h"
#include "nsIDOMNode.h"
#include "nsIMenu.h"
#include "nsIWebShell.h"
#include "nsIWidget.h"
#include "nsString.h"
#include "nsGtkEventHandler.h"
#include "nsCOMPtr.h"
#include "nsWidgetsCID.h"
static NS_DEFINE_CID(kMenuBarCID, NS_MENUBAR_CID);
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
nsresult nsMenuBar::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
*aInstancePtr = NULL;
if (aIID.Equals(nsIMenuBar::GetIID())) {
*aInstancePtr = (void*) ((nsIMenuBar*) this);
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*) ((nsISupports*)(nsIMenuBar*) this);
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(nsIMenuListener::GetIID())) {
*aInstancePtr = (void*) ((nsIMenuListener*)this);
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMPL_ADDREF(nsMenuBar)
NS_IMPL_RELEASE(nsMenuBar)
//-------------------------------------------------------------------------
//
// nsMenuBar constructor
//
//-------------------------------------------------------------------------
nsMenuBar::nsMenuBar() : nsIMenuBar(), nsIMenuListener()
{
NS_INIT_REFCNT();
mNumMenus = 0;
mMenuBar = nsnull;
mParent = nsnull;
mIsMenuBarAdded = PR_FALSE;
mWebShell = nsnull;
mDOMNode = nsnull;
}
//-------------------------------------------------------------------------
//
// nsMenuBar destructor
//
//-------------------------------------------------------------------------
nsMenuBar::~nsMenuBar()
{
// Release the menus
RemoveAll();
}
//-------------------------------------------------------------------------
//
// Create the proper widget
//
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::Create(nsIWidget *aParent)
{
SetParent(aParent);
mMenuBar = gtk_menu_bar_new();
gtk_widget_show(mMenuBar);
mParent->SetMenuBar(this);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::GetParent(nsIWidget *&aParent)
{
aParent = mParent;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::SetParent(nsIWidget *aParent)
{
mParent = aParent;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::AddMenu(nsIMenu * aMenu)
{
nsString Label;
GtkWidget *widget, *nmenu;
void *voidData;
nsISupports * supports = nsnull;
aMenu->QueryInterface(kISupportsIID, (void**)&supports);
if (supports) {
mMenusVoidArray.AppendElement(aMenu);
mNumMenus++;
}
aMenu->GetLabel(Label);
// get access key
nsString accessKey = " ";
aMenu->GetAccessKey(accessKey);
if(accessKey != " ")
{
// munge acess key into name
PRInt32 offset = Label.Find(accessKey);
if(offset != -1)
Label.Insert("_", offset);
}
char *foo = Label.ToNewCString();
g_print("%s\n", foo);
nsCRT::free(foo);
widget = nsMenuItem::CreateLocalized(Label);
gtk_widget_show(widget);
gtk_menu_bar_append (GTK_MENU_BAR (mMenuBar), widget);
aMenu->GetNativeData(&voidData);
nmenu = GTK_WIDGET(voidData);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), nmenu);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::GetMenuCount(PRUint32 &aCount)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::GetMenuAt(const PRUint32 aCount, nsIMenu *& aMenu)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::InsertMenuAt(const PRUint32 aCount, nsIMenu *& aMenu)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::RemoveMenu(const PRUint32 aCount)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::RemoveAll()
{
for (int i = mMenusVoidArray.Count(); i > 0; i--) {
if(nsnull != mMenusVoidArray[i-1]) {
nsIMenu * menu = nsnull;
((nsISupports*)mMenusVoidArray[i-1])->QueryInterface(nsIMenu::GetIID(), (void**)&menu);
if(menu) {
//void * gtkmenu= nsnull;
//menu->GetNativeData(&gtkmenu);
//if(gtkmenu){
// gtk_container_remove (GTK_CONTAINER (mMenuBar), GTK_WIDGET(gtkmenu) );
//}
NS_RELEASE(menu);
g_print("menu release \n");
int num =((nsISupports*)mMenusVoidArray[i-1])->Release();
while(num) {
g_print("menu release again!\n");
num = ((nsISupports*)mMenusVoidArray[i-1])->Release();
}
}
}
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::GetNativeData(void *& aData)
{
aData = (void *)mMenuBar;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::SetNativeData(void * aData)
{
// Temporary hack for MacOS. Will go away when nsMenuBar handles it's own
// construction
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::Paint()
{
return NS_OK;
}
//-------------------------------------------------------------------------
//
// nsMenuListener interface
//
//-------------------------------------------------------------------------
nsEventStatus nsMenuBar::MenuItemSelected(const nsMenuEvent & aMenuEvent)
{
return nsEventStatus_eIgnore;
}
nsEventStatus nsMenuBar::MenuSelected(const nsMenuEvent & aMenuEvent)
{
return nsEventStatus_eIgnore;
}
nsEventStatus nsMenuBar::MenuDeselected(const nsMenuEvent & aMenuEvent)
{
return nsEventStatus_eIgnore;
}
nsEventStatus nsMenuBar::MenuConstruct(
const nsMenuEvent & aMenuEvent,
nsIWidget * aParentWindow,
void * menubarNode,
void * aWebShell)
{
mWebShell = (nsIWebShell*) aWebShell;
mDOMNode = (nsIDOMNode*)menubarNode;
nsIMenuBar * pnsMenuBar = nsnull;
nsresult rv = nsComponentManager::CreateInstance(kMenuBarCID,
nsnull,
nsIMenuBar::GetIID(),
(void**)&pnsMenuBar);
if (NS_OK == rv) {
if (nsnull != pnsMenuBar) {
pnsMenuBar->Create(aParentWindow);
// set pnsMenuBar as a nsMenuListener on aParentWindow
nsCOMPtr<nsIMenuListener> menuListener;
pnsMenuBar->QueryInterface(nsIMenuListener::GetIID(), getter_AddRefs(menuListener));
aParentWindow->AddMenuListener(menuListener);
nsCOMPtr<nsIDOMNode> menuNode;
((nsIDOMNode*)menubarNode)->GetFirstChild(getter_AddRefs(menuNode));
while (menuNode) {
nsCOMPtr<nsIDOMElement> menuElement(do_QueryInterface(menuNode));
if (menuElement) {
nsString menuNodeType;
nsString menuName;
nsString menuAccessKey = " ";
menuElement->GetNodeName(menuNodeType);
if (menuNodeType.Equals("menu")) {
menuElement->GetAttribute(nsAutoString("value"), menuName);
menuElement->GetAttribute(nsAutoString("accesskey"), menuAccessKey);
// Don't create the menu yet, just add in the top level names
// Create nsMenu
nsIMenu * pnsMenu = nsnull;
rv = nsComponentManager::CreateInstance(kMenuCID, nsnull, nsIMenu::GetIID(), (void**)&pnsMenu);
if (NS_OK == rv) {
// Call Create
nsISupports * supports = nsnull;
pnsMenuBar->QueryInterface(kISupportsIID, (void**) &supports);
pnsMenu->Create(supports, menuName);
NS_RELEASE(supports);
pnsMenu->SetLabel(menuName);
pnsMenu->SetAccessKey(menuAccessKey);
pnsMenu->SetDOMNode(menuNode);
pnsMenu->SetDOMElement(menuElement);
pnsMenu->SetWebShell(mWebShell);
// Make nsMenu a child of nsMenuBar
// nsMenuBar takes ownership of the nsMenu
pnsMenuBar->AddMenu(pnsMenu);
// Release the menu now that the menubar owns it
NS_RELEASE(pnsMenu);
}
}
}
nsCOMPtr<nsIDOMNode> oldmenuNode(menuNode);
oldmenuNode->GetNextSibling(getter_AddRefs(menuNode));
} // end while (nsnull != menuNode)
// Give the aParentWindow this nsMenuBar to hold onto.
// The parent window should take ownership at this point
aParentWindow->SetMenuBar(pnsMenuBar);
// HACK: force a paint for now
pnsMenuBar->Paint();
NS_RELEASE(pnsMenuBar);
} // end if ( nsnull != pnsMenuBar )
}
return nsEventStatus_eIgnore;
return nsEventStatus_eIgnore;
}
nsEventStatus nsMenuBar::MenuDestruct(const nsMenuEvent & aMenuEvent)
{
return nsEventStatus_eIgnore;
}

View File

@@ -0,0 +1,85 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsMenuBar_h__
#define nsMenuBar_h__
#include "nsIMenuBar.h"
#include "nsIMenuListener.h"
#include "nsVoidArray.h"
class nsIDOMNode;
class nsIWebShell;
class nsIWidget;
/**
* Native GTK+ MenuBar wrapper
*/
class nsMenuBar : public nsIMenuBar, public nsIMenuListener
{
public:
nsMenuBar();
virtual ~nsMenuBar();
// nsIMenuListener interface
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuConstruct(
const nsMenuEvent & aMenuEvent,
nsIWidget * aParentWindow,
void * menuNode,
void * aWebShell);
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
NS_DECL_ISUPPORTS
NS_IMETHOD Create(nsIWidget * aParent);
// nsIMenuBar Methods
NS_IMETHOD GetParent(nsIWidget *&aParent);
NS_IMETHOD SetParent(nsIWidget * aParent);
NS_IMETHOD AddMenu(nsIMenu * aMenu);
NS_IMETHOD GetMenuCount(PRUint32 &aCount);
NS_IMETHOD GetMenuAt(const PRUint32 aCount, nsIMenu *& aMenu);
NS_IMETHOD InsertMenuAt(const PRUint32 aCount, nsIMenu *& aMenu);
NS_IMETHOD RemoveMenu(const PRUint32 aCount);
NS_IMETHOD RemoveAll();
NS_IMETHOD GetNativeData(void*& aData);
NS_IMETHOD Paint();
NS_IMETHOD SetNativeData(void* aData);
protected:
GtkWidget * mMenuBar;
nsIWidget * mParent;
PRBool mIsMenuBarAdded;
nsIWebShell * mWebShell;
nsIDOMNode * mDOMNode;
nsVoidArray mMenusVoidArray;
PRUint32 mNumMenus;
};
#endif // nsMenuBar_h__

View File

@@ -0,0 +1,539 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsMenuItem.h"
#include "nsIMenu.h"
#include "nsIMenuBar.h"
#include "nsIWidget.h"
#include "nsGtkEventHandler.h"
#include "nsIPopUpMenu.h"
#include "nsCOMPtr.h"
#include "nsIContent.h"
#include "nsIContentViewer.h"
#include "nsIDOMElement.h"
#include "nsIDocumentViewer.h"
#include "nsIPresContext.h"
#include "nsIWebShell.h"
#include "nsICharsetConverterManager.h"
#include "nsIPlatformCharset.h"
#include "nsIServiceManager.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
nsresult nsMenuItem::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
*aInstancePtr = NULL;
if (aIID.Equals(nsIMenuItem::GetIID())) {
*aInstancePtr = (void*)(nsIMenuItem*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*)(nsISupports*)(nsIMenuItem*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(nsIMenuListener::GetIID())) {
*aInstancePtr = (void*)(nsIMenuListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMPL_ADDREF(nsMenuItem)
NS_IMPL_RELEASE(nsMenuItem)
//-------------------------------------------------------------------------
//
// nsMenuItem constructor
//
//-------------------------------------------------------------------------
nsMenuItem::nsMenuItem() : nsIMenuItem()
{
NS_INIT_REFCNT();
mMenuItem = nsnull;
mMenuParent = nsnull;
mPopUpParent = nsnull;
mTarget = nsnull;
mXULCommandListener = nsnull;
mIsSeparator = PR_FALSE;
mWebShell = nsnull;
mDOMElement = nsnull;
mIsSubMenu = PR_FALSE;
}
//-------------------------------------------------------------------------
//
// nsMenuItem destructor
//
//-------------------------------------------------------------------------
nsMenuItem::~nsMenuItem()
{
//g_print("nsMenuItem::~nsMenuItem called\n");
//NS_IF_RELEASE(mTarget);
gtk_widget_destroy(mMenuItem);
mMenuItem = nsnull;
//g_print("end nsMenuItem::~nsMenuItem\n");
}
//-------------------------------------------------------------------------
GtkWidget *nsMenuItem::GetNativeParent()
{
void * voidData;
if (nsnull != mMenuParent) {
mMenuParent->GetNativeData(&voidData);
} else if (nsnull != mPopUpParent) {
mPopUpParent->GetNativeData(voidData);
} else {
return nsnull;
}
return GTK_WIDGET(voidData);
}
//-------------------------------------------------------------------------
nsIWidget * nsMenuItem::GetMenuBarParent(nsISupports * aParent)
{
nsIWidget * widget = nsnull; // MenuBar's Parent
nsIMenu * menu = nsnull;
nsIMenuBar * menuBar = nsnull;
nsIPopUpMenu * popup = nsnull;
nsISupports * parent = aParent;
while(1) {
if (NS_OK == parent->QueryInterface(nsIMenu::GetIID(),(void**)&menu)) {
NS_RELEASE(parent);
if (NS_OK != menu->GetParent(parent)) {
NS_RELEASE(menu);
return nsnull;
}
NS_RELEASE(menu);
} else if (NS_OK == parent->QueryInterface(nsIPopUpMenu::GetIID(),(void**)&popup)) {
if (NS_OK != popup->GetParent(widget)) {
widget = nsnull;
}
NS_RELEASE(popup);
NS_RELEASE(parent);
return widget;
} else if (NS_OK == parent->QueryInterface(nsIMenuBar::GetIID(),(void**)&menuBar)) {
if (NS_OK != menuBar->GetParent(widget)) {
widget = nsnull;
}
NS_RELEASE(menuBar);
NS_RELEASE(parent);
return widget;
} else {
NS_RELEASE(parent);
return nsnull;
}
}
return nsnull;
}
GtkWidget*
nsMenuItem::CreateLocalized(const nsString& aLabel)
{
nsresult result;
static nsIUnicodeEncoder* converter = nsnull;
static int isLatin1 = 0;
static int initialized = 0;
if (!initialized) {
initialized = 1;
result = NS_ERROR_FAILURE;
NS_WITH_SERVICE(nsIPlatformCharset, platform, NS_PLATFORMCHARSET_PROGID,
&result);
if (platform && NS_SUCCEEDED(result)) {
nsAutoString charset("");
result = platform->GetCharset(kPlatformCharsetSel_Menu, charset);
if (NS_SUCCEEDED(result) && (charset.Length() > 0)) {
if (!charset.Compare("iso-8859-1", PR_TRUE)) {
isLatin1 = 1;
}
NS_WITH_SERVICE(nsICharsetConverterManager, manager,
NS_CHARSETCONVERTERMANAGER_PROGID, &result);
if (manager && NS_SUCCEEDED(result)) {
result = manager->GetUnicodeEncoder(&charset, &converter);
if (NS_FAILED(result) && converter) {
NS_RELEASE(converter);
converter = nsnull;
}
else if (converter) {
result = converter->SetOutputErrorBehavior(
nsIUnicodeEncoder::kOnError_Replace, nsnull, '?');
}
}
}
}
}
GtkWidget* menuItem = nsnull;
if (converter) {
char labelStr[128];
labelStr[0] = 0;
PRInt32 srcLen = aLabel.Length() + 1;
PRInt32 destLen = sizeof(labelStr);
result = converter->Convert(aLabel.GetUnicode(), &srcLen, labelStr,
&destLen);
if (labelStr[0] && NS_SUCCEEDED(result)) {
menuItem = gtk_menu_item_new_with_label(labelStr);
if (menuItem && (!isLatin1)) {
GtkWidget* label = GTK_BIN(menuItem)->child;
gtk_widget_ensure_style(label);
GtkStyle* style = gtk_style_copy(label->style);
gdk_font_unref(style->font);
style->font = gdk_fontset_load("*");
gtk_widget_set_style(label, style);
gtk_style_unref(style);
}
}
}
else {
char labelStr[128];
aLabel.ToCString(labelStr, sizeof(labelStr));
menuItem = gtk_menu_item_new_with_label(labelStr);
}
return menuItem;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::Create(nsISupports *aParent,
const nsString &aLabel,
PRBool aIsSeparator)
{
if (nsnull == aParent) {
return NS_ERROR_FAILURE;
}
if(aParent) {
nsIMenu * menu;
aParent->QueryInterface(nsIMenu::GetIID(), (void**) &menu);
mMenuParent = menu;
NS_RELEASE(menu);
}
nsIWidget *widget = nsnull; // MenuBar's Parent
nsISupports *sups;
if (NS_OK == aParent->QueryInterface(kISupportsIID,(void**)&sups)) {
widget = GetMenuBarParent(sups);
// GetMenuBarParent will call release for us
// NS_RELEASE(sups);
mTarget = widget;
}
mIsSeparator = aIsSeparator;
mLabel = aLabel;
// create the native menu item
if(mIsSeparator) {
mMenuItem = gtk_menu_item_new();
} else {
mMenuItem = CreateLocalized(aLabel);
}
gtk_widget_show(mMenuItem);
gtk_signal_connect(GTK_OBJECT(mMenuItem), "activate",
GTK_SIGNAL_FUNC(menu_item_activate_handler),
this);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetLabel(nsString &aText)
{
aText = mLabel;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::SetLabel(nsString &aText)
{
mLabel = aText;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::SetEnabled(PRBool aIsEnabled)
{
gtk_widget_set_sensitive(GTK_WIDGET(mMenuItem), aIsEnabled);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetEnabled(PRBool *aIsEnabled)
{
*aIsEnabled = GTK_WIDGET_IS_SENSITIVE(mMenuItem);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::SetChecked(PRBool aIsEnabled)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetChecked(PRBool *aIsEnabled)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::SetCheckboxType(PRBool aIsCheckbox)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetCheckboxType(PRBool *aIsCheckbox)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetCommand(PRUint32 & aCommand)
{
aCommand = mCommand;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetTarget(nsIWidget *& aTarget)
{
aTarget = mTarget;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetNativeData(void *& aData)
{
aData = (void *)mMenuItem;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::AddMenuListener(nsIMenuListener * aMenuListener)
{
NS_IF_RELEASE(mXULCommandListener);
NS_IF_ADDREF(aMenuListener);
mXULCommandListener = aMenuListener;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::RemoveMenuListener(nsIMenuListener * aMenuListener)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::IsSeparator(PRBool & aIsSep)
{
aIsSep = mIsSeparator;
return NS_OK;
}
//-------------------------------------------------------------------------
// nsIMenuListener interface
//-------------------------------------------------------------------------
nsEventStatus nsMenuItem::MenuItemSelected(const nsMenuEvent & aMenuEvent)
{
if(!mIsSeparator) {
//g_print("nsMenuItem::MenuItemSelected\n");
DoCommand();
}else{
//g_print("nsMenuItem::MenuItemSelected is separator\n");
}
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenuItem::MenuSelected(const nsMenuEvent & aMenuEvent)
{
if(mXULCommandListener)
return mXULCommandListener->MenuSelected(aMenuEvent);
//g_print("nsMenuItem::MenuSelected\n");
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenuItem::MenuDeselected(const nsMenuEvent &aMenuEvent)
{
//g_print("nsMenuItem::MenuDeselected\n");
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenuItem::MenuConstruct(const nsMenuEvent &aMenuEvent,
nsIWidget *aParentWindow,
void *menuNode,
void *aWebShell)
{
//g_print("nsMenuItem::MenuConstruct\n");
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenuItem::MenuDestruct(const nsMenuEvent &aMenuEvent)
{
//g_print("nsMenuItem::MenuDestruct\n");
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
/**
* Sets the JavaScript Command to be invoked when a "gui" event
* occurs on a source widget
* @param aStrCmd the JS command to be cached for later execution
* @return NS_OK
*/
NS_METHOD nsMenuItem::SetCommand(const nsString &aStrCmd)
{
return NS_OK;
}
//-------------------------------------------------------------------------
/**
* Executes the "cached" JavaScript Command
* @return NS_OK if the command was executed properly, otherwise an error code
*/
NS_METHOD nsMenuItem::DoCommand()
{
nsresult rv = NS_ERROR_FAILURE;
if(!mWebShell || !mDOMElement)
return rv;
nsCOMPtr<nsIContentViewer> contentViewer;
NS_ENSURE_SUCCESS(mWebShell->GetContentViewer(getter_AddRefs(contentViewer)),
NS_ERROR_FAILURE);
nsCOMPtr<nsIDocumentViewer> docViewer;
docViewer = do_QueryInterface(contentViewer);
if (!docViewer) {
NS_ERROR("Document viewer interface not supported by the content viewer.");
//g_print("Document viewer interface not supported by the content viewer.");
return rv;
}
nsCOMPtr<nsIPresContext> presContext;
if (NS_FAILED(rv = docViewer->GetPresContext(*getter_AddRefs(presContext)))) {
NS_ERROR("Unable to retrieve the doc viewer's presentation context.");
//g_print("Unable to retrieve the doc viewer's presentation context.");
return rv;
}
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_MOUSE_EVENT;
event.message = NS_MENU_ACTION;
nsCOMPtr<nsIContent> contentNode;
contentNode = do_QueryInterface(mDOMElement);
if (!contentNode) {
NS_ERROR("DOM Node doesn't support the nsIContent interface required to handle DOM events.");
//g_print("DOM Node doesn't support the nsIContent interface required to handle DOM events.");
return rv;
}
rv = contentNode->HandleDOMEvent(*presContext, &event, nsnull, NS_EVENT_FLAG_INIT, status);
//g_print("HandleDOMEvent called");
return rv;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::SetDOMNode(nsIDOMNode * aDOMNode)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetDOMNode(nsIDOMNode ** aDOMNode)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::SetDOMElement(nsIDOMElement * aDOMElement)
{
mDOMElement = aDOMElement;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetDOMElement(nsIDOMElement ** aDOMElement)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::SetWebShell(nsIWebShell * aWebShell)
{
mWebShell = aWebShell;
return NS_OK;
}
//----------------------------------------------------------------------
NS_IMETHODIMP nsMenuItem::SetShortcutChar(const nsString &aText)
{
mKeyEquivalent = aText;
return NS_OK;
}
//----------------------------------------------------------------------
NS_IMETHODIMP nsMenuItem::GetShortcutChar(nsString &aText)
{
aText = mKeyEquivalent;
return NS_OK;
}
//----------------------------------------------------------------------
NS_IMETHODIMP nsMenuItem::SetModifiers(PRUint8 aModifiers)
{
mModifiers = aModifiers;
return NS_OK;
}
//----------------------------------------------------------------------
NS_IMETHODIMP nsMenuItem::GetModifiers(PRUint8 * aModifiers)
{
*aModifiers = mModifiers;
return NS_OK;
}

View File

@@ -0,0 +1,116 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsMenuItem_h__
#define nsMenuItem_h__
#include "nsIMenuItem.h"
#include "nsString.h"
#include "nsIMenuListener.h"
class nsIDOMNode;
class nsIDOMElement;
class nsIMenu;
class nsIPopUpMenu;
class nsIWebShell;
class nsIWidget;
/**
* Native GTK+ MenuItem wrapper
*/
class nsMenuItem : public nsIMenuItem, public nsIMenuListener
{
public:
nsMenuItem();
virtual ~nsMenuItem();
// nsISupports
NS_DECL_ISUPPORTS
// nsIMenuItem Methods
NS_IMETHOD Create(nsISupports *aParent,
const nsString &aLabel,
PRBool aIsSeparator);
NS_IMETHOD GetLabel(nsString &aText);
NS_IMETHOD SetLabel(nsString &aText);
NS_IMETHOD SetEnabled(PRBool aIsEnabled);
NS_IMETHOD GetEnabled(PRBool *aIsEnabled);
NS_IMETHOD SetChecked(PRBool aIsEnabled);
NS_IMETHOD GetChecked(PRBool *aIsEnabled);
NS_IMETHOD SetCheckboxType(PRBool aIsCheckbox);
NS_IMETHOD GetCheckboxType(PRBool *aIsCheckbox);
NS_IMETHOD GetCommand(PRUint32 & aCommand);
NS_IMETHOD GetTarget(nsIWidget *& aTarget);
NS_IMETHOD GetNativeData(void*& aData);
NS_IMETHOD AddMenuListener(nsIMenuListener * aMenuListener);
NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener);
NS_IMETHOD IsSeparator(PRBool & aIsSep);
NS_IMETHOD SetCommand(const nsString & aStrCmd);
NS_IMETHOD DoCommand();
NS_IMETHOD SetDOMNode(nsIDOMNode * aDOMNode);
NS_IMETHOD GetDOMNode(nsIDOMNode ** aDOMNode);
NS_IMETHOD SetDOMElement(nsIDOMElement * aDOMElement);
NS_IMETHOD GetDOMElement(nsIDOMElement ** aDOMElement);
NS_IMETHOD SetWebShell(nsIWebShell * aWebShell);
NS_IMETHOD SetShortcutChar(const nsString &aText);
NS_IMETHOD GetShortcutChar(nsString &aText);
NS_IMETHOD SetModifiers(PRUint8 aModifiers);
NS_IMETHOD GetModifiers(PRUint8 * aModifiers);
// nsIMenuListener interface
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuConstruct(const nsMenuEvent & aMenuEvent,
nsIWidget * aParentWindow,
void * menuNode,
void * aWebShell);
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
static GtkWidget* CreateLocalized(const nsString& aLabel);
protected:
nsIWidget *GetMenuBarParent(nsISupports * aParentSupports);
GtkWidget *GetNativeParent();
nsIMenuListener *mXULCommandListener;
nsString mLabel;
nsString mKeyEquivalent;
PRUint8 mModifiers;
PRUint32 mCommand;
nsIMenu *mMenuParent;
nsIPopUpMenu *mPopUpParent;
nsIWidget *mTarget;
GtkWidget *mMenuItem; // native cascade widget
PRBool mIsSeparator;
PRBool mIsSubMenu;
nsIWebShell * mWebShell;
nsIDOMElement * mDOMElement;
};
#endif // nsMenuItem_h__

View File

@@ -0,0 +1,214 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsPopUpMenu.h"
#include "nsIMenu.h"
#include "nsIWidget.h"
#include "nsString.h"
#include "nsFileSpec.h" // XXX: For nsAutoCString
NS_IMPL_ISUPPORTS(nsPopUpMenu, nsIPopUpMenu::GetIID())
//-------------------------------------------------------------------------
//
// nsPopUpMenu constructor
//
//-------------------------------------------------------------------------
nsPopUpMenu::nsPopUpMenu() : nsIPopUpMenu()
{
NS_INIT_REFCNT();
mNumMenuItems = 0;
mParent = nsnull;
mMenu = nsnull;
}
//-------------------------------------------------------------------------
//
// nsPopUpMenu destructor
//
//-------------------------------------------------------------------------
nsPopUpMenu::~nsPopUpMenu()
{
NS_IF_RELEASE(mParent);
}
//-------------------------------------------------------------------------
//
// Create the proper widget
//
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::Create(nsIWidget *aParent)
{
mParent = aParent;
NS_ADDREF(mParent);
mMenu = gtk_menu_new();
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::AddItem(const nsString &aText)
{
GtkWidget *widget;
widget = gtk_menu_item_new_with_label ((const char*)nsAutoCString(mLabel));
gtk_widget_show(widget);
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::AddItem(nsIMenuItem * aMenuItem)
{
GtkWidget *widget;
void *voidData;
aMenuItem->GetNativeData(voidData);
widget = GTK_WIDGET(voidData);
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
// XXX add aMenuItem to internal data structor list
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::AddMenu(nsIMenu * aMenu)
{
nsString Label;
GtkWidget *item=NULL, *parentmenu=NULL, *newmenu=NULL;
void *voidData=NULL;
aMenu->GetLabel(Label);
GetNativeData(voidData);
parentmenu = GTK_WIDGET(voidData);
item = gtk_menu_item_new_with_label ((const char*)nsAutoCString(Label));
gtk_widget_show(item);
gtk_menu_shell_append (GTK_MENU_SHELL (parentmenu), item);
voidData = NULL;
aMenu->GetNativeData(&voidData);
newmenu = GTK_WIDGET(voidData);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), newmenu);
// XXX add aMenu to internal data structor list
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::AddSeparator()
{
GtkWidget *widget;
widget = gtk_menu_item_new ();
gtk_widget_show(widget);
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::GetItemCount(PRUint32 &aCount)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::GetItemAt(const PRUint32 aCount, nsIMenuItem *& aMenuItem)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::InsertItemAt(const PRUint32 aCount, nsIMenuItem *& aMenuItem)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::InsertItemAt(const PRUint32 aCount, const nsString & aMenuItemName)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::InsertSeparator(const PRUint32 aCount)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::RemoveItem(const PRUint32 aCount)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::RemoveAll()
{
return NS_OK;
}
//-------------------------------------------------------------------------
void nsPopUpMenu::GetXY(GtkMenu *menu, gint *x, gint *y, gpointer user_data)
{
*x = ((nsPopUpMenu *)(user_data))->mX;
*y = ((nsPopUpMenu *)(user_data))->mY;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::ShowMenu(PRInt32 aX, PRInt32 aY)
{
mX = aX;
mY = aY;
gtk_menu_popup (GTK_MENU(mMenu),
NULL,
NULL,
GetXY,
this,
0,
GDK_CURRENT_TIME);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::GetNativeData(void *& aData)
{
aData = (void *)mMenu;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::GetParent(nsIWidget *& aParent)
{
aParent = mParent;
return NS_OK;
}

View File

@@ -0,0 +1,77 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsPopUpMenu_h__
#define nsPopUpMenu_h__
#include "nsIPopUpMenu.h"
#include <gtk/gtk.h>
class nsIWidget;
/**
* Native GTK+ PopUp wrapper
*/
class nsPopUpMenu : public nsIPopUpMenu
{
public:
nsPopUpMenu();
virtual ~nsPopUpMenu();
NS_DECL_ISUPPORTS
NS_IMETHOD Create(nsIWidget * aParent);
// nsIPopUpMenu Methods
NS_IMETHOD AddItem(const nsString &aText);
NS_IMETHOD AddItem(nsIMenuItem * aMenuItem);
NS_IMETHOD AddMenu(nsIMenu * aMenu);
NS_IMETHOD AddSeparator();
NS_IMETHOD GetItemCount(PRUint32 &aCount);
NS_IMETHOD GetItemAt(const PRUint32 aCount, nsIMenuItem *& aMenuItem);
NS_IMETHOD InsertItemAt(const PRUint32 aCount, nsIMenuItem *& aMenuItem);
NS_IMETHOD InsertItemAt(const PRUint32 aCount, const nsString & aMenuItemName);
NS_IMETHOD InsertSeparator(const PRUint32 aCount);
NS_IMETHOD RemoveItem(const PRUint32 aCount);
NS_IMETHOD RemoveAll();
static void GetXY(GtkMenu *menu, gint *x, gint *y, gpointer user_data);
NS_IMETHOD ShowMenu(PRInt32 aX, PRInt32 aY);
NS_IMETHOD GetNativeData(void*& aData);
NS_IMETHOD GetParent(nsIWidget*& aParent);
protected:
nsString mLabel;
PRUint32 mNumMenuItems;
nsIWidget *mParent;
GtkWidget *mMenu;
gint mX;
gint mY;
};
#endif // nsPopUpMenu_h__

View File

@@ -0,0 +1,240 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsRadioButton.h"
#include "nsString.h"
#include "nsGtkEventHandler.h"
NS_IMPL_ADDREF_INHERITED(nsRadioButton, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsRadioButton, nsWidget)
//-------------------------------------------------------------------------
//
// nsRadioButton constructor
//
//-------------------------------------------------------------------------
nsRadioButton::nsRadioButton() : nsWidget(), nsIRadioButton()
{
NS_INIT_REFCNT();
mLabel = nsnull;
mRadioButton = nsnull;
}
//-------------------------------------------------------------------------
//
// nsRadioButton destructor
//
//-------------------------------------------------------------------------
nsRadioButton::~nsRadioButton()
{
#if 0
if (mLabel)
gtk_widget_destroy(mLabel);
#endif
}
//-------------------------------------------------------------------------
//
// Query interface implementation
//
//-------------------------------------------------------------------------
nsresult nsRadioButton::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
nsresult result = nsWidget::QueryInterface(aIID, aInstancePtr);
if (result == NS_NOINTERFACE && aIID.Equals(nsIRadioButton::GetIID())) {
*aInstancePtr = (void*) ((nsIRadioButton*)this);
AddRef();
result = NS_OK;
}
return result;
}
//-------------------------------------------------------------------------
//
// Create the native RadioButton widget
//
//-------------------------------------------------------------------------
NS_METHOD nsRadioButton::CreateNative(GtkObject *parentWindow)
{
mWidget = gtk_event_box_new();
mRadioButton = gtk_radio_button_new(nsnull);
gtk_container_add(GTK_CONTAINER(mWidget), mRadioButton);
gtk_widget_show(mRadioButton);
gtk_widget_set_name(mWidget, "nsRadioButton");
gtk_radio_button_set_group(GTK_RADIO_BUTTON(mRadioButton), nsnull);
gtk_signal_connect(GTK_OBJECT(mRadioButton),
"destroy",
GTK_SIGNAL_FUNC(DestroySignal),
this);
return NS_OK;
}
void
nsRadioButton::OnDestroySignal(GtkWidget* aGtkWidget)
{
if (aGtkWidget == mLabel) {
mLabel = nsnull;
}
else if (aGtkWidget == mRadioButton) {
mRadioButton = nsnull;
}
else {
nsWidget::OnDestroySignal(aGtkWidget);
}
}
void nsRadioButton::InitCallbacks(char * aName)
{
InstallButtonPressSignal(mRadioButton);
InstallButtonReleaseSignal(mRadioButton);
InstallEnterNotifySignal(mWidget);
InstallLeaveNotifySignal(mWidget);
// These are needed so that the events will go to us and not our parent.
AddToEventMask(mWidget,
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_ENTER_NOTIFY_MASK |
GDK_EXPOSURE_MASK |
GDK_FOCUS_CHANGE_MASK |
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_POINTER_MOTION_MASK);
}
//-------------------------------------------------------------------------
//
// Set this button label
//
//-------------------------------------------------------------------------
NS_METHOD nsRadioButton::SetState(const PRBool aState)
{
if (mWidget) {
GtkToggleButton * item = GTK_TOGGLE_BUTTON(mRadioButton);
item->active = (gboolean) aState;
gtk_widget_queue_draw(GTK_WIDGET(item));
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set this button state
//-------------------------------------------------------------------------
NS_METHOD nsRadioButton::GetState(PRBool& aState)
{
if (mWidget) {
aState = (PRBool) GTK_TOGGLE_BUTTON(mRadioButton)->active;
}
else {
aState = PR_TRUE;
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set this button label
//
//-------------------------------------------------------------------------
NS_METHOD nsRadioButton::SetLabel(const nsString& aText)
{
if (mWidget) {
NS_ALLOC_STR_BUF(label, aText, 256);
g_print("nsRadioButton::SetLabel(%s)\n",label);
if (mLabel) {
gtk_label_set(GTK_LABEL(mLabel), label);
} else {
mLabel = gtk_label_new(label);
gtk_misc_set_alignment (GTK_MISC (mLabel), 0.0, 0.5);
gtk_container_add(GTK_CONTAINER(mRadioButton), mLabel);
gtk_widget_show(mLabel); /* XXX */
gtk_signal_connect(GTK_OBJECT(mLabel),
"destroy",
GTK_SIGNAL_FUNC(DestroySignal),
this);
}
NS_FREE_STR_BUF(label);
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get this button label
//
//-------------------------------------------------------------------------
NS_METHOD nsRadioButton::GetLabel(nsString& aBuffer)
{
aBuffer.Truncate();
if (mWidget) {
if (mLabel) {
char* text;
gtk_label_get(GTK_LABEL(mLabel), &text);
aBuffer.Append(text);
}
}
return NS_OK;
}
//////////////////////////////////////////////////////////////////////
// SetBackgroundColor for RadioButton
/*virtual*/
void nsRadioButton::SetBackgroundColorNative(GdkColor *aColorNor,
GdkColor *aColorBri,
GdkColor *aColorDark)
{
// use same style copy as SetFont
GtkStyle *style = gtk_style_copy(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0))->style);
style->bg[GTK_STATE_NORMAL]=*aColorNor;
// Mouse over button
style->bg[GTK_STATE_PRELIGHT]=*aColorBri;
// Button is down
style->bg[GTK_STATE_ACTIVE]=*aColorDark;
// other states too? (GTK_STATE_ACTIVE, GTK_STATE_PRELIGHT,
// GTK_STATE_SELECTED, GTK_STATE_INSENSITIVE)
gtk_widget_set_style(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0)), style);
// set style for eventbox too
gtk_widget_set_style(mWidget, style);
gtk_style_unref(style);
}

View File

@@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsRadioButton_h__
#define nsRadioButton_h__
#include "nsWidget.h"
#include "nsIRadioButton.h"
/**
* Native GTK+ Radiobutton wrapper
*/
class nsRadioButton : public nsWidget,
public nsIRadioButton
{
public:
nsRadioButton();
virtual ~nsRadioButton();
// nsISupports
NS_IMETHOD_(nsrefcnt) AddRef();
NS_IMETHOD_(nsrefcnt) Release();
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
// nsIRadioButton part
NS_IMETHOD SetLabel(const nsString& aText);
NS_IMETHOD GetLabel(nsString& aBuffer);
NS_IMETHOD SetState(const PRBool aState);
NS_IMETHOD GetState(PRBool& aState);
virtual PRBool OnMove(PRInt32 aX, PRInt32 aY) { return PR_FALSE; }
virtual PRBool OnPaint(nsPaintEvent & aEvent) { return PR_FALSE; }
virtual PRBool OnResize(nsRect &aRect) { return PR_FALSE; }
// These are needed to Override the auto check behavior
void Armed();
void DisArmed();
protected:
NS_IMETHOD CreateNative(GtkObject *parentWindow);
virtual void InitCallbacks(char * aName = nsnull);
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
// Sets background for checkbutton
virtual void SetBackgroundColorNative(GdkColor *aColorNor,
GdkColor *aColorBri,
GdkColor *aColorDark);
GtkWidget *mLabel;
GtkWidget *mRadioButton;
};
#endif // nsRadioButton_h__

View File

@@ -0,0 +1,455 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsScrollbar.h"
#include "nsGUIEvent.h"
#include "nsGtkEventHandler.h"
NS_IMPL_ADDREF_INHERITED(nsScrollbar, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsScrollbar, nsWidget)
NS_IMPL_QUERY_INTERFACE2(nsScrollbar, nsIScrollbar, nsIWidget)
//-------------------------------------------------------------------------
//
// nsScrollbar constructor
//
//-------------------------------------------------------------------------
nsScrollbar::nsScrollbar (PRBool aIsVertical):nsWidget (), nsIScrollbar ()
{
NS_INIT_REFCNT ();
mOrientation = (aIsVertical) ?
GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL;
}
//-------------------------------------------------------------------------
//
// nsScrollbar destructor
//
//-------------------------------------------------------------------------
nsScrollbar::~nsScrollbar ()
{
}
//-------------------------------------------------------------------------
//
// Create the native scrollbar widget
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::CreateNative (GtkObject * parentWindow)
{
// Create scrollbar, random default values
mAdjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 100, 1, 25, 25));
#ifdef USE_SUPERWIN
if (!GDK_IS_SUPERWIN(parentWindow)) {
g_print("Damn, brother. That's not a superwin.\n");
return NS_ERROR_FAILURE;
}
GdkSuperWin *superwin = GDK_SUPERWIN(parentWindow);
mMozBox = gtk_mozbox_new(superwin->bin_window);
#endif /* USE_SUPERWIN */
switch (mOrientation)
{
case GTK_ORIENTATION_HORIZONTAL:
mWidget = gtk_hscrollbar_new (mAdjustment);
break;
case GTK_ORIENTATION_VERTICAL:
mWidget = gtk_vscrollbar_new (mAdjustment);
break;
}
#ifdef USE_SUPERWIN
// make sure that we put the scrollbar into the mozbox
gtk_container_add(GTK_CONTAINER(mMozBox), mWidget);
#endif /* USE_SUPERWIN */
gtk_widget_set_name (mWidget, "nsScrollbar");
gtk_signal_connect (GTK_OBJECT (mAdjustment),
"value_changed",
GTK_SIGNAL_FUNC (handle_scrollbar_value_changed),
this);
gtk_signal_connect (GTK_OBJECT (mAdjustment),
"destroy",
GTK_SIGNAL_FUNC (DestroySignal),
this);
return NS_OK;
}
void
nsScrollbar::OnDestroySignal(GtkWidget* aGtkWidget)
{
if ((void*)aGtkWidget == (void*)mAdjustment) {
mAdjustment = nsnull;
}
else {
nsWidget::OnDestroySignal(aGtkWidget);
}
}
//-------------------------------------------------------------------------
//
// Define the range settings
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::SetMaxRange (PRUint32 aEndRange)
{
if (mAdjustment) {
GTK_ADJUSTMENT (mAdjustment)->upper = (float) aEndRange;
gtk_signal_emit_by_name (GTK_OBJECT (mAdjustment), "changed");
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Return the range settings
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::GetMaxRange (PRUint32 & aMaxRange)
{
if (mAdjustment)
aMaxRange = (PRUint32) GTK_ADJUSTMENT (mAdjustment)->upper;
else
aMaxRange = 0;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set the thumb position
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::SetPosition (PRUint32 aPos)
{
// if (mAdjustment)
// gtk_adjustment_set_value (GTK_ADJUSTMENT (mAdjustment), (float) aPos);
if (mAdjustment && mWidget)
{
//
// The following bit of code borrowed from gtkrange.c,
// gtk_range_adjustment_value_changed():
//
// Ok, so, like, the problem is that the view manager expects
// SetPosition() to simply do that - set the position of the
// scroll bar. Nothing else!
//
// Unfortunately, calling gtk_adjustment_set_value() causes
// the adjustment object (mAdjustment) to emit a
// "value_changed" signal which in turn causes the
// scrollbar widget (mWidget) to scroll to the given position.
//
// The net result of this is that the content is scrolled
// twice, once by the view manager and once by the
// scrollbar - and things get messed up from then onwards.
//
// The following bit of code does the equivalent of
// gtk_adjustment_set_value(), except no signal is emitted.
//
GtkRange * range = GTK_RANGE(mWidget);
GtkAdjustment * adjustment = GTK_ADJUSTMENT(mAdjustment);
adjustment->value = (float) aPos;
if (range->old_value != adjustment->value)
{
gtk_range_slider_update (range);
gtk_range_clear_background (range);
range->old_value = adjustment->value;
}
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get the current thumb position.
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::GetPosition (PRUint32 & aPos)
{
if (mAdjustment)
aPos = (PRUint32) GTK_ADJUSTMENT (mAdjustment)->value;
else
aPos = 0;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set the thumb size
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::SetThumbSize (PRUint32 aSize)
{
if (aSize > 0)
{
if (mAdjustment) {
GTK_ADJUSTMENT (mAdjustment)->page_increment = (float) aSize;
GTK_ADJUSTMENT (mAdjustment)->page_size = (float) aSize;
gtk_signal_emit_by_name (GTK_OBJECT (mAdjustment), "changed");
}
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get the thumb size
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::GetThumbSize (PRUint32 & aThumbSize)
{
if (mAdjustment)
aThumbSize = (PRUint32) GTK_ADJUSTMENT (mAdjustment)->page_size;
else
aThumbSize = 0;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set the line increment for this scrollbar
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::SetLineIncrement (PRUint32 aLineIncrement)
{
if (aLineIncrement > 0)
{
if (mAdjustment) {
GTK_ADJUSTMENT (mAdjustment)->step_increment = (float) aLineIncrement;
gtk_signal_emit_by_name (GTK_OBJECT (mAdjustment), "changed");
}
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get the line increment for this scrollbar
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::GetLineIncrement (PRUint32 & aLineInc)
{
if (mAdjustment) {
aLineInc = (PRUint32) GTK_ADJUSTMENT (mAdjustment)->step_increment;
}
else
aLineInc = 0;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set all scrolling parameters
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::SetParameters (PRUint32 aMaxRange, PRUint32 aThumbSize,
PRUint32 aPosition, PRUint32 aLineIncrement)
{
if (mAdjustment) {
int thumbSize = (((int) aThumbSize) > 0 ? aThumbSize : 1);
int maxRange = (((int) aMaxRange) > 0 ? aMaxRange : 10);
int mLineIncrement = (((int) aLineIncrement) > 0 ? aLineIncrement : 1);
int maxPos = maxRange - thumbSize;
int pos = ((int) aPosition) > maxPos ? maxPos - 1 : ((int) aPosition);
GTK_ADJUSTMENT (mAdjustment)->lower = 0;
GTK_ADJUSTMENT (mAdjustment)->upper = maxRange;
GTK_ADJUSTMENT (mAdjustment)->page_size = thumbSize;
GTK_ADJUSTMENT (mAdjustment)->page_increment = thumbSize;
GTK_ADJUSTMENT (mAdjustment)->step_increment = mLineIncrement;
// this will emit the changed signal for us
gtk_adjustment_set_value (GTK_ADJUSTMENT (mAdjustment), pos);
}
return NS_OK;
}
//-------------------------------------------------------------------------
int nsScrollbar::AdjustScrollBarPosition (int aPosition)
{
return 0; /* XXX */
}
//-------------------------------------------------------------------------
//
// Deal with scrollbar messages (actually implemented only in nsScrollbar)
//
//-------------------------------------------------------------------------
PRBool nsScrollbar::OnScroll (nsScrollbarEvent & aEvent, PRUint32 cPos)
{
PRBool result = PR_TRUE;
float newPosition;
switch (aEvent.message)
{
// scroll one line right or down
case NS_SCROLLBAR_LINE_NEXT:
{
newPosition = GTK_ADJUSTMENT (mAdjustment)->value;
// newPosition += mLineIncrement;
newPosition += 10;
PRUint32 thumbSize;
PRUint32 maxRange;
GetThumbSize (thumbSize);
GetMaxRange (maxRange);
PRUint32 max = maxRange - thumbSize;
if (newPosition > (int) max)
newPosition = (int) max;
// if an event callback is registered, give it the chance
// to change the increment
if (mEventCallback)
{
aEvent.position = (PRUint32) newPosition;
result = ConvertStatus ((*mEventCallback) (&aEvent));
newPosition = aEvent.position;
}
break;
}
// scroll one line left or up
case NS_SCROLLBAR_LINE_PREV:
{
newPosition = GTK_ADJUSTMENT (mAdjustment)->value;
// newPosition -= mLineIncrement;
newPosition -= 10;
if (newPosition < 0)
newPosition = 0;
// if an event callback is registered, give it the chance
// to change the decrement
if (mEventCallback)
{
aEvent.position = (PRUint32) newPosition;
aEvent.widget = (nsWidget *) this;
result = ConvertStatus ((*mEventCallback) (&aEvent));
newPosition = aEvent.position;
}
break;
}
// Scrolls one page right or down
case NS_SCROLLBAR_PAGE_NEXT:
{
newPosition = GTK_ADJUSTMENT (mAdjustment)->value;
PRUint32 thumbSize;
GetThumbSize (thumbSize);
PRUint32 maxRange;
GetThumbSize (thumbSize);
GetMaxRange (maxRange);
PRUint32 max = maxRange - thumbSize;
if (newPosition > (int) max)
newPosition = (int) max;
// if an event callback is registered, give it the chance
// to change the increment
if (mEventCallback)
{
aEvent.position = (PRUint32) newPosition;
result = ConvertStatus ((*mEventCallback) (&aEvent));
newPosition = aEvent.position;
}
break;
}
// Scrolls one page left or up.
case NS_SCROLLBAR_PAGE_PREV:
{
newPosition = GTK_ADJUSTMENT (mAdjustment)->value;
if (newPosition < 0)
newPosition = 0;
// if an event callback is registered, give it the chance
// to change the increment
if (mEventCallback)
{
aEvent.position = (PRUint32) newPosition;
result = ConvertStatus ((*mEventCallback) (&aEvent));
newPosition = aEvent.position;
}
break;
}
// Scrolls to the absolute position. The current position is specified by
// the cPos parameter.
case NS_SCROLLBAR_POS:
{
newPosition = cPos;
// if an event callback is registered, give it the chance
// to change the increment
if (mEventCallback)
{
aEvent.position = (PRUint32) newPosition;
result = ConvertStatus ((*mEventCallback) (&aEvent));
newPosition = aEvent.position;
}
break;
}
}
/*
GTK_ADJUSTMENT(mAdjustment)->value = newPosition;
gtk_signal_emit_by_name(GTK_OBJECT(mAdjustment), "value_changed");
*/
/*
if (mEventCallback) {
aEvent.position = cPos;
result = ConvertStatus((*mEventCallback)(&aEvent));
newPosition = aEvent.position;
}
*/
return result;
}

View File

@@ -0,0 +1,66 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the 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 nsScrollbar_h__
#define nsScrollbar_h__
#include "nsWidget.h"
#include "nsIScrollbar.h"
/**
* Native GTK+ scrollbar wrapper.
*/
class nsScrollbar : public nsWidget,
public nsIScrollbar
{
public:
nsScrollbar(PRBool aIsVertical);
virtual ~nsScrollbar();
NS_DECL_ISUPPORTS_INHERITED
// nsIScrollBar implementation
NS_IMETHOD SetMaxRange(PRUint32 aEndRange);
NS_IMETHOD GetMaxRange(PRUint32& aMaxRange);
NS_IMETHOD SetPosition(PRUint32 aPos);
NS_IMETHOD GetPosition(PRUint32& aPos);
NS_IMETHOD SetThumbSize(PRUint32 aSize);
NS_IMETHOD GetThumbSize(PRUint32& aSize);
NS_IMETHOD SetLineIncrement(PRUint32 aSize);
NS_IMETHOD GetLineIncrement(PRUint32& aSize);
NS_IMETHOD SetParameters(PRUint32 aMaxRange, PRUint32 aThumbSize,
PRUint32 aPosition, PRUint32 aLineIncrement);
virtual PRBool OnScroll (nsScrollbarEvent & aEvent, PRUint32 cPos);
protected:
NS_IMETHOD CreateNative(GtkObject *parentWindow);
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
private:
int mOrientation;
GtkAdjustment *mAdjustment;
int AdjustScrollBarPosition(int aPosition);
};
#endif /* nsScrollbar_h__ */

View File

@@ -0,0 +1,125 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nscore.h"
#include "nsIAllocator.h"
#include "plstr.h"
#include "stdio.h"
#include "prlink.h"
#include "nsSound.h"
#include <unistd.h>
#include <gtk/gtk.h>
/* used with esd_open_sound */
//static int esdref = -1;
static PRLibrary *lib = nsnull;
//typedef int (PR_CALLBACK *EsdOpenSoundType)(const char *host);
//typedef int (PR_CALLBACK *EsdCloseType)(int);
/* used to play the sounds from the find symbol call */
typedef int (PR_CALLBACK *EsdPlayFileType)(const char *, const char *, int);
NS_IMPL_ISUPPORTS1(nsSound, nsISound);
////////////////////////////////////////////////////////////////////////
nsSound::nsSound()
{
NS_INIT_REFCNT();
/* we don't need to do esd_open_sound if we are only going to play files
but we will if we want to do things like streams, etc
*/
// EsdOpenSoundType EsdOpenSound;
lib = PR_LoadLibrary("libesd.so");
/*
if (!lib)
return;
EsdOpenSound = (EsdOpenSoundType) PR_FindSymbol(lib, "esd_open_sound");
esdref = (*EsdOpenSound)("localhost");
*/
}
nsSound::~nsSound()
{
/* see above comment */
/*
if (esdref != -1)
{
EsdCloseType EsdClose = (EsdCloseType) PR_FindSymbol(lib, "esd_close");
(*EsdClose)(esdref);
esdref = -1;
}
*/
}
nsresult NS_NewSound(nsISound** aSound)
{
NS_PRECONDITION(aSound != nsnull, "null ptr");
if (! aSound)
return NS_ERROR_NULL_POINTER;
*aSound = new nsSound();
if (! *aSound)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aSound);
return NS_OK;
}
NS_METHOD nsSound::Init(void)
{
return NS_OK;
}
NS_METHOD nsSound::Beep()
{
::gdk_beep();
return NS_OK;
}
NS_METHOD nsSound::Play(nsIFileSpec *filespec)
{
if (lib)
{
char *filename;
filespec->GetNativePath(&filename);
g_print("there are some issues with playing sound right now, but this should work\n");
EsdPlayFileType EsdPlayFile = (EsdPlayFileType) PR_FindSymbol(lib, "esd_play_file");
(*EsdPlayFile)("mozilla", filename, 1);
nsCRT::free(filename);
return NS_OK;
}
return NS_OK;
}

View File

@@ -20,11 +20,22 @@
* Contributor(s):
*/
#include "nsISupports.idl"
#ifndef __nsSound_h__
#define __nsSound_h__
#include "nsISound.h"
#include <gtk/gtk.h>
class nsSound : public nsISound {
public:
nsSound();
virtual ~nsSound();
NS_DECL_ISUPPORTS
NS_DECL_NSISOUND
[scriptable, uuid(6ccb17a0-e95e-11d1-beae-00805f8a66dc)]
interface nsIBaseStream : nsISupports
{
/** Close the stream. */
void Close();
};
#endif /* __nsSound_h__ */

View File

@@ -0,0 +1,97 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsTextAreaWidget.h"
#include "nsString.h"
NS_IMPL_ADDREF_INHERITED(nsTextAreaWidget, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsTextAreaWidget, nsWidget)
NS_IMPL_QUERY_INTERFACE2(nsTextAreaWidget, nsITextAreaWidget, nsIWidget)
//-------------------------------------------------------------------------
//
// nsTextAreaWidget constructor
//
//-------------------------------------------------------------------------
nsTextAreaWidget::nsTextAreaWidget()
{
mBackground = NS_RGB(124, 124, 124);
}
//-------------------------------------------------------------------------
//
// nsTextAreaWidget destructor
//
//-------------------------------------------------------------------------
nsTextAreaWidget::~nsTextAreaWidget()
{
gtk_widget_destroy(mTextWidget);
mTextWidget = nsnull;
}
//-------------------------------------------------------------------------
//
// Create the native Text widget
//
//-------------------------------------------------------------------------
NS_METHOD nsTextAreaWidget::CreateNative(GtkObject *parentWindow)
{
PRBool oldIsReadOnly;
mWidget = gtk_scrolled_window_new(nsnull, nsnull);
gtk_container_set_border_width(GTK_CONTAINER(mWidget), 0);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(mWidget),
GTK_POLICY_NEVER,
GTK_POLICY_ALWAYS);
mTextWidget = gtk_text_new(nsnull, nsnull);
gtk_text_set_word_wrap(GTK_TEXT(mTextWidget), PR_TRUE);
gtk_widget_set_name(mTextWidget, "nsTextAreaWidget");
gtk_widget_show(mTextWidget);
SetPassword(mIsPassword);
SetReadOnly(mIsReadOnly, oldIsReadOnly);
gtk_container_add(GTK_CONTAINER(mWidget), mTextWidget);
return NS_OK;
}
//-------------------------------------------------------------------------
//
// set font for textarea
//
//-------------------------------------------------------------------------
/* virtual */
void nsTextAreaWidget::SetFontNative(GdkFont *aFont)
{
GtkStyle *style = gtk_style_copy(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0))->style);
// gtk_style_copy ups the ref count of the font
gdk_font_unref (style->font);
style->font = aFont;
gdk_font_ref(style->font);
gtk_widget_set_style(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0)), style);
gtk_style_unref(style);
}

View File

@@ -20,28 +20,30 @@
* Contributor(s):
*/
#ifndef nsAtomTable_h__
#define nsAtomTable_h__
#ifndef nsTextAreaWidget_h__
#define nsTextAreaWidget_h__
#include "nsIAtom.h"
#include "nsTextHelper.h"
#include "nsITextAreaWidget.h"
/**
* Native GTK+ multi-line edit control wrapper.
*/
class nsTextAreaWidget : public nsTextHelper
{
class AtomImpl : public nsIAtom {
public:
AtomImpl();
virtual ~AtomImpl();
nsTextAreaWidget();
virtual ~nsTextAreaWidget();
NS_DECL_ISUPPORTS
NS_DECL_NSIATOM
NS_DECL_ISUPPORTS_INHERITED
void* operator new(size_t size, const nsAReadableString& aString);
virtual void SetFontNative(GdkFont *aFont);
void operator delete(void* ptr) {
::operator delete(ptr);
}
// Actually more; 0 terminated. This slot is reserved for the
// terminating zero.
PRUnichar mString[1];
protected:
NS_METHOD CreateNative(GtkObject *parentWindow);
};
#endif // nsAtomTable_h__
#endif // nsTextAreaWidget_h__

View File

@@ -0,0 +1,216 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsTextHelper.h"
#include "nsTextWidget.h"
#include "nsString.h"
NS_IMPL_ADDREF_INHERITED(nsTextHelper, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsTextHelper, nsWidget)
//-------------------------------------------------------------------------
//
// nsTextHelper constructor
//
//-------------------------------------------------------------------------
nsTextHelper::nsTextHelper() : nsWidget(), nsITextAreaWidget(), nsITextWidget()
{
mIsReadOnly = PR_FALSE;
mIsPassword = PR_FALSE;
}
//-------------------------------------------------------------------------
//
// nsTextHelper destructor
//
//-------------------------------------------------------------------------
nsTextHelper::~nsTextHelper()
{
}
//-------------------------------------------------------------------------
//
// Set initial parameters
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::PreCreateWidget(nsWidgetInitData *aInitData)
{
if (nsnull != aInitData) {
nsTextWidgetInitData* data = (nsTextWidgetInitData *) aInitData;
mIsPassword = data->mIsPassword;
mIsReadOnly = data->mIsReadOnly;
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::SetMaxTextLength(PRUint32 aChars)
{
// This is a normal entry only thing, not a text box
gtk_entry_set_max_length(GTK_ENTRY(mTextWidget), (int)aChars);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::GetText(nsString& aTextBuffer, PRUint32 aBufferSize, PRUint32& aActualSize)
{
char *str = nsnull;
if (GTK_IS_ENTRY(mTextWidget))
{
str = gtk_entry_get_text(GTK_ENTRY(mTextWidget));
}
else if (GTK_IS_TEXT(mTextWidget))
{
str = gtk_editable_get_chars (GTK_EDITABLE (mTextWidget), 0,
gtk_text_get_length (GTK_TEXT (mTextWidget)));
}
aTextBuffer.SetLength(0);
aTextBuffer.Append(str);
PRUint32 len = (PRUint32)strlen(str);
aActualSize = len;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::SetText(const nsString& aText, PRUint32& aActualSize)
{
if (GTK_IS_ENTRY(mTextWidget)) {
gtk_entry_set_text(GTK_ENTRY(mTextWidget),
(const gchar *)nsAutoCString(aText));
} else if (GTK_IS_TEXT(mTextWidget)) {
gtk_editable_delete_text(GTK_EDITABLE(mTextWidget), 0,
gtk_text_get_length(GTK_TEXT (mTextWidget)));
gtk_text_insert(GTK_TEXT(mTextWidget),
nsnull, nsnull, nsnull,
(const char *)nsAutoCString(aText),
aText.Length());
}
aActualSize = aText.Length();
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::InsertText(const nsString &aText,
PRUint32 aStartPos,
PRUint32 aEndPos,
PRUint32& aActualSize)
{
gtk_editable_insert_text(GTK_EDITABLE(mTextWidget),
(const gchar *)nsAutoCString(aText),
(gint)aText.Length(), (gint*)&aStartPos);
aActualSize = aText.Length();
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::RemoveText()
{
if (GTK_IS_ENTRY(mTextWidget)) {
gtk_entry_set_text(GTK_ENTRY(mTextWidget), "");
} else if (GTK_IS_TEXT(mTextWidget)) {
gtk_editable_delete_text(GTK_EDITABLE(mTextWidget), 0,
gtk_text_get_length(GTK_TEXT (mTextWidget)));
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::SetPassword(PRBool aIsPassword)
{
mIsPassword = aIsPassword?PR_FALSE:PR_TRUE;
if (GTK_IS_ENTRY(mTextWidget)) {
gtk_entry_set_visibility(GTK_ENTRY(mTextWidget), mIsPassword);
}
// this won't work for gtk_texts
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::SetReadOnly(PRBool aReadOnlyFlag, PRBool& aOldReadOnlyFlag)
{
NS_ASSERTION(nsnull != mTextWidget,
"SetReadOnly - Widget is NULL, Create may not have been called!");
aOldReadOnlyFlag = mIsReadOnly;
mIsReadOnly = aReadOnlyFlag?PR_FALSE:PR_TRUE;
gtk_editable_set_editable(GTK_EDITABLE(mTextWidget), mIsReadOnly);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::SelectAll()
{
nsString text;
PRUint32 actualSize = 0;
PRUint32 numChars = GetText(text, 0, actualSize);
SetSelection(0, numChars);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::SetSelection(PRUint32 aStartSel, PRUint32 aEndSel)
{
gtk_editable_select_region(GTK_EDITABLE(mTextWidget), aStartSel, aEndSel);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::GetSelection(PRUint32 *aStartSel, PRUint32 *aEndSel)
{
#if 0
XmTextPosition left;
XmTextPosition right;
if (XmTextGetSelectionPosition(mTextWidget, &left, &right)) {
*aStartSel = (PRUint32)left;
*aEndSel = (PRUint32)right;
} else {
printf("nsTextHelper::GetSelection Error getting positions\n");
return NS_ERROR_FAILURE;
}
#endif
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::SetCaretPosition(PRUint32 aPosition)
{
gtk_editable_set_position(GTK_EDITABLE(mTextWidget), aPosition);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::GetCaretPosition(PRUint32& aPosition)
{
aPosition = (PRUint32)GTK_EDITABLE(mTextWidget)->current_pos;
return NS_OK;
}

View File

@@ -0,0 +1,66 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the 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 nsTextHelper_h__
#define nsTextHelper_h__
#include "nsITextWidget.h"
#include "nsITextAreaWidget.h"
#include "nsWidget.h"
/**
* Base class for nsTextAreaWidget and nsTextWidget
*/
class nsTextHelper : public nsWidget,
public nsITextAreaWidget,
public nsITextWidget
{
public:
nsTextHelper();
virtual ~nsTextHelper();
// nsISupports
NS_IMETHOD_(nsrefcnt) AddRef();
NS_IMETHOD_(nsrefcnt) Release();
NS_IMETHOD SelectAll();
NS_IMETHOD PreCreateWidget(nsWidgetInitData *aInitData);
NS_IMETHOD SetMaxTextLength(PRUint32 aChars);
NS_IMETHOD GetText(nsString& aTextBuffer, PRUint32 aBufferSize, PRUint32& aActualSize);
NS_IMETHOD SetText(const nsString &aText, PRUint32& aActualSize);
NS_IMETHOD InsertText(const nsString &aText, PRUint32 aStartPos, PRUint32 aEndPos, PRUint32& aActualSize);
NS_IMETHOD RemoveText();
NS_IMETHOD SetPassword(PRBool aIsPassword);
NS_IMETHOD SetReadOnly(PRBool aNewReadOnlyFlag, PRBool& aOldReadOnlyFlag);
NS_IMETHOD SetSelection(PRUint32 aStartSel, PRUint32 aEndSel);
NS_IMETHOD GetSelection(PRUint32 *aStartSel, PRUint32 *aEndSel);
NS_IMETHOD SetCaretPosition(PRUint32 aPosition);
NS_IMETHOD GetCaretPosition(PRUint32& aPosition);
protected:
GtkWidget *mTextWidget;
PRBool mIsPassword;
PRBool mIsReadOnly;
};
#endif // nsTextHelper_h__

View File

@@ -0,0 +1,130 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsTextWidget.h"
#include "nsString.h"
#include "nsGtkEventHandler.h"
extern int mIsPasswordCallBacksInstalled;
NS_IMPL_ADDREF_INHERITED(nsTextWidget, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsTextWidget, nsWidget)
NS_IMPL_QUERY_INTERFACE2(nsTextWidget, nsITextWidget, nsIWidget)
//-------------------------------------------------------------------------
//
// nsTextWidget constructor
//
//-------------------------------------------------------------------------
nsTextWidget::nsTextWidget() : nsTextHelper()
{
}
//-------------------------------------------------------------------------
//
// nsTextWidget destructor
//
//-------------------------------------------------------------------------
nsTextWidget::~nsTextWidget()
{
// avoid freeing this twice in other destructors
mTextWidget = nsnull;
}
//-------------------------------------------------------------------------
//
// Create the native Entry widget
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextWidget::CreateNative(GtkObject *parentWindow)
{
PRBool oldIsReadOnly;
mWidget = gtk_entry_new();
#ifdef USE_SUPERWIN
if (!GDK_IS_SUPERWIN(parentWindow)) {
g_print("Damn, brother. That's not a superwin.\n");
return NS_ERROR_FAILURE;
}
GdkSuperWin *superwin = GDK_SUPERWIN(parentWindow);
mMozBox = gtk_mozbox_new(superwin->bin_window);
#endif /* USE_SUPERWIN */
// used by nsTextHelper because nsTextArea needs a scrolled_window
mTextWidget = mWidget;
gtk_widget_set_name(mWidget, "nsTextWidget");
/*
* GTK's text widget does XIM for us, so we don't want to use the default key handler
* which does XIM, so we connect to a non-XIM key event for the text widget
*/
gtk_signal_connect_after(GTK_OBJECT(mWidget),
"key_press_event",
GTK_SIGNAL_FUNC(handle_key_press_event_for_text),
this);
gtk_signal_connect(GTK_OBJECT(mWidget),
"key_release_event",
GTK_SIGNAL_FUNC(handle_key_release_event_for_text),
this);
SetPassword(mIsPassword);
SetReadOnly(mIsReadOnly, oldIsReadOnly);
gtk_widget_show(mWidget);
// These are needed so that the events will go to us and not our parent.
AddToEventMask(mWidget,
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_ENTER_NOTIFY_MASK |
GDK_EXPOSURE_MASK |
GDK_FOCUS_CHANGE_MASK |
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_POINTER_MOTION_MASK);
#ifdef USE_SUPERWIN
// make sure that we put the scrollbar into the mozbox
gtk_container_add(GTK_CONTAINER(mMozBox), mWidget);
#endif /* USE_SUPERWIN */
return NS_OK;
}
PRBool nsTextWidget::OnKey(nsKeyEvent &aEvent)
{
if (mEventCallback) {
return DispatchWindowEvent(&aEvent);
}
return PR_FALSE;
}

View File

@@ -20,14 +20,29 @@
* Contributor(s):
*/
#include "nsIInputStream.idl"
#ifndef nsTextWidget_h__
#define nsTextWidget_h__
[scriptable, uuid(b5a21556-35fc-4815-aff1-f9142639686e)]
interface nsIByteArrayInputStream : nsIInputStream
#include "nsTextHelper.h"
#include "nsITextWidget.h"
/**
* Native GTK+ single line edit control wrapper.
*/
class nsTextWidget : public nsTextHelper
{
public:
nsTextWidget();
virtual ~nsTextWidget();
NS_DECL_ISUPPORTS_INHERITED
PRBool OnKey(nsKeyEvent &aEvent);
protected:
NS_IMETHOD CreateNative(GtkObject *parentWindow);
};
%{C++
extern NS_COM nsresult
NS_NewByteArrayInputStream (nsIByteArrayInputStream ** aResult, char * buffer, unsigned long size);
%}
#endif // nsTextWidget_h__

View File

@@ -0,0 +1,144 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nscore.h" // needed for 'nsnull'
#include "nsToolkit.h"
//
// Static thread local storage index of the Toolkit
// object associated with a given thread...
//
static PRUintn gToolkitTLSIndex = 0;
//-------------------------------------------------------------------------
//
// constructor
//
//-------------------------------------------------------------------------
nsToolkit::nsToolkit()
{
NS_INIT_REFCNT();
mSharedGC = nsnull;
}
//-------------------------------------------------------------------------
//
// destructor
//
//-------------------------------------------------------------------------
nsToolkit::~nsToolkit()
{
if (mSharedGC)
gdk_gc_unref(mSharedGC);
// Remove the TLS reference to the toolkit...
PR_SetThreadPrivate(gToolkitTLSIndex, nsnull);
}
//-------------------------------------------------------------------------
//
// nsISupports implementation macro
//
//-------------------------------------------------------------------------
NS_IMPL_ISUPPORTS1(nsToolkit, nsIToolkit)
void nsToolkit::CreateSharedGC(void)
{
GdkPixmap *pixmap;
if (mSharedGC)
return;
pixmap = ::gdk_pixmap_new (NULL, 1, 1, gdk_rgb_get_visual()->depth);
mSharedGC = ::gdk_gc_new (pixmap);
gdk_pixmap_unref (pixmap);
mSharedGC = gdk_gc_ref(mSharedGC);
}
GdkGC *nsToolkit::GetSharedGC(void)
{
return gdk_gc_ref(mSharedGC);
}
//-------------------------------------------------------------------------
//
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsToolkit::Init(PRThread *aThread)
{
CreateSharedGC();
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Return the nsIToolkit for the current thread. If a toolkit does not
// yet exist, then one will be created...
//
//-------------------------------------------------------------------------
NS_METHOD NS_GetCurrentToolkit(nsIToolkit* *aResult)
{
nsIToolkit* toolkit = nsnull;
nsresult rv = NS_OK;
PRStatus status;
// Create the TLS index the first time through...
if (0 == gToolkitTLSIndex) {
status = PR_NewThreadPrivateIndex(&gToolkitTLSIndex, NULL);
if (PR_FAILURE == status) {
rv = NS_ERROR_FAILURE;
}
}
if (NS_SUCCEEDED(rv)) {
toolkit = (nsIToolkit*)PR_GetThreadPrivate(gToolkitTLSIndex);
//
// Create a new toolkit for this thread...
//
if (!toolkit) {
toolkit = new nsToolkit();
if (!toolkit) {
rv = NS_ERROR_OUT_OF_MEMORY;
} else {
NS_ADDREF(toolkit);
toolkit->Init(PR_GetCurrentThread());
//
// The reference stored in the TLS is weak. It is removed in the
// nsToolkit destructor...
//
PR_SetThreadPrivate(gToolkitTLSIndex, (void*)toolkit);
}
} else {
NS_ADDREF(toolkit);
}
*aResult = toolkit;
}
return rv;
}

View File

@@ -20,35 +20,36 @@
* Contributor(s):
*/
#ifndef nsArena_h__
#define nsArena_h__
#ifndef TOOLKIT_H
#define TOOLKIT_H
#include "nsIArena.h"
#include "nsIToolkit.h"
#include <gtk/gtk.h>
#define PL_ARENA_CONST_ALIGN_MASK 7
#include "plarena.h"
/**
* Wrapper around the thread running the message pump.
* The toolkit abstraction is necessary because the message pump must
* execute within the same thread that created the widget under Win32.
*/
class nsToolkit : public nsIToolkit
{
// Simple arena implementation layered on plarena
class ArenaImpl : public nsIArena {
public:
ArenaImpl(void);
virtual ~ArenaImpl();
nsToolkit();
virtual ~nsToolkit();
NS_DECL_ISUPPORTS
static NS_METHOD
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
NS_IMETHOD Init(PRUint32 arenaBlockSize);
NS_IMETHOD_(void*) Alloc(PRUint32 size);
protected:
PLArenaPool mPool;
PRUint32 mBlockSize;
NS_IMETHOD Init(PRThread *aThread);
void CreateSharedGC(void);
GdkGC *GetSharedGC(void);
private:
PRBool mInitialized;
GdkGC *mSharedGC;
};
#endif // nsArena_h__
#endif // TOOLKIT_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,410 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsWidget_h__
#define nsWidget_h__
#include "nsBaseWidget.h"
#include "nsIRegion.h"
// XXX: This must go away when nsAutoCString moves out of nsFileSpec.h
#include "nsFileSpec.h" // for nsAutoCString()
class nsILookAndFeel;
class nsIAppShell;
class nsIToolkit;
#include <gtk/gtk.h>
#include <gdk/gdkprivate.h>
#include "gtkmozbox.h"
#define USE_SUPERWIN
#define NSRECT_TO_GDKRECT(ns,gdk) \
PR_BEGIN_MACRO \
gdk.x = ns.x; \
gdk.y = ns.y; \
gdk.width = ns.width; \
gdk.height = ns.height; \
PR_END_MACRO
#define NSCOLOR_TO_GDKCOLOR(n,g) \
PR_BEGIN_MACRO \
g.red = 256 * NS_GET_R(n); \
g.green = 256 * NS_GET_G(n); \
g.blue = 256 * NS_GET_B(n); \
PR_END_MACRO
#define NS_TO_GDK_RGB(ns) (ns & 0xff) << 16 | (ns & 0xff00) | ((ns >> 16) & 0xff)
/**
* Base of all GTK+ native widgets.
*/
class nsWidget : public nsBaseWidget
{
public:
nsWidget();
virtual ~nsWidget();
NS_IMETHOD Create(nsIWidget *aParent,
const nsRect &aRect,
EVENT_CALLBACK aHandleEventFunction,
nsIDeviceContext *aContext,
nsIAppShell *aAppShell = nsnull,
nsIToolkit *aToolkit = nsnull,
nsWidgetInitData *aInitData = nsnull);
NS_IMETHOD Create(nsNativeWidget aParent,
const nsRect &aRect,
EVENT_CALLBACK aHandleEventFunction,
nsIDeviceContext *aContext,
nsIAppShell *aAppShell = nsnull,
nsIToolkit *aToolkit = nsnull,
nsWidgetInitData *aInitData = nsnull);
NS_IMETHOD Destroy(void);
nsIWidget* GetParent(void);
NS_IMETHOD SetModal(PRBool aModal);
NS_IMETHOD Show(PRBool state);
NS_IMETHOD CaptureRollupEvents(nsIRollupListener *aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent);
NS_IMETHOD IsVisible(PRBool &aState);
NS_IMETHOD Move(PRInt32 aX, PRInt32 aY);
NS_IMETHOD Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint);
NS_IMETHOD Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth,
PRInt32 aHeight, PRBool aRepaint);
NS_IMETHOD Enable(PRBool aState);
NS_IMETHOD SetFocus(void);
PRBool OnResize(nsSizeEvent event);
virtual PRBool OnResize(nsRect &aRect);
virtual PRBool OnMove(PRInt32 aX, PRInt32 aY);
nsIFontMetrics *GetFont(void);
NS_IMETHOD SetFont(const nsFont &aFont);
NS_IMETHOD SetBackgroundColor(const nscolor &aColor);
NS_IMETHOD SetCursor(nsCursor aCursor);
NS_IMETHOD SetColorMap(nsColorMap *aColorMap);
void* GetNativeData(PRUint32 aDataType);
NS_IMETHOD GetAbsoluteBounds(nsRect &aRect);
NS_IMETHOD WidgetToScreen(const nsRect &aOldRect, nsRect &aNewRect);
NS_IMETHOD ScreenToWidget(const nsRect &aOldRect, nsRect &aNewRect);
NS_IMETHOD BeginResizingChildren(void);
NS_IMETHOD EndResizingChildren(void);
NS_IMETHOD GetPreferredSize(PRInt32& aWidth, PRInt32& aHeight);
NS_IMETHOD SetPreferredSize(PRInt32 aWidth, PRInt32 aHeight);
// Use this to set the name of a widget for normal widgets.. not the same as the nsWindow version
NS_IMETHOD SetTitle(const nsString& aTitle);
virtual void ConvertToDeviceCoordinates(nscoord &aX, nscoord &aY);
// the following are nsWindow specific, and just stubbed here
NS_IMETHOD Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect) { return NS_ERROR_FAILURE; }
NS_IMETHOD SetMenuBar(nsIMenuBar *aMenuBar) { return NS_ERROR_FAILURE; }
NS_IMETHOD ShowMenuBar(PRBool aShow) { return NS_ERROR_FAILURE; }
// *could* be done on a widget, but that would be silly wouldn't it?
NS_IMETHOD CaptureMouse(PRBool aCapture) { return NS_ERROR_FAILURE; }
NS_IMETHOD Invalidate(PRBool aIsSynchronous);
NS_IMETHOD Invalidate(const nsRect &aRect, PRBool aIsSynchronous);
NS_IMETHOD InvalidateRegion(const nsIRegion *aRegion, PRBool aIsSynchronous);
NS_IMETHOD Update(void);
NS_IMETHOD DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus);
void InitEvent(nsGUIEvent& event, PRUint32 aEventType, nsPoint* aPoint = nsnull);
// Utility functions
void HandleEvent(GdkEvent *event);
PRBool ConvertStatus(nsEventStatus aStatus);
PRBool DispatchMouseEvent(nsMouseEvent& aEvent);
PRBool DispatchStandardEvent(PRUint32 aMsg);
PRBool DispatchFocus(nsGUIEvent &aEvent);
// are we a "top level" widget?
PRBool mIsToplevel;
#ifdef DEBUG
void IndentByDepth(FILE* out);
#endif
// Return the Gdk window used for rendering
virtual GdkWindow * GetRenderWindow(GtkObject * aGtkWidget);
protected:
virtual void InitCallbacks(char * aName = nsnull);
virtual void OnDestroy();
NS_IMETHOD CreateNative(GtkObject *parentWindow) { return NS_OK; }
nsresult CreateWidget(nsIWidget *aParent,
const nsRect &aRect,
EVENT_CALLBACK aHandleEventFunction,
nsIDeviceContext *aContext,
nsIAppShell *aAppShell,
nsIToolkit *aToolkit,
nsWidgetInitData *aInitData,
nsNativeWidget aNativeParent = nsnull);
PRBool DispatchWindowEvent(nsGUIEvent* event);
// Return the Gdk window whose background should change
virtual GdkWindow *GetWindowForSetBackground();
// Sets font for widgets
virtual void SetFontNative(GdkFont *aFont);
// Sets backround for widgets
virtual void SetBackgroundColorNative(GdkColor *aColorNor,
GdkColor *aColorBri,
GdkColor *aColorDark);
//////////////////////////////////////////////////////////////////
//
// GTK signal installers
//
//////////////////////////////////////////////////////////////////
void InstallMotionNotifySignal(GtkWidget * aWidget);
void InstallDragMotionSignal(GtkWidget * aWidget);
void InstallDragLeaveSignal(GtkWidget * aWidget);
void InstallDragBeginSignal(GtkWidget * aWidget);
void InstallDragDropSignal(GtkWidget * aWidget);
void InstallEnterNotifySignal(GtkWidget * aWidget);
void InstallLeaveNotifySignal(GtkWidget * aWidget);
void InstallButtonPressSignal(GtkWidget * aWidget);
void InstallButtonReleaseSignal(GtkWidget * aWidget);
virtual
void InstallFocusInSignal(GtkWidget * aWidget);
virtual
void InstallFocusOutSignal(GtkWidget * aWidget);
void InstallRealizeSignal(GtkWidget * aWidget);
void AddToEventMask(GtkWidget * aWidget,
gint aEventMask);
//////////////////////////////////////////////////////////////////
//
// OnSomething handlers
//
//////////////////////////////////////////////////////////////////
virtual void OnMotionNotifySignal(GdkEventMotion * aGdkMotionEvent);
virtual void OnDragMotionSignal(GdkDragContext *aGdkDragContext,
gint x,
gint y,
guint time);
/* OnDragEnterSignal is not a real signal.. it is only called from OnDragMotionSignal */
virtual void OnDragEnterSignal(GdkDragContext *aGdkDragContext,
gint x,
gint y,
guint time);
virtual void OnDragLeaveSignal(GdkDragContext *context,
guint time);
virtual void OnDragBeginSignal(GdkDragContext *aGdkDragContext);
virtual void OnDragDropSignal(GdkDragContext *aGdkDragContext,
gint x,
gint y,
guint time);
virtual void OnEnterNotifySignal(GdkEventCrossing * aGdkCrossingEvent);
virtual void OnLeaveNotifySignal(GdkEventCrossing * aGdkCrossingEvent);
virtual void OnButtonPressSignal(GdkEventButton * aGdkButtonEvent);
virtual void OnButtonReleaseSignal(GdkEventButton * aGdkButtonEvent);
virtual void OnFocusInSignal(GdkEventFocus * aGdkFocusEvent);
virtual void OnFocusOutSignal(GdkEventFocus * aGdkFocusEvent);
virtual void OnRealize(GtkWidget *aWidget);
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
// Static method used to trampoline to OnDestroySignal
static gint DestroySignal(GtkWidget * aGtkWidget,
nsWidget* aWidget);
static void SuppressModality(PRBool aSuppress);
public:
PRBool mIMEEnable;
PRUnichar* mIMECompositionUniString;
PRInt32 mIMECompositionUniStringSize;
void SetXICSpotLocation(nsPoint aPoint);
protected:
//////////////////////////////////////////////////////////////////
//
// GTK widget signals
//
//////////////////////////////////////////////////////////////////
static gint MotionNotifySignal(GtkWidget * aWidget,
GdkEventMotion * aGdkMotionEvent,
gpointer aData);
static gint DragMotionSignal(GtkWidget * aWidget,
GdkDragContext *context,
gint x,
gint y,
guint time,
void *data);
static void DragLeaveSignal(GtkWidget * aWidget,
GdkDragContext *aDragContext,
guint time,
void *aData);
static gint DragBeginSignal(GtkWidget * aWidget,
GdkDragContext *context,
gint x,
gint y,
guint time,
void *data);
static gint DragDropSignal(GtkWidget * aWidget,
GdkDragContext *context,
gint x,
gint y,
guint time,
void *data);
static gint EnterNotifySignal(GtkWidget * aWidget,
GdkEventCrossing * aGdkCrossingEvent,
gpointer aData);
static gint LeaveNotifySignal(GtkWidget * aWidget,
GdkEventCrossing * aGdkCrossingEvent,
gpointer aData);
static gint ButtonPressSignal(GtkWidget * aWidget,
GdkEventButton * aGdkButtonEvent,
gpointer aData);
static gint ButtonReleaseSignal(GtkWidget * aWidget,
GdkEventButton * aGdkButtonEvent,
gpointer aData);
static gint RealizeSignal(GtkWidget * aWidget,
gpointer aData);
static gint FocusInSignal(GtkWidget * aWidget,
GdkEventFocus * aGdkFocusEvent,
gpointer aData);
static gint FocusOutSignal(GtkWidget * aWidget,
GdkEventFocus * aGdkFocusEvent,
gpointer aData);
protected:
//////////////////////////////////////////////////////////////////
//
// GTK event support methods
//
//////////////////////////////////////////////////////////////////
void InstallSignal(GtkWidget * aWidget,
gchar * aSignalName,
GtkSignalFunc aSignalFunction);
PRBool DropEvent(GtkWidget * aWidget,
GdkWindow * aEventWindow);
void InitMouseEvent(GdkEventButton * aGdkButtonEvent,
nsMouseEvent & anEvent,
PRUint32 aEventType);
#ifdef DEBUG
nsCAutoString debug_GetName(GtkObject * aGtkWidget);
nsCAutoString debug_GetName(GtkWidget * aGtkWidget);
PRInt32 debug_GetRenderXID(GtkObject * aGtkWidget);
PRInt32 debug_GetRenderXID(GtkWidget * aGtkWidget);
#endif
guint32 mGrabTime;
GtkWidget *mWidget;
// our mozbox for those native widgets
GtkWidget *mMozBox;
nsIWidget *mParent;
// This is the composite update area (union of all the calls to
// Invalidate)
nsIRegion *mUpdateArea;
PRBool mShown;
PRUint32 mPreferredWidth, mPreferredHeight;
PRBool mListenForResizes;
GdkICPrivate *mIC;
GdkICPrivate *GetXIC();
void SetXIC(GdkICPrivate *aIC);
void GetXYFromPosition(unsigned long *aX, unsigned long *aY);
// this is the rollup listener variables
static nsIRollupListener *gRollupListener;
static nsIWidget *gRollupWidget;
static PRBool gRollupConsumeRollupEvent;
private:
PRBool mIsDragDest;
static nsILookAndFeel *sLookAndFeel;
static PRUint32 sWidgetCount;
//
// Keep track of the last widget being "dragged"
//
static nsWidget *sButtonMotionTarget;
static gint sButtonMotionRootX;
static gint sButtonMotionRootY;
static gint sButtonMotionWidgetX;
static gint sButtonMotionWidgetY;
};
#endif /* nsWidget_h__ */

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