Compare commits
2 Commits
SUPERWIN
...
regalloc_c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c43d4984f | ||
|
|
cfe021ff88 |
134
mozilla/ef/Compiler/RegisterAllocator/BitSet.cpp
Normal file
134
mozilla/ef/Compiler/RegisterAllocator/BitSet.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
/* -*- 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.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "BitSet.h"
|
||||
|
||||
// Return the next bit after index set to true or -1 if none.
|
||||
//
|
||||
Int32 BitSet::nextOne(Int32 pos) const
|
||||
{
|
||||
++pos;
|
||||
|
||||
if (pos < 0 || Uint32(pos) >= universeSize)
|
||||
return -1;
|
||||
|
||||
Uint32 offset = getWordOffset(pos);
|
||||
Uint8 index = getBitOffset(pos);
|
||||
Word* ptr = &word[offset];
|
||||
Word currentWord = *ptr++ >> index;
|
||||
|
||||
if (currentWord != Word(0)) {
|
||||
while ((currentWord & Word(1)) == 0) {
|
||||
++index;
|
||||
currentWord >>= 1;
|
||||
}
|
||||
return (offset << nBitsInWordLog2) + index;
|
||||
}
|
||||
|
||||
Word* limit = &word[getSizeInWords(universeSize)];
|
||||
while (ptr < limit) {
|
||||
++offset;
|
||||
currentWord = *ptr++;
|
||||
if (currentWord != Word(0)) {
|
||||
index = 0;
|
||||
while ((currentWord & Word(1)) == 0) {
|
||||
++index;
|
||||
currentWord >>= 1;
|
||||
}
|
||||
return (offset << nBitsInWordLog2) + index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Return the next bit after index set to false or -1 if none.
|
||||
//
|
||||
Int32 BitSet::nextZero(Int32 pos) const
|
||||
{
|
||||
++pos;
|
||||
|
||||
if (pos < 0 || Uint32(pos) >= universeSize)
|
||||
return -1;
|
||||
|
||||
Uint32 offset = getWordOffset(pos);
|
||||
Uint8 index = getBitOffset(pos);
|
||||
Word* ptr = &word[offset];
|
||||
Word currentWord = *ptr++ >> index;
|
||||
|
||||
if (currentWord != Word(~0)) {
|
||||
for (; index < nBitsInWord; ++index) {
|
||||
if ((currentWord & Word(1)) == 0) {
|
||||
Int32 ret = (offset << nBitsInWordLog2) + index;
|
||||
return (Uint32(ret) < universeSize) ? ret : -1;
|
||||
}
|
||||
currentWord >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
Word* limit = &word[getSizeInWords(universeSize)];
|
||||
while (ptr < limit) {
|
||||
++offset;
|
||||
currentWord = *ptr++;
|
||||
if (currentWord != Word(~0)) {
|
||||
for (index = 0; index < nBitsInWord; ++index) {
|
||||
if ((currentWord & Word(1)) == 0) {
|
||||
Int32 ret = (offset << nBitsInWordLog2) + index;
|
||||
return (Uint32(ret) < universeSize) ? ret : -1;
|
||||
}
|
||||
currentWord >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
|
||||
// Print the set.
|
||||
//
|
||||
void BitSet::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("[ "));
|
||||
|
||||
for (Int32 i = firstOne(); i != -1; i = nextOne(i)) {
|
||||
Int32 currentBit = i;
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%d", currentBit));
|
||||
|
||||
Int32 nextBit = nextOne(currentBit);
|
||||
if (nextBit != currentBit + 1) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" "));
|
||||
continue;
|
||||
}
|
||||
|
||||
while ((nextBit != -1) && (nextBit == (currentBit + 1))) {
|
||||
currentBit = nextBit;
|
||||
nextBit = nextOne(nextBit);
|
||||
}
|
||||
|
||||
if (currentBit > (i+1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("-%d ", currentBit));
|
||||
else
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" %d ", currentBit));
|
||||
|
||||
i = currentBit;
|
||||
}
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("]\n"));
|
||||
}
|
||||
|
||||
#endif // DEBUG_LOG
|
||||
195
mozilla/ef/Compiler/RegisterAllocator/BitSet.h
Normal file
195
mozilla/ef/Compiler/RegisterAllocator/BitSet.h
Normal file
@@ -0,0 +1,195 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _BITSET_H_
|
||||
#define _BITSET_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "LogModule.h"
|
||||
#include "Pool.h"
|
||||
#include <string.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// BitSet -
|
||||
|
||||
class BitSet
|
||||
{
|
||||
private:
|
||||
|
||||
#if (PR_BITS_PER_WORD == 64)
|
||||
typedef Uint64 Word;
|
||||
#elif (PR_BITS_PER_WORD == 32)
|
||||
typedef Uint32 Word;
|
||||
#endif
|
||||
|
||||
static const nBitsInWord = PR_BITS_PER_WORD;
|
||||
static const nBytesInWord = PR_BYTES_PER_WORD;
|
||||
static const nBitsInWordLog2 = PR_BITS_PER_WORD_LOG2;
|
||||
static const nBytesInWordLog2 = PR_BYTES_PER_WORD_LOG2;
|
||||
|
||||
// Return the number of Word need to store the universe.
|
||||
static Uint32 getSizeInWords(Uint32 sizeOfUniverse) {return (sizeOfUniverse + (nBitsInWord - 1)) >> nBitsInWordLog2;}
|
||||
// Return the given element offset in its containing Word.
|
||||
static Uint32 getBitOffset(Uint32 element) {return element & (nBitsInWord - 1);}
|
||||
// Return the Word offset for the given element int the universe.
|
||||
static Uint32 getWordOffset(Uint32 element) {return element >> nBitsInWordLog2;}
|
||||
// Return the mask for the given bit index.
|
||||
static Word getMask(Uint8 index) {return Word(1) << index;}
|
||||
|
||||
private:
|
||||
|
||||
Uint32 universeSize; // Size of the universe
|
||||
Word* word; // universe memory.
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
BitSet(const BitSet&);
|
||||
|
||||
// Check if the given set's universe is of the same size than this universe.
|
||||
void checkUniverseCompatibility(const BitSet& set) const {assert(set.universeSize == universeSize);}
|
||||
// Check if pos is valid for this set's universe.
|
||||
void checkMember(Int32 pos) const {assert(pos >=0 && Uint32(pos) < universeSize);}
|
||||
|
||||
public:
|
||||
|
||||
// Create a bitset of universeSize bits.
|
||||
BitSet(Pool& pool, Uint32 universeSize) : universeSize(universeSize) {word = new(pool) Word[getSizeInWords(universeSize)]; clear();}
|
||||
|
||||
// Return the size of this bitset.
|
||||
Uint32 getSize() const {return universeSize;}
|
||||
|
||||
// Clear the bitset.
|
||||
void clear() {memset(word, 0x00, getSizeInWords(universeSize) << nBytesInWordLog2);}
|
||||
// Clear the bit at index.
|
||||
void clear(Uint32 index) {checkMember(index); word[getWordOffset(index)] &= ~getMask(index);}
|
||||
// Set the bitset.
|
||||
void set() {memset(word, 0xFF, getSizeInWords(universeSize) << nBytesInWordLog2);}
|
||||
// Set the bit at index.
|
||||
void set(Uint32 index) {checkMember(index); word[getWordOffset(index)] |= getMask(index);}
|
||||
// Return true if the bit at index is set.
|
||||
bool test(Uint32 index) const {checkMember(index); return (word[getWordOffset(index)] & getMask(index)) != 0;}
|
||||
// Union with the given bitset.
|
||||
inline void or(const BitSet& set);
|
||||
// Intersection with the given bitset.
|
||||
inline void and(const BitSet& set);
|
||||
// Difference with the given bitset.
|
||||
inline void difference(const BitSet& set);
|
||||
// Copy set.
|
||||
inline BitSet& operator = (const BitSet& set);
|
||||
// Return true if the bitset are identical.
|
||||
friend bool operator == (const BitSet& set1, const BitSet& set2);
|
||||
// Return true if the bitset are different.
|
||||
friend bool operator != (const BitSet& set1, const BitSet& set2);
|
||||
|
||||
// Logical operators.
|
||||
BitSet& operator |= (const BitSet& set) {or(set); return *this;}
|
||||
BitSet& operator &= (const BitSet& set) {and(set); return *this;}
|
||||
BitSet& operator -= (const BitSet& set) {difference(set); return *this;}
|
||||
|
||||
// Return the first bit at set to true or -1 if none.
|
||||
Int32 firstOne() const {return nextOne(-1);}
|
||||
// Return the next bit after index set to true or -1 if none.
|
||||
Int32 nextOne(Int32 pos) const;
|
||||
// Return the first bit at set to false or -1 if none.
|
||||
Int32 firstZero() const {return nextZero(-1);}
|
||||
// Return the next bit after index set to false or -1 if none.
|
||||
Int32 nextZero(Int32 pos) const;
|
||||
|
||||
// Iterator to conform with the set API.
|
||||
typedef Int32 iterator;
|
||||
// Return true if the walk is ordered.
|
||||
static bool isOrdered() {return true;}
|
||||
// Return the iterator for the first element of this set.
|
||||
iterator begin() const {return firstOne();}
|
||||
// Return the next iterator.
|
||||
iterator advance(iterator pos) const {return nextOne(pos);}
|
||||
// Return true if the iterator is at the end of the set.
|
||||
bool done(iterator pos) const {return pos == -1;}
|
||||
// Return the element corresponding to the given iterator.
|
||||
Uint32 get(iterator pos) const {return pos;}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the set.
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
// Union with the given bitset.
|
||||
//
|
||||
inline void BitSet::or(const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Word* src = set.word;
|
||||
Word* dst = word;
|
||||
Word* limit = &src[getSizeInWords(universeSize)];
|
||||
|
||||
while (src < limit)
|
||||
*dst++ |= *src++;
|
||||
}
|
||||
|
||||
// Intersection with the given bitset.
|
||||
//
|
||||
inline void BitSet::and(const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Word* src = set.word;
|
||||
Word* dst = word;
|
||||
Word* limit = &src[getSizeInWords(universeSize)];
|
||||
|
||||
while (src < limit)
|
||||
*dst++ &= *src++;
|
||||
}
|
||||
|
||||
// Difference with the given bitset.
|
||||
//
|
||||
inline void BitSet::difference(const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Word* src = set.word;
|
||||
Word* dst = word;
|
||||
Word* limit = &src[getSizeInWords(universeSize)];
|
||||
|
||||
while (src < limit)
|
||||
*dst++ &= ~*src++;
|
||||
}
|
||||
|
||||
// Copy the given set into this set.
|
||||
//
|
||||
inline BitSet& BitSet::operator = (const BitSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
if (this != &set)
|
||||
memcpy(word, set.word, getSizeInWords(universeSize) << nBytesInWordLog2);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Return true if the given set is identical to this set.
|
||||
inline bool operator == (const BitSet& set1, const BitSet& set2)
|
||||
{
|
||||
set1.checkUniverseCompatibility(set2);
|
||||
|
||||
if (&set1 == &set2)
|
||||
return true;
|
||||
|
||||
return memcmp(set1.word, set2.word, BitSet::getSizeInWords(set1.universeSize) << BitSet::nBytesInWordLog2) == 0;
|
||||
}
|
||||
|
||||
inline bool operator != (const BitSet& set1, const BitSet& set2) {return !(set1 == set2);}
|
||||
|
||||
#endif // _BITSET_H
|
||||
159
mozilla/ef/Compiler/RegisterAllocator/Coalescing.h
Normal file
159
mozilla/ef/Compiler/RegisterAllocator/Coalescing.h
Normal file
@@ -0,0 +1,159 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _COALESCING_H_
|
||||
#define _COALESCING_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "InterferenceGraph.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "SparseSet.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
|
||||
#if 1
|
||||
// Performing an ultra conservative coalescing meens that when we look at
|
||||
// candidates (source,destination) for coalescing we need to make sure
|
||||
// that the combined interference of the source and destination register
|
||||
// will not exceed the total number of register available for the register
|
||||
// class.
|
||||
#define ULTRA_CONSERVATIVE_COALESCING
|
||||
#else
|
||||
// If we are not doing an ultra conservative coalescing we have to make sure
|
||||
// that the total number of neighbor whose degree is greater than the total
|
||||
// number of register is not greater than the total number of register.
|
||||
#undef ULTRA_CONSERVATIVE_COALESCING
|
||||
#endif
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct Coalescing
|
||||
{
|
||||
static bool coalesce(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Coalescing<RegisterPressure>::coalesce(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
|
||||
// Initialize the lookup table
|
||||
//
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* newRange = new RegisterName[2 * rangeCount];
|
||||
RegisterName* coalescedRange = &newRange[rangeCount];
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
init(coalescedRange, rangeCount);
|
||||
|
||||
SparseSet interferences(pool, rangeCount);
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
bool removedInstructions = false;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.lndList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
|
||||
// Walk the nodes in the loop nesting depth list.
|
||||
for (Int32 n = nNodes - 1; n >= 0; n--) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
|
||||
InstructionList::iterator it = instructions.begin();
|
||||
while (!instructions.done(it)) {
|
||||
Instruction& instruction = instructions.get(it);
|
||||
it = instructions.advance(it);
|
||||
|
||||
if ((instruction.getFlags() & ifCopy) != 0) {
|
||||
assert(instruction.getInstructionUseBegin() != instruction.getInstructionUseEnd() && instruction.getInstructionUseBegin()[0].isRegister());
|
||||
assert(instruction.getInstructionDefineBegin() != instruction.getInstructionDefineEnd() && instruction.getInstructionDefineBegin()[0].isRegister());
|
||||
|
||||
RegisterName source = findRoot(name2range[instruction.getInstructionUseBegin()[0].getRegisterName()], coalescedRange);
|
||||
RegisterName destination = findRoot(name2range[instruction.getInstructionDefineBegin()[0].getRegisterName()], coalescedRange);
|
||||
|
||||
if (source == destination) {
|
||||
instruction.remove();
|
||||
} else if (!iGraph.interfere(source, destination)) {
|
||||
InterferenceVector* sourceVector = iGraph.getInterferenceVector(source);
|
||||
InterferenceVector* destinationVector = iGraph.getInterferenceVector(destination);
|
||||
|
||||
#ifdef ULTRA_CONSERVATIVE_COALESCING
|
||||
interferences.clear();
|
||||
|
||||
InterferenceVector* vector;
|
||||
for (vector = sourceVector; vector != NULL; vector = vector->next) {
|
||||
RegisterName* neighbors = vector->neighbors;
|
||||
for (Uint32 i = 0; i < vector->count; i++)
|
||||
interferences.set(findRoot(neighbors[i], coalescedRange));
|
||||
}
|
||||
for (vector = destinationVector; vector != NULL; vector = vector->next) {
|
||||
RegisterName* neighbors = vector->neighbors;
|
||||
for (Uint32 i = 0; i < vector->count; i++)
|
||||
interferences.set(findRoot(neighbors[i], coalescedRange));
|
||||
}
|
||||
|
||||
Uint32 count = interferences.getSize();
|
||||
#else // ULTRA_CONSERVATIVE_COALESCING
|
||||
trespass("not implemented");
|
||||
Uint32 count = 0;
|
||||
#endif // ULTRA_CONSERVATIVE_COALESCING
|
||||
|
||||
if (count < 6 /* FIX: should get the number from the class */) {
|
||||
// Update the interferences vector.
|
||||
if (sourceVector == NULL) {
|
||||
iGraph.setInterferenceVector(source, destinationVector);
|
||||
sourceVector = destinationVector;
|
||||
} else if (destinationVector == NULL)
|
||||
iGraph.setInterferenceVector(destination, sourceVector);
|
||||
else {
|
||||
InterferenceVector* last = NULL;
|
||||
for (InterferenceVector* v = sourceVector; v != NULL; v = v->next)
|
||||
last = v;
|
||||
assert(last);
|
||||
last->next = destinationVector;
|
||||
iGraph.setInterferenceVector(destination, sourceVector);
|
||||
}
|
||||
// Update the interference matrix.
|
||||
for (InterferenceVector* v = sourceVector; v != NULL; v = v->next) {
|
||||
RegisterName* neighbors = v->neighbors;
|
||||
for (Uint32 i = 0; i < v->count; i++) {
|
||||
RegisterName neighbor = findRoot(neighbors[i], coalescedRange);
|
||||
iGraph.setInterference(neighbor, source);
|
||||
iGraph.setInterference(neighbor, destination);
|
||||
}
|
||||
}
|
||||
|
||||
instruction.remove();
|
||||
coalescedRange[source] = destination;
|
||||
removedInstructions = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerAllocator.rangeCount = compress(registerAllocator.name2range, coalescedRange, registerAllocator.nameCount, rangeCount);
|
||||
delete newRange;
|
||||
|
||||
return removedInstructions;
|
||||
}
|
||||
|
||||
#endif // _COALESCING_H_
|
||||
283
mozilla/ef/Compiler/RegisterAllocator/Coloring.cpp
Normal file
283
mozilla/ef/Compiler/RegisterAllocator/Coloring.cpp
Normal file
@@ -0,0 +1,283 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef NEW_LAURENTM_CODE
|
||||
|
||||
#include "Coloring.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "FastBitSet.h"
|
||||
#include "FastBitMatrix.h"
|
||||
#include "CpuInfo.h"
|
||||
|
||||
bool Coloring::
|
||||
assignRegisters(FastBitMatrix& interferenceMatrix)
|
||||
{
|
||||
PRUint32 *stackPtr = new(pool) PRUint32[vRegManager.count()];
|
||||
|
||||
return select(interferenceMatrix, stackPtr, simplify(interferenceMatrix, stackPtr));
|
||||
}
|
||||
|
||||
PRInt32 Coloring::
|
||||
getLowestSpillCostRegister(FastBitSet& bitset)
|
||||
{
|
||||
PRInt32 lowest = bitset.firstOne();
|
||||
if (lowest != -1)
|
||||
{
|
||||
Flt32 cost = vRegManager.getVirtualRegister(lowest).spillInfo.spillCost;
|
||||
for (PRInt32 r = bitset.nextOne(lowest); r != -1; r = bitset.nextOne(r))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
|
||||
if (!vReg.spillInfo.infiniteSpillCost && (vReg.spillInfo.spillCost < cost))
|
||||
{
|
||||
cost = vReg.spillInfo.spillCost;
|
||||
lowest = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
return lowest;
|
||||
}
|
||||
|
||||
PRUint32* Coloring::
|
||||
simplify(FastBitMatrix interferenceMatrix, PRUint32* stackPtr)
|
||||
{
|
||||
// first we construct the sets low and high. low contains all nodes of degree
|
||||
// inferior to the number of register available on the processor. All the
|
||||
// nodes with an high degree and a finite spill cost are placed in high.
|
||||
// Nodes of high degree and infinite spill cost are not included in either sets.
|
||||
|
||||
PRUint32 nRegisters = vRegManager.count();
|
||||
FastBitSet low(pool, nRegisters);
|
||||
FastBitSet high(pool, nRegisters);
|
||||
FastBitSet stack(pool, nRegisters);
|
||||
|
||||
for (VirtualRegisterManager::iterator i = vRegManager.begin(); !vRegManager.done(i); i = vRegManager.advance(i))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(i);
|
||||
|
||||
if (vReg.getClass() == vrcStackSlot)
|
||||
{
|
||||
stack.set(i);
|
||||
vReg.colorRegister(nRegisters);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vReg.colorInfo.interferenceDegree < NUMBER_OF_REGISTERS)
|
||||
low.set(i);
|
||||
else // if (!vReg.spillInfo.infiniteSpillCost)
|
||||
high.set(i);
|
||||
|
||||
// Set coloring info.
|
||||
vReg.spillInfo.willSpill = false;
|
||||
|
||||
switch(vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
vReg.colorRegister(LAST_GREGISTER + 1);
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
vReg.colorRegister(LAST_FPREGISTER + 1);
|
||||
break;
|
||||
default:
|
||||
PR_ASSERT(false); // Cannot happen.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// push the stack registers
|
||||
PRInt32 j;
|
||||
for (j = stack.firstOne(); j != -1; j = stack.nextOne(j))
|
||||
*stackPtr++ = j;
|
||||
|
||||
// simplify
|
||||
while (true)
|
||||
{
|
||||
PRInt32 r;
|
||||
while ((r = getLowestSpillCostRegister(low)) != -1)
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
|
||||
|
||||
/* update low and high */
|
||||
FastBitSet inter(interferenceMatrix.getRow(r), nRegisters);
|
||||
for (j = inter.firstOne(); j != -1; j = inter.nextOne(j))
|
||||
{
|
||||
VirtualRegister& neighbor = vRegManager.getVirtualRegister(j);
|
||||
// if the new interference degree of one of his neighbor becomes
|
||||
// NUMBER_OF_REGISTERS - 1 then it is added to the set 'low'.
|
||||
|
||||
PRUint32 maxInterference = 0;
|
||||
switch (neighbor.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
maxInterference = NUMBER_OF_GREGISTERS;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
maxInterference = NUMBER_OF_FPREGISTERS;
|
||||
break;
|
||||
default:
|
||||
PR_ASSERT(false);
|
||||
}
|
||||
if ((vRegManager.getVirtualRegister(j).colorInfo.interferenceDegree-- == maxInterference))
|
||||
{
|
||||
high.clear(j);
|
||||
low.set(j);
|
||||
}
|
||||
vReg.colorInfo.interferenceDegree--;
|
||||
interferenceMatrix.clear(r, j);
|
||||
interferenceMatrix.clear(j, r);
|
||||
}
|
||||
low.clear(r);
|
||||
|
||||
// Push this register.
|
||||
*stackPtr++ = r;
|
||||
}
|
||||
if ((r = getLowestSpillCostRegister(high)) != -1)
|
||||
{
|
||||
high.clear(r);
|
||||
low.set(r);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return stackPtr;
|
||||
}
|
||||
|
||||
bool Coloring::
|
||||
select(FastBitMatrix& interferenceMatrix, PRUint32* stackBase, PRUint32* stackPtr)
|
||||
{
|
||||
PRUint32 nRegisters = vRegManager.count();
|
||||
FastBitSet usedRegisters(NUMBER_OF_REGISTERS + 1); // usedRegisters if used for both GR & FPR.
|
||||
FastBitSet preColoredRegisters(NUMBER_OF_REGISTERS + 1);
|
||||
FastBitSet usedStack(nRegisters + 1);
|
||||
bool success = true;
|
||||
Int32 lastUsedSSR = -1;
|
||||
|
||||
// select
|
||||
while (stackPtr != stackBase)
|
||||
{
|
||||
// Pop one register.
|
||||
PRUint32 r = *--stackPtr;
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(r);
|
||||
|
||||
FastBitSet neighbors(interferenceMatrix.getRow(r), nRegisters);
|
||||
|
||||
if (vReg.getClass() == vrcStackSlot)
|
||||
// Stack slots coloring.
|
||||
{
|
||||
usedStack.clear();
|
||||
|
||||
for (PRInt32 i = neighbors.firstOne(); i != -1; i = neighbors.nextOne(i))
|
||||
usedStack.set(vRegManager.getVirtualRegister(i).getColor());
|
||||
|
||||
Int32 color = usedStack.firstZero();
|
||||
vReg.colorRegister(color);
|
||||
if (color > lastUsedSSR)
|
||||
lastUsedSSR = color;
|
||||
}
|
||||
else
|
||||
// Integer & Floating point register coloring.
|
||||
{
|
||||
usedRegisters.clear();
|
||||
preColoredRegisters.clear();
|
||||
|
||||
for (PRInt32 i = neighbors.firstOne(); i != -1; i = neighbors.nextOne(i))
|
||||
{
|
||||
VirtualRegister& nvReg = vRegManager.getVirtualRegister(i);
|
||||
usedRegisters.set(nvReg.getColor());
|
||||
if (nvReg.isPreColored())
|
||||
preColoredRegisters.set(nvReg.getPreColor());
|
||||
}
|
||||
if (vReg.hasSpecialInterference)
|
||||
usedRegisters |= vReg.specialInterference;
|
||||
|
||||
PRInt8 c = -1;
|
||||
PRInt8 maxColor = 0;
|
||||
PRInt8 firstColor = 0;
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
firstColor = FIRST_GREGISTER;
|
||||
maxColor = LAST_GREGISTER;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
firstColor = FIRST_FPREGISTER;
|
||||
maxColor = LAST_FPREGISTER;
|
||||
break;
|
||||
default:
|
||||
PR_ASSERT(false);
|
||||
}
|
||||
|
||||
if (vReg.isPreColored())
|
||||
{
|
||||
c = vReg.getPreColor();
|
||||
if (usedRegisters.test(c))
|
||||
c = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = usedRegisters.nextZero(firstColor - 1); (c >= 0) && (c <= maxColor) && (preColoredRegisters.test(c));
|
||||
c = usedRegisters.nextZero(c)) {}
|
||||
}
|
||||
|
||||
if ((c >= 0) && (c <= maxColor))
|
||||
{
|
||||
vReg.colorRegister(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
VirtualRegister& stackRegister = vRegManager.newVirtualRegister(vrcStackSlot);
|
||||
vReg.equivalentRegister[vrcStackSlot] = &stackRegister;
|
||||
vReg.spillInfo.willSpill = true;
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (success)
|
||||
{
|
||||
for (VirtualRegisterManager::iterator i = vRegManager.begin(); !vRegManager.done(i); i = vRegManager.advance(i))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(i);
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
if (vReg.getColor() > LAST_GREGISTER)
|
||||
PR_ASSERT(false);
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
#if NUMBER_OF_FPREGISTERS != 0
|
||||
if (vReg.getColor() > LAST_FPREGISTER)
|
||||
PR_ASSERT(false);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vRegManager.nUsedStackSlots = lastUsedSSR + 1;
|
||||
return success;
|
||||
}
|
||||
#endif // NEW_LAURENTM_CODE
|
||||
284
mozilla/ef/Compiler/RegisterAllocator/Coloring.h
Normal file
284
mozilla/ef/Compiler/RegisterAllocator/Coloring.h
Normal file
@@ -0,0 +1,284 @@
|
||||
/* -*- 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.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "InterferenceGraph.h"
|
||||
#include "SparseSet.h"
|
||||
#include "Spilling.h"
|
||||
#include "Splits.h"
|
||||
|
||||
UT_EXTERN_LOG_MODULE(RegAlloc);
|
||||
|
||||
template <class RegisterPressure>
|
||||
class Coloring
|
||||
{
|
||||
private:
|
||||
static RegisterName* simplify(RegisterAllocator& registerAllocator, RegisterName* coloringStack);
|
||||
static bool select(RegisterAllocator& registerAllocator, RegisterName* coloringStack, RegisterName* coloringStackPtr);
|
||||
|
||||
public:
|
||||
static bool color(RegisterAllocator& registerAllocator);
|
||||
static void finalColoring(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Coloring<RegisterPressure>::finalColoring(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
RegisterName* color = registerAllocator.color;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
usePtr->setRegisterName(color[name2range[usePtr->getRegisterName()]]);
|
||||
#ifdef DEBUG
|
||||
RegisterID rid = usePtr->getRegisterID();
|
||||
setColoredRegister(rid);
|
||||
usePtr->setRegisterID(rid);
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
definePtr->setRegisterName(color[name2range[definePtr->getRegisterName()]]);
|
||||
#ifdef DEBUG
|
||||
RegisterID rid = definePtr->getRegisterID();
|
||||
setColoredRegister(rid);
|
||||
definePtr->setRegisterID(rid);
|
||||
#endif // DEBUG
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Coloring<RegisterPressure>::select(RegisterAllocator& registerAllocator, RegisterName* coloringStack, RegisterName* coloringStackPtr)
|
||||
{
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* color = new RegisterName[rangeCount];
|
||||
registerAllocator.color = color;
|
||||
|
||||
for (Uint32 r = 1; r < rangeCount; r++)
|
||||
color[r] = RegisterName(6); // FIX;
|
||||
|
||||
// Color the preColored registers.
|
||||
//
|
||||
VirtualRegisterManager& vrManager = registerAllocator.vrManager;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
PreColoredRegister* machineEnd = vrManager.getMachineRegistersEnd();
|
||||
for (PreColoredRegister* machinePtr = vrManager.getMachineRegistersBegin(); machinePtr < machineEnd; machinePtr++)
|
||||
if (machinePtr->id != invalidID) {
|
||||
color[name2range[getName(machinePtr->id)]] = machinePtr->color;
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\twill preColor range %d as %d\n", name2range[getName(machinePtr->id)], machinePtr->color));
|
||||
}
|
||||
|
||||
SpillCost* cost = registerAllocator.spillCost;
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet& spill = *new(pool) SparseSet(pool, rangeCount);
|
||||
registerAllocator.willSpill = &spill;
|
||||
SparseSet neighborColors(pool, 6); // FIX
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
|
||||
bool coloringFailed = false;
|
||||
while (coloringStackPtr > coloringStack) {
|
||||
RegisterName range = *--coloringStackPtr;
|
||||
|
||||
if (!cost[range].infinite && cost[range].cost < 0) {
|
||||
coloringFailed = true;
|
||||
spill.set(range);
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tfailed to color %d, will spill.\n", range));
|
||||
} else {
|
||||
neighborColors.clear();
|
||||
|
||||
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
|
||||
for (Int32 i = vector->count - 1; i >= 0; --i) {
|
||||
RegisterName neighborColor = color[vector->neighbors[i]];
|
||||
if (neighborColor < 6) // FIX
|
||||
neighborColors.set(neighborColor);
|
||||
}
|
||||
|
||||
if (neighborColors.getSize() == 6) { // FIX
|
||||
coloringFailed = true;
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tfailed to color %d, ", range));
|
||||
|
||||
if (!Splits<RegisterPressure>::findSplit(registerAllocator, color, range)) {
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("will spill.\n"));
|
||||
spill.set(range);
|
||||
} else
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("will split.\n"));
|
||||
} else {
|
||||
for (Uint32 i = 0; i < 6; i++) // FIX
|
||||
if (!neighborColors.test(i)) {
|
||||
fprintf(stdout, "\twill color %d as %d\n", range, i);
|
||||
color[range] = RegisterName(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
if (coloringFailed) {
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring failed:\n"));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\twill spill: "));
|
||||
spill.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
} else {
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring succeeded:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++)
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\trange %d colored as %d\n", i, color[i]));
|
||||
}
|
||||
#endif
|
||||
|
||||
return !coloringFailed;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
RegisterName* Coloring<RegisterPressure>::simplify(RegisterAllocator& registerAllocator, RegisterName* coloringStack)
|
||||
{
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
SpillCost* spillCost = registerAllocator.spillCost;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
|
||||
Uint32* degree = new Uint32[rangeCount];
|
||||
for (RegisterName i = RegisterName(1); i < rangeCount; i = RegisterName(i + 1)) {
|
||||
InterferenceVector* vector = iGraph.getInterferenceVector(i);
|
||||
degree[i] = (vector != NULL) ? vector->count : 0;
|
||||
}
|
||||
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet low(pool, rangeCount);
|
||||
SparseSet high(pool, rangeCount);
|
||||
SparseSet highInfinite(pool, rangeCount);
|
||||
SparseSet preColored(pool, rangeCount);
|
||||
|
||||
// Get the precolored registers.
|
||||
//
|
||||
VirtualRegisterManager& vrManager = registerAllocator.vrManager;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
PreColoredRegister* machineEnd = vrManager.getMachineRegistersEnd();
|
||||
for (PreColoredRegister* machinePtr = vrManager.getMachineRegistersBegin(); machinePtr < machineEnd; machinePtr++)
|
||||
if (machinePtr->id != invalidID)
|
||||
preColored.set(name2range[getName(machinePtr->id)]);
|
||||
|
||||
// Insert the live ranges in the sets.
|
||||
//
|
||||
for (Uint32 range = 1; range < rangeCount; range++)
|
||||
if (!preColored.test(range))
|
||||
if (degree[range] < 6) // FIX
|
||||
low.set(range);
|
||||
else if (!spillCost[range].infinite)
|
||||
high.set(range);
|
||||
else
|
||||
highInfinite.set(range);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring sets:\n\tlow = "));
|
||||
low.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\thigh = "));
|
||||
high.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\thighInfinite = "));
|
||||
highInfinite.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tpreColored = "));
|
||||
preColored.printPretty(UT_LOG_MODULE(RegAlloc));
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
RegisterName* coloringStackPtr = coloringStack;
|
||||
|
||||
while (low.getSize() != 0 || high.getSize() != 0) {
|
||||
while (low.getSize() != 0) {
|
||||
RegisterName range = RegisterName(low.getOne());
|
||||
low.clear(range);
|
||||
*coloringStackPtr++ = range;
|
||||
|
||||
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
|
||||
for (Int32 i = (vector->count - 1); i >= 0; --i) {
|
||||
RegisterName neighbor = vector->neighbors[i];
|
||||
degree[neighbor]--;
|
||||
|
||||
if (degree[neighbor] < 6) // FIX
|
||||
if (high.test(neighbor)) {
|
||||
high.clear(neighbor);
|
||||
low.set(neighbor);
|
||||
} else if (highInfinite.test(neighbor)) {
|
||||
highInfinite.clear(neighbor);
|
||||
low.set(neighbor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (high.getSize() != 0) {
|
||||
RegisterName best = RegisterName(high.getOne());
|
||||
double bestCost = spillCost[best].cost;
|
||||
double bestDegree = degree[best];
|
||||
|
||||
// Choose the next best candidate.
|
||||
//
|
||||
for (SparseSet::iterator i = high.begin(); !high.done(i); i = high.advance(i)) {
|
||||
RegisterName range = RegisterName(high.get(i));
|
||||
double thisCost = spillCost[range].cost;
|
||||
double thisDegree = degree[range];
|
||||
|
||||
if (thisCost * bestDegree < bestCost * thisDegree) {
|
||||
best = range;
|
||||
bestCost = thisCost;
|
||||
bestDegree = thisDegree;
|
||||
}
|
||||
}
|
||||
|
||||
high.clear(best);
|
||||
low.set(best);
|
||||
}
|
||||
}
|
||||
assert(highInfinite.getSize() == 0);
|
||||
|
||||
delete degree;
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("Coloring stack:\n\t"));
|
||||
for (RegisterName* sp = coloringStack; sp < coloringStackPtr; ++sp)
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("%d ", *sp));
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\n"));
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
return coloringStackPtr;
|
||||
}
|
||||
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Coloring<RegisterPressure>::color(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
RegisterName* coloringStack = new RegisterName[registerAllocator.rangeCount];
|
||||
return select(registerAllocator, coloringStack, simplify(registerAllocator, coloringStack));
|
||||
}
|
||||
212
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.cpp
Normal file
212
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.cpp
Normal file
@@ -0,0 +1,212 @@
|
||||
/* -*- 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.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
|
||||
#include "DominatorGraph.h"
|
||||
|
||||
DominatorGraph::DominatorGraph(ControlGraph& controlGraph) : controlGraph(controlGraph)
|
||||
{
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
GtoV = new Uint32[nNodes + 1];
|
||||
VtoG = new Uint32[nNodes + 1];
|
||||
|
||||
Uint32 v = 1;
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
VtoG[v] = n;
|
||||
GtoV[n] = v++;
|
||||
}
|
||||
|
||||
// Initialize all the 1-based arrays.
|
||||
//
|
||||
parent = new Uint32[v];
|
||||
semi = new Uint32[v];
|
||||
vertex = new Uint32[v];
|
||||
label = new Uint32[v];
|
||||
size = new Uint32[v];
|
||||
ancestor = new Uint32[v];
|
||||
child = new Uint32[v];
|
||||
dom = new Uint32[v];
|
||||
bucket = new DGLinkedList*[v];
|
||||
|
||||
memset(semi, '\0', v * sizeof(Uint32));
|
||||
memset(bucket, '\0', v * sizeof(DGLinkedList*));
|
||||
|
||||
vCount = v;
|
||||
|
||||
build();
|
||||
|
||||
delete parent;
|
||||
delete semi;
|
||||
delete vertex;
|
||||
delete label;
|
||||
delete size;
|
||||
delete ancestor;
|
||||
delete child;
|
||||
delete dom;
|
||||
delete bucket;
|
||||
}
|
||||
|
||||
Uint32 DominatorGraph::DFS(Uint32 vx, Uint32 n)
|
||||
{
|
||||
semi[vx] = ++n;
|
||||
vertex[n] = label[vx] = vx;
|
||||
ancestor[vx] = child[vx] = 0;
|
||||
size[vx] = 1;
|
||||
|
||||
|
||||
ControlNode& node = *controlGraph.dfsList[VtoG[vx]];
|
||||
ControlEdge* successorEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorPtr = node.getSuccessorsBegin(); successorPtr < successorEnd; successorPtr++) {
|
||||
Uint32 w = GtoV[successorPtr->getTarget().dfsNum];
|
||||
if (semi[w] == 0) {
|
||||
parent[w] = vx;
|
||||
n = DFS(w, n);
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void DominatorGraph::LINK(Uint32 vx, Uint32 w)
|
||||
{
|
||||
Uint32 s = w;
|
||||
|
||||
while (semi[label[w]] < semi[label[child[s]]]) {
|
||||
if (size[s] + size[child[child[s]]] >= (size[child[s]] << 1)) {
|
||||
ancestor[child[s]] = s;
|
||||
child[s] = child[child[s]];
|
||||
} else {
|
||||
size[child[s]] = size[s];
|
||||
s = ancestor[s] = child[s];
|
||||
}
|
||||
}
|
||||
label[s] = label[w];
|
||||
size[vx] += size[w];
|
||||
if(size[vx] < (size[w] << 1)) {
|
||||
Uint32 t = s;
|
||||
s = child[vx];
|
||||
child[vx] = t;
|
||||
}
|
||||
while( s != 0 ) {
|
||||
ancestor[s] = vx;
|
||||
s = child[s];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DominatorGraph::COMPRESS(Uint32 vx)
|
||||
{
|
||||
if(ancestor[ancestor[vx]] != 0) {
|
||||
COMPRESS(ancestor[vx]);
|
||||
if(semi[label[ancestor[vx]]] < semi[label[vx]])
|
||||
label[vx] = label[ancestor[vx]];
|
||||
ancestor[vx] = ancestor[ancestor[vx]];
|
||||
}
|
||||
}
|
||||
|
||||
Uint32 DominatorGraph::EVAL(Uint32 vx)
|
||||
{
|
||||
if(ancestor[vx] == 0)
|
||||
return label[vx];
|
||||
COMPRESS(vx);
|
||||
return (semi[label[ancestor[vx]]] >= semi[label[vx]]) ? label[vx] : label[ancestor[vx]];
|
||||
}
|
||||
|
||||
void DominatorGraph::build()
|
||||
{
|
||||
Uint32 n = DFS(GtoV[0], 0);
|
||||
size[0] = label[0] = semi[0];
|
||||
|
||||
for (Uint32 i = n; i >= 2; i--) {
|
||||
Uint32 w = vertex[i];
|
||||
|
||||
ControlNode& node = *controlGraph.dfsList[VtoG[w]];
|
||||
const DoublyLinkedList<ControlEdge>& predecessors = node.getPredecessors();
|
||||
for (DoublyLinkedList<ControlEdge>::iterator p = predecessors.begin(); !predecessors.done(p); p = predecessors.advance(p)) {
|
||||
Uint32 vx = GtoV[predecessors.get(p).getSource().dfsNum];
|
||||
Uint32 u = EVAL(vx);
|
||||
|
||||
if(semi[u] < semi[w])
|
||||
semi[w] = semi[u];
|
||||
}
|
||||
|
||||
DGLinkedList* elem = new DGLinkedList();
|
||||
elem->next = bucket[vertex[semi[w]]];
|
||||
elem->index = w;
|
||||
bucket[vertex[semi[w]]] = elem;
|
||||
|
||||
LINK(parent[w], w);
|
||||
|
||||
elem = bucket[parent[w]];
|
||||
while(elem != NULL) {
|
||||
Uint32 vx = elem->index;
|
||||
Uint32 u = EVAL(vx);
|
||||
dom[vx] = (semi[u] < semi[vx]) ? u : parent[w];
|
||||
elem = elem->next;
|
||||
}
|
||||
}
|
||||
|
||||
memset(size, '\0', n * sizeof(Uint32));
|
||||
Pool& pool = controlGraph.pool;
|
||||
nodes = new(pool) DGNode[n];
|
||||
|
||||
for(Uint32 j = 2; j <= n; j++) {
|
||||
Uint32 w = vertex[j];
|
||||
Uint32 d = dom[w];
|
||||
if(d != vertex[semi[w]]) {
|
||||
d = dom[d];
|
||||
dom[w] = d;
|
||||
}
|
||||
size[d]++;
|
||||
}
|
||||
dom[GtoV[0]] = 0;
|
||||
|
||||
for (Uint32 k = 1; k <= n; k++) {
|
||||
DGNode& node = nodes[VtoG[k]];
|
||||
Uint32 count = size[k];
|
||||
node.successorsEnd = node.successorsBegin = (count) ? new(pool) Uint32[count] : (Uint32*) 0;
|
||||
}
|
||||
|
||||
for (Uint32 l = 2; l <= n; l++)
|
||||
*(nodes[VtoG[dom[l]]].successorsEnd)++ = VtoG[l];
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
void DominatorGraph::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Dominator Graph:\n"));
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
for (Uint32 i = 0; i < nNodes; i++) {
|
||||
DGNode& node = nodes[i];
|
||||
if (node.successorsBegin != node.successorsEnd) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tN%d dominates ", i));
|
||||
for (Uint32* successorsPtr = node.successorsBegin; successorsPtr < node.successorsEnd; successorsPtr++)
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("N%d ", *successorsPtr));
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
|
||||
|
||||
80
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.h
Normal file
80
mozilla/ef/Compiler/RegisterAllocator/DominatorGraph.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _DOMINATOR_GRAPH_H_
|
||||
#define _DOMINATOR_GRAPH_H_
|
||||
|
||||
#include "LogModule.h"
|
||||
|
||||
class ControlGraph;
|
||||
|
||||
struct DGNode
|
||||
{
|
||||
Uint32* successorsBegin;
|
||||
Uint32* successorsEnd;
|
||||
};
|
||||
|
||||
struct DGLinkedList
|
||||
{
|
||||
DGLinkedList* next;
|
||||
Uint32 index;
|
||||
};
|
||||
|
||||
class DominatorGraph
|
||||
{
|
||||
private:
|
||||
|
||||
ControlGraph& controlGraph;
|
||||
|
||||
Uint32 vCount;
|
||||
|
||||
Uint32* VtoG;
|
||||
Uint32* GtoV;
|
||||
Uint32* parent;
|
||||
Uint32* semi;
|
||||
Uint32* vertex;
|
||||
Uint32* label;
|
||||
Uint32* size;
|
||||
Uint32* ancestor;
|
||||
Uint32* child;
|
||||
Uint32* dom;
|
||||
DGLinkedList** bucket;
|
||||
DGNode* nodes;
|
||||
|
||||
private:
|
||||
|
||||
void build();
|
||||
|
||||
Uint32 DFS(Uint32 vx, Uint32 n);
|
||||
void LINK(Uint32 vx, Uint32 w);
|
||||
void COMPRESS(Uint32 vx);
|
||||
Uint32 EVAL(Uint32 vx);
|
||||
|
||||
public:
|
||||
|
||||
DominatorGraph(ControlGraph& controlGraph);
|
||||
|
||||
Uint32* getSuccessorsBegin(Uint32 n) const {return nodes[n].successorsBegin;}
|
||||
Uint32* getSuccessorsEnd(Uint32 n) const {return nodes[n].successorsEnd;}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
#endif // _DOMINATOR_GRAPH_H_
|
||||
20
mozilla/ef/Compiler/RegisterAllocator/HashSet.cpp
Normal file
20
mozilla/ef/Compiler/RegisterAllocator/HashSet.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
/* -*- 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.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "HashSet.h"
|
||||
97
mozilla/ef/Compiler/RegisterAllocator/HashSet.h
Normal file
97
mozilla/ef/Compiler/RegisterAllocator/HashSet.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _HASH_SET_H_
|
||||
#define _HASH_SET_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include <string.h>
|
||||
|
||||
struct HashSetElement
|
||||
{
|
||||
Uint32 index;
|
||||
HashSetElement* next;
|
||||
};
|
||||
|
||||
class HashSet
|
||||
{
|
||||
private:
|
||||
|
||||
static const hashSize = 64;
|
||||
|
||||
// Return the hash code for the given element index.
|
||||
static Uint32 getHashCode(Uint32 index) {return index & (hashSize - 1);} // Could be better !
|
||||
|
||||
private:
|
||||
|
||||
Pool& allocationPool;
|
||||
HashSetElement** bucket;
|
||||
HashSetElement* free;
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
HashSet(const HashSet&);
|
||||
// No copy operator.
|
||||
void operator = (const HashSet&);
|
||||
|
||||
public:
|
||||
|
||||
// Create a new HashSet.
|
||||
inline HashSet(Pool& pool, Uint32 universeSize);
|
||||
|
||||
// Clear the hashset.
|
||||
void clear();
|
||||
// Clear the element for the given index.
|
||||
void clear(Uint32 index);
|
||||
// Set the element for the given index.
|
||||
void set(Uint32 index);
|
||||
// Return true if the element at index is a member.
|
||||
bool test(Uint32 index) const;
|
||||
// Union with the given hashset.
|
||||
inline void or(const HashSet& set);
|
||||
// Intersection with the given hashset.
|
||||
inline void and(const HashSet& set);
|
||||
// Difference with the given hashset.
|
||||
inline void difference(const HashSet& set);
|
||||
|
||||
// Logical operators.
|
||||
HashSet& operator |= (const HashSet& set) {or(set); return *this;}
|
||||
HashSet& operator &= (const HashSet& set) {and(set); return *this;}
|
||||
HashSet& operator -= (const HashSet& set) {difference(set); return *this;}
|
||||
|
||||
// Iterator to conform with the set API.
|
||||
typedef HashSetElement* iterator;
|
||||
// Return the iterator for the first element of this set.
|
||||
iterator begin() const;
|
||||
// Return the next iterator.
|
||||
iterator advance(iterator pos) const;
|
||||
// Return true if the iterator is at the end of the set.
|
||||
bool done(iterator pos) const {return pos == NULL;}
|
||||
};
|
||||
|
||||
|
||||
inline HashSet::HashSet(Pool& pool, Uint32 /*universeSize*/)
|
||||
: allocationPool(pool), free(NULL)
|
||||
{
|
||||
bucket = new(pool) HashSetElement*[hashSize];
|
||||
memset(bucket, '\0', sizeof(HashSetElement*));
|
||||
}
|
||||
|
||||
#endif // _HASH_SET_H_
|
||||
213
mozilla/ef/Compiler/RegisterAllocator/IndexedPool.h
Normal file
213
mozilla/ef/Compiler/RegisterAllocator/IndexedPool.h
Normal file
@@ -0,0 +1,213 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _INDEXED_POOL_H_
|
||||
#define _INDEXED_POOL_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// IndexedPool<IndexedObjectSubclass> is an indexed pool of objects. The
|
||||
// template parameter 'IndexedObjectSubclass' must be a subclass of the struct
|
||||
// IndexedObject.
|
||||
//
|
||||
// When the indexed pool is ask to allocate and initialize a new object (using
|
||||
// the operator new(anIndexedPool) it will zero the memory used to store the
|
||||
// object and initialize the field 'index' of this object to its position in
|
||||
// the pool.
|
||||
//
|
||||
// An object allocated by the indexed pool can be freed by calling the method
|
||||
// IndexedPool::release(IndexedElement& objectIndex).
|
||||
//
|
||||
// example:
|
||||
//
|
||||
// IndexedPool<IndexedElement> elementPool;
|
||||
//
|
||||
// IndexedElement& element1 = *new(elementPool) IndexedElement();
|
||||
// IndexedElement& element2 = *new(elementPool) IndexedElement();
|
||||
//
|
||||
// indexedPool.release(element1);
|
||||
// IndexedElement& element3 = *new(elementPool) IndexedElement();
|
||||
//
|
||||
// At this point element1 is no longer a valid object, element2 is at
|
||||
// index 2 and element3 is at index 1.
|
||||
//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// IndexedObject -
|
||||
//
|
||||
|
||||
template<class Object>
|
||||
struct IndexedObject
|
||||
{
|
||||
Uint32 index; // Index in the pool.
|
||||
Object* next; // Used to link IndexedObject together.
|
||||
|
||||
Uint32 getIndex() {return index;}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// IndexedPool<IndexedObject> -
|
||||
//
|
||||
|
||||
template <class IndexedObject>
|
||||
class IndexedPool
|
||||
{
|
||||
private:
|
||||
|
||||
static const blockSize = 4; // Size of one block.
|
||||
|
||||
Uint32 nBlocks; // Number of blocks in the pool.
|
||||
IndexedObject** block; // Array of block pointers.
|
||||
IndexedObject* freeObjects; // Chained list of free IndexedObjects.
|
||||
Uint32 nextIndex; // Index of the next free object in the last block.
|
||||
|
||||
private:
|
||||
|
||||
void allocateAnotherBlock();
|
||||
IndexedObject& newObject();
|
||||
|
||||
public:
|
||||
|
||||
IndexedPool() : nBlocks(0), block(NULL), freeObjects(NULL), nextIndex(1) {}
|
||||
~IndexedPool();
|
||||
|
||||
IndexedObject& get(Uint32 index) const;
|
||||
void release(IndexedObject& object);
|
||||
|
||||
void setSize(Uint32 size) {assert(size < nextIndex); nextIndex = size;}
|
||||
|
||||
// Return the universe size.
|
||||
Uint32 getSize() {return nextIndex;}
|
||||
|
||||
friend void* operator new(size_t, IndexedPool<IndexedObject>& pool); // Needs to call newObject().
|
||||
};
|
||||
|
||||
// Free all the memory allocated for this object.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
IndexedPool<IndexedObject>::~IndexedPool()
|
||||
{
|
||||
for (Uint32 n = 0; n < nBlocks; n++)
|
||||
free(&((IndexedObject **) &block[n][n*blockSize])[-(n + 1)]);
|
||||
}
|
||||
|
||||
// Release the given. This object will be iserted in the chained
|
||||
// list of free IndexedObjects. To minimize the fragmentation the chained list
|
||||
// is ordered by ascending indexes.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
void IndexedPool<IndexedObject>::release(IndexedObject& object)
|
||||
{
|
||||
Uint32 index = object.index;
|
||||
IndexedObject* list = freeObjects;
|
||||
|
||||
assert(&object == &get(index)); // Make sure that object is owned by this pool.
|
||||
|
||||
if (list == NULL) { // The list is empty.
|
||||
freeObjects = &object;
|
||||
object.next = NULL;
|
||||
} else { // The list contains at least 1 element.
|
||||
if (index < list->index) { // insert as first element.
|
||||
freeObjects = &object;
|
||||
object.next = list;
|
||||
} else { // Find this object's place.
|
||||
while ((list->next) != NULL && (list->next->index < index))
|
||||
list = list->next;
|
||||
|
||||
object.next = list->next;
|
||||
list->next = &object;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// Sanity check to be sure that the list is correctly ordered.
|
||||
for (IndexedObject* obj = freeObjects; obj != NULL; obj = obj->next)
|
||||
if (obj->next != NULL)
|
||||
assert(obj->index < obj->next->index);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Create a new block of IndexedObjects. We will allocate the memory to
|
||||
// store IndexedPool::blockSize IndexedObject and the new Array of block
|
||||
// pointers.
|
||||
// The newly created IndexedObjects will not be initialized.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
void IndexedPool<IndexedObject>::allocateAnotherBlock()
|
||||
{
|
||||
void* memory = (void *) malloc((nBlocks + 1) * sizeof(Uint32) + blockSize * sizeof(IndexedObject));
|
||||
|
||||
memcpy(memory, block, nBlocks * sizeof(Uint32));
|
||||
|
||||
block = (IndexedObject **) memory;
|
||||
IndexedObject* objects = (IndexedObject *) &block[nBlocks + 1];
|
||||
|
||||
block[nBlocks] = &objects[-(nBlocks * blockSize)];
|
||||
nBlocks++;
|
||||
}
|
||||
|
||||
// Return the IndexedObject at the position 'index' in the pool.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
IndexedObject& IndexedPool<IndexedObject>::get(Uint32 index) const
|
||||
{
|
||||
Uint32 blockIndex = index / blockSize;
|
||||
assert(blockIndex < nBlocks);
|
||||
|
||||
return block[blockIndex][index];
|
||||
}
|
||||
|
||||
// Return the reference of an unused object in the pool.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
IndexedObject& IndexedPool<IndexedObject>::newObject()
|
||||
{
|
||||
if (freeObjects != NULL) {
|
||||
IndexedObject& newObject = *freeObjects;
|
||||
freeObjects = newObject.next;
|
||||
return newObject;
|
||||
}
|
||||
|
||||
Uint32 nextIndex = this->nextIndex++;
|
||||
Uint32 blockIndex = nextIndex / blockSize;
|
||||
|
||||
while (blockIndex >= nBlocks)
|
||||
allocateAnotherBlock();
|
||||
|
||||
IndexedObject& newObject = block[blockIndex][nextIndex];
|
||||
newObject.index = nextIndex;
|
||||
|
||||
return newObject;
|
||||
}
|
||||
|
||||
// Return the address of the next unsused object in the given
|
||||
// indexed pool. The field index of the newly allocated object
|
||||
// will be initialized to the corresponding index of this object
|
||||
// in the pool.
|
||||
//
|
||||
template <class IndexedObject>
|
||||
void* operator new(size_t size, IndexedPool<IndexedObject>& pool)
|
||||
{
|
||||
assert(size == sizeof(IndexedObject));
|
||||
return (void *) &pool.newObject();
|
||||
}
|
||||
|
||||
#endif // _INDEXED_POOL_H_
|
||||
258
mozilla/ef/Compiler/RegisterAllocator/InterferenceGraph.h
Normal file
258
mozilla/ef/Compiler/RegisterAllocator/InterferenceGraph.h
Normal file
@@ -0,0 +1,258 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _INTERFERENCE_GRAPH_H_
|
||||
#define _INTERFERENCE_GRAPH_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "Primitives.h"
|
||||
#include "Instruction.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "SparseSet.h"
|
||||
#include <string.h>
|
||||
|
||||
struct InterferenceVector
|
||||
{
|
||||
Uint32 count;
|
||||
InterferenceVector* next;
|
||||
RegisterName* neighbors;
|
||||
|
||||
InterferenceVector() : count(0), next(NULL) {}
|
||||
};
|
||||
|
||||
class RegisterAllocator;
|
||||
|
||||
template <class RegisterPressure>
|
||||
class InterferenceGraph
|
||||
{
|
||||
private:
|
||||
|
||||
RegisterAllocator& registerAllocator;
|
||||
|
||||
RegisterPressure::Set* interferences;
|
||||
InterferenceVector** vector;
|
||||
Uint32* offset;
|
||||
Uint32 rangeCount;
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
InterferenceGraph(const InterferenceGraph&);
|
||||
// No copy operator.
|
||||
void operator = (const InterferenceGraph&);
|
||||
|
||||
// Check if reg is a member of the universe.
|
||||
void checkMember(RegisterName name) {assert(name < rangeCount);}
|
||||
// Return the edge index for the interference between name1 and name2.
|
||||
Uint32 getEdgeIndex(RegisterName name1, RegisterName name2);
|
||||
|
||||
public:
|
||||
InterferenceGraph(RegisterAllocator& registerAllocator) : registerAllocator(registerAllocator) {}
|
||||
|
||||
// Calculate the interferences.
|
||||
void build();
|
||||
// Return true if reg1 and reg2 interfere.
|
||||
bool interfere(RegisterName name1, RegisterName name2);
|
||||
// Return the interference vector for the given register or NULL if there is none.
|
||||
InterferenceVector* getInterferenceVector(RegisterName name) {return vector[name];}
|
||||
// Set the interference between name1 and name2.
|
||||
void setInterference(RegisterName name1, RegisterName name2);
|
||||
// Set the interference vector for the given register.
|
||||
void setInterferenceVector(RegisterName name, InterferenceVector* v) {vector[name] = v;}
|
||||
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the interferences.
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void InterferenceGraph<RegisterPressure>::build()
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
this->rangeCount = rangeCount;
|
||||
|
||||
// Initialize the structures.
|
||||
//
|
||||
offset = new(pool) Uint32[rangeCount + 1];
|
||||
vector = new(pool) InterferenceVector*[rangeCount];
|
||||
memset(vector, '\0', sizeof(InterferenceVector*) * rangeCount);
|
||||
|
||||
Uint32 o = 0;
|
||||
offset[0] = 0;
|
||||
for (Uint32 i = 1; i <= rangeCount; ++i) {
|
||||
offset[i] = o;
|
||||
o += i;
|
||||
}
|
||||
|
||||
interferences = new(pool) RegisterPressure::Set(pool, (rangeCount * rangeCount) / 2);
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
LivenessInfo<RegisterPressure> liveness = Liveness<RegisterPressure>::analysis(controlGraph, rangeCount, name2range);
|
||||
registerAllocator.liveness = liveness;
|
||||
SparseSet currentLive(pool, rangeCount);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
currentLive = liveness.liveOut[n];
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
// Handle the copy instruction to avoid unnecessary interference between the 2 registers.
|
||||
if ((instruction.getFlags() & ifCopy) != 0) {
|
||||
assert(useBegin != useEnd && useBegin[0].isRegister());
|
||||
currentLive.clear(name2range[useBegin[0].getRegisterName()]);
|
||||
}
|
||||
|
||||
// Create the interferences.
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName define = name2range[definePtr->getRegisterName()];
|
||||
|
||||
for (SparseSet::iterator e = currentLive.begin(); !currentLive.done(e); e = currentLive.advance(e)) {
|
||||
RegisterName live = RegisterName(currentLive.get(e));
|
||||
|
||||
if ((live != define) && !interfere(live, define) && registerAllocator.canInterfere(live, define)) {
|
||||
|
||||
if (vector[define] == NULL)
|
||||
vector[define] = new(pool) InterferenceVector();
|
||||
vector[define]->count++;
|
||||
|
||||
if (vector[live] == NULL)
|
||||
vector[live] = new(pool) InterferenceVector();
|
||||
vector[live]->count++;
|
||||
|
||||
setInterference(live, define);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now update the liveness.
|
||||
//
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentLive.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
currentLive.set(name2range[usePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate the memory to store the interferences.
|
||||
//
|
||||
for (Uint32 e = 0; e < rangeCount; e++)
|
||||
if (vector[e] != NULL) {
|
||||
InterferenceVector& v = *vector[e];
|
||||
v.neighbors = new(pool) RegisterName[v.count];
|
||||
v.count = 0;
|
||||
}
|
||||
|
||||
// Initialize the edges.
|
||||
//
|
||||
if (RegisterPressure::Set::isOrdered()) {
|
||||
RegisterName name1 = RegisterName(0);
|
||||
|
||||
for (RegisterPressure::Set::iterator i = interferences->begin(); !interferences->done(i); i = interferences->advance(i)) {
|
||||
Uint32 interferenceIndex = interferences->get(i);
|
||||
|
||||
while(interferenceIndex >= offset[name1 + 1])
|
||||
name1 = RegisterName(name1 + 1);
|
||||
|
||||
assert((interferenceIndex >= offset[name1]) && (interferenceIndex < offset[name1 + 1]));
|
||||
|
||||
RegisterName name2 = RegisterName(interferenceIndex - offset[name1]);
|
||||
|
||||
assert(interfere(name1, name2));
|
||||
|
||||
InterferenceVector& vector1 = *vector[name1];
|
||||
vector1.neighbors[vector1.count++] = name2;
|
||||
|
||||
InterferenceVector& vector2 = *vector[name2];
|
||||
vector2.neighbors[vector2.count++] = name1;
|
||||
}
|
||||
} else {
|
||||
trespass("not Implemented"); // FIX: need one more pass to initialize the vectors.
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
Uint32 InterferenceGraph<RegisterPressure>::getEdgeIndex(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
checkMember(name1); checkMember(name2);
|
||||
assert(name1 != name2); // This is not possible.
|
||||
return (name1 < name2) ? offset[name2] + name1 : offset[name1] + name2;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void InterferenceGraph<RegisterPressure>::setInterference(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
interferences->set(getEdgeIndex(name1, name2));
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool InterferenceGraph<RegisterPressure>::interfere(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
return interferences->test(getEdgeIndex(name1, name2));
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
template <class RegisterPressure>
|
||||
void InterferenceGraph<RegisterPressure>::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Interference Vectors:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++) {
|
||||
if (vector[i] != NULL) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tvr%d: (", i));
|
||||
for (InterferenceVector* v = vector[i]; v != NULL; v = v->next)
|
||||
for (Uint32 j = 0; j < v->count; j++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%d", v->neighbors[j]));
|
||||
if (v->next != NULL || j != (v->count - 1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (","));
|
||||
}
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (")\n"));
|
||||
}
|
||||
}
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Interference Matrix:\n"));
|
||||
for (RegisterName name1 = RegisterName(1); name1 < rangeCount; name1 = RegisterName(name1 + 1)) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\t%d:\t", name1));
|
||||
for (RegisterName name2 = RegisterName(1); name2 < rangeCount; name2 = RegisterName(name2 + 1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%c", ((name1 != name2) && interfere(name1, name2)) ? '1' : '0'));
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
#endif // _INTERFERENCE_GRAPH_H_
|
||||
87
mozilla/ef/Compiler/RegisterAllocator/LiveRange.h
Normal file
87
mozilla/ef/Compiler/RegisterAllocator/LiveRange.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _LIVE_RANGE_H_
|
||||
#define _LIVE_RANGE_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Primitives.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct LiveRange
|
||||
{
|
||||
static void build(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void LiveRange<RegisterPressure>::build(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
// Intialize the lookup table.
|
||||
//
|
||||
Uint32 nameCount = registerAllocator.nameCount;
|
||||
RegisterName* nameTable = new(registerAllocator.pool) RegisterName[2*nameCount];
|
||||
RegisterName* rangeName = &nameTable[nameCount];
|
||||
|
||||
init(rangeName, nameCount);
|
||||
|
||||
// Walk the graph.
|
||||
//
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
SparseSet destination(registerAllocator.pool, nameCount);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
|
||||
destination.clear();
|
||||
for (InstructionList::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
|
||||
Instruction& phiNode = phiNodes.get(i);
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
|
||||
destination.set(findRoot(phiNode.getInstructionDefineBegin()[0].getRegisterName(), rangeName));
|
||||
}
|
||||
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
|
||||
RegisterName destinationName = phiNode.getInstructionDefineBegin()[0].getRegisterName();
|
||||
RegisterName destinationRoot = findRoot(destinationName, rangeName);
|
||||
|
||||
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++) {
|
||||
assert(usePtr->isRegister());
|
||||
RegisterName sourceName = usePtr->getRegisterName();
|
||||
RegisterName sourceRoot = findRoot(sourceName, rangeName);
|
||||
|
||||
if (sourceRoot != destinationRoot && !destination.test(sourceRoot))
|
||||
rangeName[sourceRoot] = destinationRoot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerAllocator.rangeCount = compress(registerAllocator.name2range, rangeName, nameCount, nameCount);
|
||||
}
|
||||
|
||||
#endif // _LIVE_RANGE_H_
|
||||
163
mozilla/ef/Compiler/RegisterAllocator/LiveRangeGraph.h
Normal file
163
mozilla/ef/Compiler/RegisterAllocator/LiveRangeGraph.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.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.
|
||||
*/
|
||||
|
||||
#ifndef _LIVE_RANGE_GRAPH_
|
||||
#define _LIVE_RANGE_GRAPH_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterTypes.h"
|
||||
|
||||
class RegisterAllocator;
|
||||
|
||||
template <class RegisterPressure>
|
||||
class LiveRangeGraph
|
||||
{
|
||||
private:
|
||||
|
||||
RegisterAllocator& registerAllocator;
|
||||
|
||||
RegisterPressure::Set* edges;
|
||||
Uint32 rangeCount;
|
||||
|
||||
public:
|
||||
//
|
||||
//
|
||||
LiveRangeGraph(RegisterAllocator& registerAllocator) : registerAllocator(registerAllocator) {}
|
||||
|
||||
//
|
||||
//
|
||||
void build();
|
||||
|
||||
//
|
||||
//
|
||||
void addEdge(RegisterName name1, RegisterName name2);
|
||||
|
||||
//
|
||||
//
|
||||
bool haveEdge(RegisterName name1, RegisterName name2);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
//
|
||||
//
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void LiveRangeGraph<RegisterPressure>::build()
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
this->rangeCount = rangeCount;
|
||||
|
||||
edges = new(pool) RegisterPressure::Set(pool, rangeCount * rangeCount);
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
LivenessInfo<RegisterPressure>& liveness = registerAllocator.liveness;
|
||||
SparseSet currentLive(pool, rangeCount);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
currentLive = liveness.liveOut[n];
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
if ((instruction.getFlags() & ifCopy) != 0) {
|
||||
assert(useBegin != useEnd && useBegin[0].isRegister());
|
||||
currentLive.clear(name2range[useBegin[0].getRegisterName()]);
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName define = name2range[definePtr->getRegisterName()];
|
||||
|
||||
for (SparseSet::iterator l = currentLive.begin(); !currentLive.done(l); l = currentLive.advance(l)) {
|
||||
RegisterName live = RegisterName(currentLive.get(l));
|
||||
if (define != live && registerAllocator.canInterfere(define, live))
|
||||
addEdge(define, live);
|
||||
}
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentLive.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
currentLive.set(name2range[usePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName use = name2range[usePtr->getRegisterName()];
|
||||
|
||||
for (SparseSet::iterator l = currentLive.begin(); !currentLive.done(l); l = currentLive.advance(l)) {
|
||||
RegisterName live = RegisterName(currentLive.get(l));
|
||||
if (use != live && registerAllocator.canInterfere(use, live))
|
||||
addEdge(use, live);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void LiveRangeGraph<RegisterPressure>::addEdge(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
assert(name1 != name2);
|
||||
edges->set(name1 * rangeCount + name2);
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool LiveRangeGraph<RegisterPressure>::haveEdge(RegisterName name1, RegisterName name2)
|
||||
{
|
||||
assert(name1 != name2);
|
||||
return edges->test(name1 * rangeCount + name2);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
template <class RegisterPressure>
|
||||
void LiveRangeGraph<RegisterPressure>::printPretty(LogModuleObject log)
|
||||
{
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Live ranges graph:\n"));
|
||||
for (RegisterName name1 = RegisterName(1); name1 < rangeCount; name1 = RegisterName(name1 + 1)) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\t%d:\t", name1));
|
||||
for (RegisterName name2 = RegisterName(1); name2 < rangeCount; name2 = RegisterName(name2 + 1))
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%c", ((name1 != name2) && haveEdge(name1, name2)) ? '1' : '0'));
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
#endif // _LIVE_RANGE_GRAPH_
|
||||
21
mozilla/ef/Compiler/RegisterAllocator/Liveness.cpp
Normal file
21
mozilla/ef/Compiler/RegisterAllocator/Liveness.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
/* -*- 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.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Liveness.h"
|
||||
|
||||
301
mozilla/ef/Compiler/RegisterAllocator/Liveness.h
Normal file
301
mozilla/ef/Compiler/RegisterAllocator/Liveness.h
Normal file
@@ -0,0 +1,301 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _LIVENESS_H_
|
||||
#define _LIVENESS_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterTypes.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// LivenessInfo -
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct LivenessInfo
|
||||
{
|
||||
RegisterPressure::Set* liveIn;
|
||||
RegisterPressure::Set* liveOut;
|
||||
DEBUG_LOG_ONLY(Uint32 size);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Liveness
|
||||
//
|
||||
// The liveness is defined by the following data-flow equations:
|
||||
//
|
||||
// LiveIn(n) = LocalLive(n) U (LiveOut(n) - Killed(n)).
|
||||
// LiveOut(n) = U LiveIn(s) (s a successor of n).
|
||||
//
|
||||
// where LocalLive(n) is the set of used registers in the block n, Killed(n)
|
||||
// is the set of defined registers in the block n, LiveIn(n) is the set of
|
||||
// live registers at the begining of the block n and LiveOut(n) is the set
|
||||
// of live registers at the end of the block n.
|
||||
//
|
||||
//
|
||||
// We will compute the liveness analysis in two stages:
|
||||
//
|
||||
// 1- Build LocalLive(n) (wich is an approximation of LiveIn(n)) and Killed(n)
|
||||
// for each block n.
|
||||
// 2- Perform a backward data-flow analysis to propagate the liveness information
|
||||
// through the entire control-flow graph.
|
||||
//
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct Liveness
|
||||
{
|
||||
static LivenessInfo<RegisterPressure> analysis(ControlGraph& controlGraph, Uint32 rangeCount, const RegisterName* name2range);
|
||||
static LivenessInfo<RegisterPressure> analysis(ControlGraph& controlGraph, Uint32 nameCount);
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
LivenessInfo<RegisterPressure> Liveness<RegisterPressure>::analysis(ControlGraph& controlGraph, Uint32 rangeCount, const RegisterName* name2range)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
// Allocate the temporary sets.
|
||||
RegisterPressure::Set* killed = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
|
||||
|
||||
// Allocate the globals sets.
|
||||
RegisterPressure::Set* liveIn = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
|
||||
RegisterPressure::Set* liveOut = new(pool) RegisterPressure::Set[nNodes](pool, rangeCount);
|
||||
|
||||
// First stage of the liveness analysis: Compute the sets LocalLive(stored in LiveIn) and Killed.
|
||||
//
|
||||
for (Uint32 n = 0; n < (nNodes - 1); n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLocalLive = liveIn[n];
|
||||
RegisterPressure::Set& currentKilled = killed[n];
|
||||
|
||||
// Find the instructions contributions to the sets LocalLive and Killed.
|
||||
//
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
// If a VirtualRegister is 'used' before being 'defined' then we add it to set LocalLive.
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
Uint32 index = name2range[usePtr->getRegisterName()];
|
||||
|
||||
if (!currentKilled.test(index))
|
||||
currentLocalLive.set(index);
|
||||
}
|
||||
|
||||
// If a Virtualregister is 'defined' then we add it to the set Killed.
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentKilled.set(name2range[definePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
|
||||
// Second stage of the liveness analysis: We propagate the LiveIn & LiveOut through the entire
|
||||
// control-flow graph.
|
||||
//
|
||||
RegisterPressure::Set temp(pool, rangeCount);
|
||||
|
||||
bool changed;
|
||||
do {
|
||||
changed = false;
|
||||
|
||||
// For all nodes is this graph except the endNode.
|
||||
for (Int32 n = (nNodes - 2); n >= 0; n--) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLiveIn = liveIn[n];
|
||||
RegisterPressure::Set& currentLiveOut = liveOut[n];
|
||||
|
||||
// Compute temp = Union of LiveIn(s) (s a successor of this node) | usedByPhiNodes(n).
|
||||
// temp will be the new LiveOut(n).
|
||||
Uint32 nSuccessors = node.nSuccessors();
|
||||
if (nSuccessors != 0) {
|
||||
temp = liveIn[node.nthSuccessor(0).getTarget().dfsNum];
|
||||
for (Uint32 s = 1; s < nSuccessors; s++)
|
||||
temp |= liveIn[node.nthSuccessor(s).getTarget().dfsNum];
|
||||
} else
|
||||
temp.clear();
|
||||
|
||||
// If temp and LiveOut(n) differ then set LiveOut(n) = temp and recalculate the
|
||||
// new LiveIn(n).
|
||||
if (currentLiveOut != temp) {
|
||||
currentLiveOut = temp;
|
||||
temp -= killed[n]; // FIX: could be optimized with one call to unionDiff !
|
||||
temp |= currentLiveIn;
|
||||
|
||||
if (currentLiveIn != temp) {
|
||||
currentLiveIn = temp;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(changed);
|
||||
|
||||
LivenessInfo<RegisterPressure> liveness;
|
||||
liveness.liveIn = liveIn;
|
||||
liveness.liveOut = liveOut;
|
||||
DEBUG_LOG_ONLY(liveness.size = nNodes);
|
||||
return liveness;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
LivenessInfo<RegisterPressure> Liveness<RegisterPressure>::analysis(ControlGraph& controlGraph, Uint32 nameCount)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
// Allocate the temporary sets.
|
||||
RegisterPressure::Set* killed = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
RegisterPressure::Set* usedByPhiNodes = NULL;
|
||||
|
||||
// Allocate the globals sets.
|
||||
RegisterPressure::Set* liveIn = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
RegisterPressure::Set* liveOut = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
|
||||
// First stage of the liveness analysis: Compute the sets LocalLive(stored in LiveIn) and Killed.
|
||||
//
|
||||
for (Uint32 n = 0; n < (nNodes - 1); n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLocalLive = liveIn[n];
|
||||
RegisterPressure::Set& currentKilled = killed[n];
|
||||
|
||||
InstructionList& phiNodes = node.getPhiNodeInstructions();
|
||||
|
||||
if ((usedByPhiNodes == NULL) && !phiNodes.empty())
|
||||
usedByPhiNodes = new(pool) RegisterPressure::Set[nNodes](pool, nameCount);
|
||||
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
InstructionDefine& define = phiNode.getInstructionDefineBegin()[0];
|
||||
currentKilled.set(define.getRegisterName());
|
||||
|
||||
typedef DoublyLinkedList<ControlEdge> ControlEdgeList;
|
||||
const ControlEdgeList& predecessors = node.getPredecessors();
|
||||
ControlEdgeList::iterator p = predecessors.begin();
|
||||
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++, p = predecessors.advance(p))
|
||||
if (usePtr->isRegister())
|
||||
usedByPhiNodes[predecessors.get(p).getSource().dfsNum].set(usePtr->getRegisterName());
|
||||
}
|
||||
|
||||
// Find the instructions contributions to the sets LocalLive and Killed.
|
||||
//
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
// If a VirtualRegister is 'used' before being 'defined' then we add it to set LocalLive.
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
Uint32 index = usePtr->getRegisterName();
|
||||
|
||||
if (!currentKilled.test(index))
|
||||
currentLocalLive.set(index);
|
||||
}
|
||||
|
||||
// If a Virtualregister is 'defined' then we add it to the set Killed.
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentKilled.set(definePtr->getRegisterName());
|
||||
}
|
||||
}
|
||||
|
||||
// Second stage of the liveness analysis: We propagate the LiveIn & LiveOut through the entire
|
||||
// control-flow graph.
|
||||
//
|
||||
RegisterPressure::Set temp(pool, nameCount);
|
||||
|
||||
bool changed;
|
||||
do {
|
||||
changed = false;
|
||||
|
||||
// For all nodes is this graph except the endNode.
|
||||
for (Int32 n = (nNodes - 2); n >= 0; n--) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
RegisterPressure::Set& currentLiveIn = liveIn[n];
|
||||
RegisterPressure::Set& currentLiveOut = liveOut[n];
|
||||
|
||||
// Compute temp = Union of LiveIn(s) (s a successor of this node) | usedByPhiNodes(n).
|
||||
// temp will be the new LiveOut(n).
|
||||
Uint32 nSuccessors = node.nSuccessors();
|
||||
if (nSuccessors != 0) {
|
||||
temp = liveIn[node.nthSuccessor(0).getTarget().dfsNum];
|
||||
for (Uint32 s = 1; s < nSuccessors; s++)
|
||||
temp |= liveIn[node.nthSuccessor(s).getTarget().dfsNum];
|
||||
} else
|
||||
temp.clear();
|
||||
|
||||
// Insert the phiNodes contribution.
|
||||
if (usedByPhiNodes != NULL)
|
||||
temp |= usedByPhiNodes[n];
|
||||
|
||||
// If temp and LiveOut(n) differ then set LiveOut(n) = temp and recalculate the
|
||||
// new LiveIn(n).
|
||||
if (currentLiveOut != temp) {
|
||||
currentLiveOut = temp;
|
||||
temp -= killed[n]; // FIX: could be optimized with one call to unionDiff !
|
||||
temp |= currentLiveIn;
|
||||
|
||||
if (currentLiveIn != temp) {
|
||||
currentLiveIn = temp;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(changed);
|
||||
|
||||
LivenessInfo<RegisterPressure> liveness;
|
||||
liveness.liveIn = liveIn;
|
||||
liveness.liveOut = liveOut;
|
||||
DEBUG_LOG_ONLY(liveness.size = nNodes);
|
||||
return liveness;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
template <class RegisterPressure>
|
||||
void LivenessInfo<RegisterPressure>::printPretty(LogModuleObject log)
|
||||
{
|
||||
for (Uint32 n = 0; n < size; n++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Node N%d:\n\tliveIn = ", n));
|
||||
liveIn[n].printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\tliveOut = "));
|
||||
liveOut[n].printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
#endif // _LIVENESS_H_
|
||||
40
mozilla/ef/Compiler/RegisterAllocator/Makefile
Normal file
40
mozilla/ef/Compiler/RegisterAllocator/Makefile
Normal file
@@ -0,0 +1,40 @@
|
||||
#! gmake
|
||||
|
||||
DEPTH = ../..
|
||||
|
||||
MODULE_NAME = RegisterAllocator
|
||||
|
||||
include $(DEPTH)/config/config.mk
|
||||
|
||||
INCLUDES += \
|
||||
-I$(DEPTH)/Utilities/General \
|
||||
-I$(DEPTH)/Utilities/zlib \
|
||||
-I$(DEPTH)/Runtime/ClassReader \
|
||||
-I$(DEPTH)/Runtime/NativeMethods \
|
||||
-I$(DEPTH)/Runtime/System \
|
||||
-I$(DEPTH)/Runtime/ClassInfo \
|
||||
-I$(DEPTH)/Runtime/FileReader \
|
||||
-I$(DEPTH)/Compiler/PrimitiveGraph \
|
||||
-I$(DEPTH)/Compiler/FrontEnd \
|
||||
-I$(DEPTH)/Compiler/Optimizer \
|
||||
-I$(DEPTH)/Compiler/CodeGenerator \
|
||||
-I$(DEPTH)/Compiler/CodeGenerator/md \
|
||||
-I$(DEPTH)/Compiler/CodeGenerator/md/$(CPU_ARCH) \
|
||||
-I$(DEPTH)/Compiler/RegisterAllocator \
|
||||
-I$(DEPTH)/Driver/StandAloneJava \
|
||||
-I$(DEPTH)/Debugger \
|
||||
$(NULL)
|
||||
|
||||
CXXSRCS = \
|
||||
RegisterAllocator.cpp \
|
||||
RegisterAllocatorTools.cpp \
|
||||
DominatorGraph.cpp \
|
||||
VirtualRegister.cpp \
|
||||
BitSet.cpp \
|
||||
SparseSet.cpp \
|
||||
$(NULL)
|
||||
|
||||
|
||||
include $(DEPTH)/config/rules.mk
|
||||
|
||||
libs:: $(MODULE)
|
||||
392
mozilla/ef/Compiler/RegisterAllocator/PhiNodeRemover.h
Normal file
392
mozilla/ef/Compiler/RegisterAllocator/PhiNodeRemover.h
Normal file
@@ -0,0 +1,392 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _PHI_NODE_REMOVER_H_
|
||||
#define _PHI_NODE_REMOVER_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "DominatorGraph.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "Liveness.h"
|
||||
#include "Instruction.h"
|
||||
#include "InstructionEmitter.h"
|
||||
#include "SparseSet.h"
|
||||
#include <string.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterNameNode -
|
||||
|
||||
struct RegisterNameNode
|
||||
{
|
||||
RegisterNameNode* next;
|
||||
RegisterName newName;
|
||||
Uint32 nextPushed;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// CopyData -
|
||||
|
||||
struct CopyData
|
||||
{
|
||||
RegisterName source;
|
||||
RegisterClassKind classKind;
|
||||
Uint32 useCount;
|
||||
bool isLiveOut;
|
||||
RegisterName sourceNameToUse;
|
||||
RegisterName temporaryName;
|
||||
RegisterNameNode* newName;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// PhiNodeRemover<RegisterPressure> -
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct PhiNodeRemover
|
||||
{
|
||||
// Replace the phi nodes by copy instructions.
|
||||
static void replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
|
||||
};
|
||||
|
||||
// Split some of the critical edges and return true if there are still some
|
||||
// in the graph after that.
|
||||
//
|
||||
static bool splitCriticalEdges(ControlGraph& /*cg*/)
|
||||
{
|
||||
// FIX: not implemented.
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void pushName(Pool& pool, RegisterNameNode** stack, SparseSet& pushed, Uint32* nodeListPointer, RegisterName oldName, RegisterName newName)
|
||||
{
|
||||
RegisterNameNode& newNode = *new(pool) RegisterNameNode();
|
||||
|
||||
if (pushed.test(oldName))
|
||||
(*stack)->newName = newName;
|
||||
else {
|
||||
newNode.newName = newName;
|
||||
newNode.nextPushed = *nodeListPointer;
|
||||
*nodeListPointer = oldName;
|
||||
newNode.next = *stack;
|
||||
*stack = &newNode;
|
||||
pushed.set(oldName);
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void PhiNodeRemover<RegisterPressure>::replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
// Initialize the local variables.
|
||||
//
|
||||
|
||||
// When we insert the copies we will also need to create new VirtualRegisters for
|
||||
// the insertion of temporaries. The maximum number of temporary register will not
|
||||
// exceed the number of phiNodes in the primitive graph.
|
||||
Uint32 nameCount = vrManager.getSize();
|
||||
Uint32 maxNameCount = nameCount;
|
||||
for (Uint32 n = 0; n < nNodes; n++)
|
||||
maxNameCount += nodes[n]->getPhiNodes().length();
|
||||
|
||||
// If the CFG contains some critical edges (backward edge which source has more than one
|
||||
// outgoing edge and destination has more than one incomimg edge) then we need the liveness
|
||||
// information to be able to insert temporary copies.
|
||||
RegisterPressure::Set* liveOut = NULL;
|
||||
if (splitCriticalEdges(controlGraph))
|
||||
liveOut = Liveness<LowRegisterPressure>::analysis(controlGraph, nameCount).liveOut;
|
||||
|
||||
DominatorGraph dGraph(controlGraph);
|
||||
|
||||
SparseSet pushed(pool, maxNameCount);
|
||||
SparseSet destinationList(pool, maxNameCount);
|
||||
SparseSet workList(pool, maxNameCount);
|
||||
|
||||
CopyData* copyStats = new(pool) CopyData[maxNameCount];
|
||||
memset(copyStats, '\0', maxNameCount*sizeof(CopyData));
|
||||
|
||||
struct NodeStack {
|
||||
Uint32* next;
|
||||
Uint32* limit;
|
||||
Uint32 pushedList;
|
||||
};
|
||||
|
||||
// Allocate the node stack and initialize the node stack pointer.
|
||||
NodeStack* nodeStack = new(pool) NodeStack[nNodes + 1];
|
||||
NodeStack* nodeStackPtr = nodeStack;
|
||||
|
||||
// We start by the begin node.
|
||||
Uint32 startNode = 0;
|
||||
Uint32* next = &startNode;
|
||||
Uint32* limit = &startNode + 1;
|
||||
|
||||
while (true) {
|
||||
|
||||
if (next == limit) {
|
||||
// If there are no more node in the sibling, we have to pop the current
|
||||
// frame from the stack and update the copyStats of the pushed nodes.
|
||||
//
|
||||
if (nodeStackPtr == nodeStack)
|
||||
// We are at the bottom of the stack and there are no more nodes
|
||||
// to look at. We are done !
|
||||
break;
|
||||
|
||||
--nodeStackPtr;
|
||||
// We are done with all the children of this node in the dominator tree.
|
||||
// We need to update the copy information of all the new names pushed
|
||||
// during the walk over this node.
|
||||
Uint32 pushedList = nodeStackPtr->pushedList;
|
||||
while (pushedList != 0) {
|
||||
Uint32 nextName = copyStats[pushedList].newName->nextPushed;
|
||||
copyStats[pushedList].newName = copyStats[pushedList].newName->next;
|
||||
pushedList = nextName;
|
||||
}
|
||||
|
||||
// restore the previous frame.
|
||||
next = nodeStackPtr->next;
|
||||
limit = nodeStackPtr->limit;
|
||||
} else {
|
||||
Uint32 currentNode = *next++;
|
||||
Uint32 pushedList = 0;
|
||||
|
||||
|
||||
// Initialize the sets.
|
||||
pushed.clear();
|
||||
destinationList.clear();
|
||||
|
||||
// STEP1:
|
||||
// Walk the instruction list and to replace all the instruction uses with their new name.
|
||||
// If the instruction is a phi node and its defined register is alive at the end of this
|
||||
// block then we push the defined register into the stack.
|
||||
//
|
||||
ControlNode& node = *nodes[currentNode];
|
||||
RegisterPressure::Set* currentLiveOut = (liveOut != NULL) ? &liveOut[currentNode] : (RegisterPressure::Set*) 0;
|
||||
|
||||
InstructionList& phiNodes = node.getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = phiNode.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = phiNode.getInstructionUseBegin(); usePtr < useEnd; usePtr++) {
|
||||
assert(usePtr->isRegister());
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
|
||||
if (copyStats[name].newName != NULL && copyStats[name].newName->newName != name)
|
||||
usePtr->setRegisterName(copyStats[name].newName->newName);
|
||||
}
|
||||
|
||||
if (currentLiveOut != NULL) {
|
||||
// This is a phi node and we have to push its defined name if it is live
|
||||
// at the end of the node. We only need to do this if the CFG has critical edges.
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd() && phiNode.getInstructionDefineBegin()[0].isRegister());
|
||||
RegisterName name = phiNode.getInstructionDefineBegin()[0].getRegisterName();
|
||||
|
||||
if (currentLiveOut->test(name))
|
||||
pushName(pool, &(copyStats[name].newName), pushed, &pushedList, name, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
|
||||
if (copyStats[name].newName != NULL && copyStats[name].newName->newName != name)
|
||||
usePtr->setRegisterName(copyStats[name].newName->newName);
|
||||
}
|
||||
}
|
||||
|
||||
// STEP2:
|
||||
// Look at this node's successors' phiNodes. We keep track of the number of time
|
||||
// a VR will be used by another copy instruction and insert each definition into the
|
||||
// destinationList. This is the only pass over this node's successors as we will
|
||||
// get all the information we need in the CopyData structures.
|
||||
//
|
||||
ControlEdge* successorEdgeEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorEdgePtr = node.getSuccessorsBegin(); successorEdgePtr < successorEdgeEnd; successorEdgePtr++) {
|
||||
Uint32 useIndex = successorEdgePtr->getIndex();
|
||||
ControlNode& successor = successorEdgePtr->getTarget();
|
||||
|
||||
// Look at its phi nodes. The phi nodes are at the top of the instruction list. We exit
|
||||
// as soon as we find an instruction which is not a phi node
|
||||
InstructionList& phiNodes = successor.getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& phiNode = phiNodes.get(p);
|
||||
|
||||
assert((phiNode.getInstructionUseBegin() + useIndex) < phiNode.getInstructionUseEnd());
|
||||
assert(phiNode.getInstructionDefineBegin() != phiNode.getInstructionDefineEnd());
|
||||
|
||||
InstructionUse& source = phiNode.getInstructionUseBegin()[useIndex];
|
||||
InstructionDefine& destination = phiNode.getInstructionDefineBegin()[0];
|
||||
|
||||
assert(source.isRegister() && destination.isRegister());
|
||||
|
||||
RegisterName sourceName = source.getRegisterName();
|
||||
RegisterName destinationName = destination.getRegisterName();
|
||||
|
||||
// Get the correct name for the source.
|
||||
if (copyStats[sourceName].newName != NULL)
|
||||
sourceName = copyStats[sourceName].newName->newName;
|
||||
|
||||
// Update the CopyData structures.
|
||||
if ((sourceName != rnInvalid) && (sourceName != destinationName)) {
|
||||
copyStats[destinationName].source = sourceName;
|
||||
copyStats[destinationName].classKind = destination.getRegisterClass();
|
||||
copyStats[destinationName].isLiveOut = (currentLiveOut != NULL) ? currentLiveOut->test(destinationName) : false;
|
||||
copyStats[destinationName].sourceNameToUse = destinationName;
|
||||
copyStats[sourceName].sourceNameToUse = sourceName;
|
||||
copyStats[sourceName].useCount++;
|
||||
destinationList.set(destinationName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// STEP3:
|
||||
// Insert into the worklist only the destination registers that will be not used in
|
||||
// another copy instruction in this block.
|
||||
//
|
||||
assert(workList.getSize() == 0);
|
||||
for (SparseSet::iterator d = destinationList.begin(); !destinationList.done(d); d = destinationList.advance(d)) {
|
||||
Uint32 dest = destinationList.get(d);
|
||||
if (copyStats[dest].useCount == 0)
|
||||
workList.set(dest);
|
||||
}
|
||||
|
||||
// STEP4:
|
||||
// Insert the copy instructions.
|
||||
//
|
||||
Uint32 destinationListSize = destinationList.getSize();
|
||||
InstructionList::iterator endOfTheNode = instructions.end();
|
||||
|
||||
// Find the right place to insert the copy instructions.
|
||||
if (destinationListSize != 0)
|
||||
while (instructions.get(endOfTheNode).getFlags() & ifControl)
|
||||
endOfTheNode = instructions.retreat(endOfTheNode);
|
||||
|
||||
while (destinationListSize != 0) {
|
||||
while(workList.getSize()) {
|
||||
RegisterName destinationName = RegisterName(workList.getOne());
|
||||
RegisterName sourceName = copyStats[destinationName].source;
|
||||
|
||||
workList.clear(destinationName);
|
||||
if (copyStats[destinationName].isLiveOut && !copyStats[destinationName].temporaryName) {
|
||||
// Lost copy problem.
|
||||
copyStats[destinationName].isLiveOut = false;
|
||||
|
||||
RegisterName sourceName = destinationName;
|
||||
RegisterClassKind classKind = copyStats[sourceName].classKind;
|
||||
RegisterName destinationName = getName(vrManager.newVirtualRegister(classKind));
|
||||
assert(destinationName < maxNameCount);
|
||||
|
||||
copyStats[destinationName].classKind = classKind;
|
||||
copyStats[sourceName].useCount = 0;
|
||||
|
||||
// We need to insert a copy to a temporary register to keep the
|
||||
// source register valid at the end of the node defining it.
|
||||
// This copy will be inserted right after the phi node defining it.
|
||||
RegisterName from = copyStats[sourceName].sourceNameToUse;
|
||||
Instruction* definingPhiNode = vrManager.getVirtualRegister(from).getDefiningInstruction();
|
||||
assert(definingPhiNode && (definingPhiNode->getFlags() & ifPhiNode) != 0);
|
||||
|
||||
RegisterID fromID = buildRegisterID(from, classKind);
|
||||
RegisterID toID = buildRegisterID(destinationName, classKind);
|
||||
Instruction& copy = emitter.newCopy(*definingPhiNode->getPrimitive(), fromID, toID);
|
||||
vrManager.getVirtualRegister(destinationName).setDefiningInstruction(copy);
|
||||
definingPhiNode->getPrimitive()->getContainer()->getInstructions().addFirst(copy);
|
||||
|
||||
copyStats[sourceName].temporaryName = destinationName;
|
||||
copyStats[sourceName].sourceNameToUse = destinationName;
|
||||
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
|
||||
}
|
||||
|
||||
// Insert the copy instruction at the end of the current node.
|
||||
RegisterName from = copyStats[sourceName].sourceNameToUse;
|
||||
|
||||
RegisterClassKind classKind = copyStats[destinationName].classKind;
|
||||
RegisterID fromID = buildRegisterID(from, classKind);
|
||||
RegisterID toID = buildRegisterID(destinationName, classKind);
|
||||
Instruction& copy = emitter.newCopy(*vrManager.getVirtualRegister(from).getDefiningInstruction()->getPrimitive(), fromID, toID);
|
||||
instructions.insertAfter(copy, endOfTheNode);
|
||||
endOfTheNode = instructions.advance(endOfTheNode);
|
||||
|
||||
copyStats[sourceName].useCount = 0;
|
||||
if (destinationList.test(sourceName) && copyStats[sourceName].isLiveOut)
|
||||
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
|
||||
copyStats[sourceName].isLiveOut = false;
|
||||
copyStats[sourceName].sourceNameToUse = destinationName;
|
||||
|
||||
if (destinationList.test(sourceName))
|
||||
workList.set(sourceName);
|
||||
destinationList.clear(destinationName);
|
||||
}
|
||||
|
||||
destinationListSize = destinationList.getSize();
|
||||
if (destinationListSize != 0) {
|
||||
RegisterName sourceName = RegisterName(destinationList.getOne());
|
||||
RegisterName destinationName;
|
||||
|
||||
if (!copyStats[sourceName].temporaryName) {
|
||||
// Cycle problem.
|
||||
RegisterClassKind classKind = copyStats[sourceName].classKind;
|
||||
destinationName = getName(vrManager.newVirtualRegister(classKind));
|
||||
assert(destinationName < maxNameCount);
|
||||
|
||||
copyStats[destinationName].classKind = classKind;
|
||||
copyStats[sourceName].temporaryName = destinationName;
|
||||
|
||||
// Insert the copy instruction at the end of the current node.
|
||||
RegisterName from = copyStats[sourceName].sourceNameToUse;
|
||||
|
||||
RegisterID fromID = buildRegisterID(from, classKind);
|
||||
RegisterID toID = buildRegisterID(destinationName, classKind);
|
||||
Instruction& copy = emitter.newCopy(*vrManager.getVirtualRegister(from).getDefiningInstruction()->getPrimitive(), fromID, toID);
|
||||
vrManager.getVirtualRegister(destinationName).setDefiningInstruction(copy);
|
||||
instructions.insertAfter(copy, endOfTheNode);
|
||||
endOfTheNode = instructions.advance(endOfTheNode);
|
||||
} else
|
||||
destinationName = copyStats[sourceName].temporaryName;
|
||||
|
||||
copyStats[sourceName].useCount = 0;
|
||||
copyStats[sourceName].isLiveOut = false;
|
||||
copyStats[sourceName].sourceNameToUse = destinationName;
|
||||
pushName(pool, &(copyStats[sourceName].newName), pushed, &pushedList, sourceName, destinationName);
|
||||
|
||||
workList.set(sourceName);
|
||||
}
|
||||
}
|
||||
|
||||
nodeStackPtr->pushedList = pushedList;
|
||||
nodeStackPtr->next = next;
|
||||
nodeStackPtr->limit = limit;
|
||||
++nodeStackPtr;
|
||||
next = dGraph.getSuccessorsBegin(currentNode);
|
||||
limit = dGraph.getSuccessorsEnd(currentNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _PHI_NODE_REMOVER_H_
|
||||
155
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.cpp
Normal file
155
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
/* -*- 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.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "LogModule.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterPressure.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
#include "PhiNodeRemover.h"
|
||||
#include "LiveRange.h"
|
||||
#include "Liveness.h"
|
||||
#include "InterferenceGraph.h"
|
||||
#include "LiveRangeGraph.h"
|
||||
#include "Coalescing.h"
|
||||
#include "Spilling.h"
|
||||
#include "Coloring.h"
|
||||
#include "Splits.h"
|
||||
|
||||
class Pool;
|
||||
class ControlGraph;
|
||||
class VirtualRegisterManager;
|
||||
class InstructionEmitter;
|
||||
|
||||
UT_DEFINE_LOG_MODULE(RegAlloc);
|
||||
|
||||
void RegisterAllocator::allocateRegisters(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
|
||||
{
|
||||
// Insert the phi node instructions. We want to do this to have a single defined register per instruction.
|
||||
// If we keep the PhiNode (as a DataNode) and a PhiNode is of DoubleWordKind then we have to execute
|
||||
// some special code for the high word annotation.
|
||||
//
|
||||
RegisterAllocatorTools::insertPhiNodeInstructions(controlGraph, emitter);
|
||||
|
||||
// Perform some tests on the instruction graph.
|
||||
//
|
||||
DEBUG_ONLY(RegisterAllocatorTools::testTheInstructionGraph(controlGraph, vrManager));
|
||||
|
||||
// Replace the phi node instructions by their equivalent copy instructions.
|
||||
//
|
||||
PhiNodeRemover<LowRegisterPressure>::replacePhiNodes(controlGraph, vrManager, emitter);
|
||||
|
||||
// Do the register allocation.
|
||||
//
|
||||
RegisterAllocator registerAllocator(pool, controlGraph, vrManager, emitter);
|
||||
registerAllocator.doGraphColoring();
|
||||
}
|
||||
|
||||
void RegisterAllocator::doGraphColoring()
|
||||
{
|
||||
// Initialize the liverange map.
|
||||
//
|
||||
initLiveRanges();
|
||||
|
||||
// Build the live ranges. We do this to compress the number of RegisterNames
|
||||
// used in the insterference graph.
|
||||
//
|
||||
LiveRange<LowRegisterPressure>::build(*this);
|
||||
|
||||
// Remove unnecessary copies.
|
||||
//
|
||||
RegisterAllocatorTools::removeUnnecessaryCopies(*this);
|
||||
|
||||
for (Uint8 loop = 0; loop < 10; loop++) {
|
||||
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("********* RegisterAllocator loop %d *********\n", loop));
|
||||
|
||||
while(true) {
|
||||
// Build the interference graph.
|
||||
//
|
||||
iGraph.build();
|
||||
|
||||
// Coalesce the copy instructions.
|
||||
//
|
||||
if (!Coalescing<LowRegisterPressure>::coalesce(*this))
|
||||
break;
|
||||
}
|
||||
|
||||
// Print the interference graph.
|
||||
//
|
||||
DEBUG_LOG_ONLY(iGraph.printPretty(UT_LOG_MODULE(RegAlloc)));
|
||||
|
||||
// Calculate the spill costs.
|
||||
//
|
||||
Spilling<LowRegisterPressure>::calculateSpillCosts(*this);
|
||||
DEBUG_LOG_ONLY(RegisterAllocatorTools::printSpillCosts(*this));
|
||||
|
||||
// Calculate the split costs.
|
||||
//
|
||||
Splits<LowRegisterPressure>::calculateSplitCosts(*this);
|
||||
DEBUG_LOG_ONLY(RegisterAllocatorTools::printSplitCosts(*this));
|
||||
|
||||
// Build the live range graph.
|
||||
//
|
||||
lGraph.build();
|
||||
DEBUG_LOG_ONLY(lGraph.printPretty(UT_LOG_MODULE(RegAlloc)));
|
||||
|
||||
// Color the graph. If it succeeds then we're done with the
|
||||
// register allocation.
|
||||
//
|
||||
if (Coloring<LowRegisterPressure>::color(*this)) {
|
||||
// Write the final colors in the instruction graph.
|
||||
//
|
||||
Coloring<LowRegisterPressure>::finalColoring(*this);
|
||||
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("********** RegisterAllocator done **********\n"));
|
||||
DEBUG_LOG_ONLY(RegisterAllocatorTools::printInstructions(*this));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to spill some registers.
|
||||
//
|
||||
Spilling<LowRegisterPressure>::insertSpillCode(*this);
|
||||
|
||||
// Insert the split instructions.
|
||||
//
|
||||
Splits<LowRegisterPressure>::insertSplitCode(*this);
|
||||
|
||||
// Update the live ranges.
|
||||
//
|
||||
// FIX
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
RegisterAllocatorTools::updateInstructionGraph(*this);
|
||||
RegisterAllocatorTools::printInstructions(*this);
|
||||
#endif
|
||||
fprintf(stderr, "!!! Coloring failed after 10 loops !!!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
void RegisterAllocator::initLiveRanges()
|
||||
{
|
||||
Uint32 count = this->nameCount;
|
||||
RegisterName* name2range = new(pool) RegisterName[nameCount];
|
||||
for (RegisterName r = RegisterName(1); r < count; r = RegisterName(r + 1))
|
||||
name2range[r] = r;
|
||||
this->name2range = name2range;
|
||||
rangeCount = count;
|
||||
}
|
||||
88
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.h
Normal file
88
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocator.h
Normal 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_ALLOCATOR_H_
|
||||
#define _REGISTER_ALLOCATOR_H_
|
||||
|
||||
class Pool;
|
||||
class ControlGraph;
|
||||
class InstructionEmitter;
|
||||
struct SpillCost;
|
||||
struct SplitCost;
|
||||
|
||||
#include "Liveness.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "RegisterPressure.h" // This should included by Backend.cpp
|
||||
#include "InterferenceGraph.h"
|
||||
#include "LiveRangeGraph.h"
|
||||
|
||||
//template <class RegisterPressure>
|
||||
class RegisterAllocator
|
||||
{
|
||||
public:
|
||||
|
||||
Pool& pool; //
|
||||
ControlGraph& controlGraph; //
|
||||
VirtualRegisterManager& vrManager; //
|
||||
InstructionEmitter& emitter; //
|
||||
|
||||
RegisterName* name2range; //
|
||||
RegisterName* color; //
|
||||
SpillCost* spillCost; //
|
||||
SparseSet* willSpill; //
|
||||
SplitCost* splitCost; //
|
||||
NameLinkedList** splitAround; //
|
||||
InterferenceGraph<LowRegisterPressure> iGraph; //
|
||||
LiveRangeGraph<LowRegisterPressure> lGraph; //
|
||||
LivenessInfo<LowRegisterPressure> liveness; //
|
||||
Uint32 nameCount; //
|
||||
Uint32 rangeCount; //
|
||||
bool splitFound; //
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
//
|
||||
void doGraphColoring();
|
||||
|
||||
public:
|
||||
|
||||
//
|
||||
//
|
||||
inline RegisterAllocator(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
|
||||
|
||||
//
|
||||
//
|
||||
bool canInterfere(RegisterName /*name1*/, RegisterName /*name2*/) const {return true;}
|
||||
|
||||
//
|
||||
//
|
||||
void initLiveRanges();
|
||||
|
||||
//
|
||||
//
|
||||
static void allocateRegisters(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter);
|
||||
};
|
||||
|
||||
//
|
||||
//
|
||||
inline RegisterAllocator::RegisterAllocator(Pool& pool, ControlGraph& controlGraph, VirtualRegisterManager& vrManager, InstructionEmitter& emitter)
|
||||
: pool(pool), controlGraph(controlGraph), vrManager(vrManager), emitter(emitter), iGraph(*this), lGraph(*this), nameCount(vrManager.getSize()) {}
|
||||
|
||||
#endif // _REGISTER_ALLOCATOR_H_
|
||||
|
||||
355
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.cpp
Normal file
355
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.cpp
Normal file
@@ -0,0 +1,355 @@
|
||||
/* -*- 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.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "LogModule.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Primitives.h"
|
||||
#include "InstructionEmitter.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "Spilling.h"
|
||||
#include "Splits.h"
|
||||
#include "BitSet.h"
|
||||
|
||||
UT_EXTERN_LOG_MODULE(RegAlloc);
|
||||
|
||||
#ifdef DEBUG
|
||||
void RegisterAllocatorTools::testTheInstructionGraph(ControlGraph& controlGraph, VirtualRegisterManager& vrManager)
|
||||
{
|
||||
// Test the declared VirtualRegisters. The register allocator tries to condense the register universe.
|
||||
// Any gap in the VirtualRegister names will be a loss of efficiency !!!!
|
||||
|
||||
Uint32 nameCount = vrManager.getSize();
|
||||
BitSet registerSeen(controlGraph.pool, nameCount);
|
||||
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
registerSeen.set(usePtr->getRegisterName());
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
registerSeen.set(definePtr->getRegisterName());
|
||||
}
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& instruction = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
registerSeen.set(usePtr->getRegisterName());
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
registerSeen.set(definePtr->getRegisterName());
|
||||
}
|
||||
}
|
||||
|
||||
bool renameRegisters = false;
|
||||
for (BitSet::iterator i = registerSeen.nextZero(0); !registerSeen.done(i); i = registerSeen.nextZero(i)) {
|
||||
renameRegisters = true;
|
||||
fprintf(stderr,
|
||||
"WARNING: The VirtualRegister vr%d has been allocated during CodeGeneration but\n"
|
||||
" is never used nor defined by any instruction in the instruction graph\n"
|
||||
" PLEASE FIX \n",
|
||||
i);
|
||||
}
|
||||
if (renameRegisters) {
|
||||
Instruction** definingInstruction = new Instruction*[nameCount];
|
||||
memset(definingInstruction, '\0', nameCount * sizeof(Instruction*));
|
||||
RegisterName* newName = new RegisterName[nameCount];
|
||||
memset(newName, '\0', nameCount * sizeof(RegisterName));
|
||||
RegisterName nextName = RegisterName(1);
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
usePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName name = definePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
definePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
}
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& instruction = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName name = usePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
usePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName name = definePtr->getRegisterName();
|
||||
if (newName[name] == rnInvalid) {
|
||||
newName[name] = nextName;
|
||||
definingInstruction[nextName] = vrManager.getVirtualRegister(name).getDefiningInstruction();
|
||||
nextName = RegisterName(nextName + 1);
|
||||
}
|
||||
definePtr->setRegisterName(newName[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vrManager.setSize(nextName);
|
||||
|
||||
for (RegisterName r = RegisterName(1); r < nextName; r = RegisterName(r + 1))
|
||||
vrManager.getVirtualRegister(r).definingInstruction = definingInstruction[r];
|
||||
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("RegisterMap:\n"));
|
||||
for (Uint32 i = 1; i < nameCount; i++)
|
||||
if (newName[i] != 0)
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tvr%d becomes vr%d.\n", i, newName[i]));
|
||||
else
|
||||
UT_OBJECTLOG(UT_LOG_MODULE(RegAlloc), PR_LOG_ALWAYS, ("\tvr%d is dead.\n", i));
|
||||
|
||||
|
||||
delete newName;
|
||||
delete definingInstruction;
|
||||
}
|
||||
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
void RegisterAllocatorTools::removeUnnecessaryCopies(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i);) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
i = instructions.advance(i);
|
||||
|
||||
if (instruction.getFlags() & ifCopy) {
|
||||
assert(instruction.getInstructionUseBegin() != instruction.getInstructionUseEnd() && instruction.getInstructionUseBegin()[0].isRegister());
|
||||
assert(instruction.getInstructionDefineBegin() != instruction.getInstructionDefineEnd() && instruction.getInstructionDefineBegin()[0].isRegister());
|
||||
|
||||
RegisterName source = name2range[instruction.getInstructionUseBegin()[0].getRegisterName()];
|
||||
RegisterName destination = name2range[instruction.getInstructionDefineBegin()[0].getRegisterName()];
|
||||
|
||||
if (source == destination)
|
||||
instruction.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RegisterAllocatorTools::updateInstructionGraph(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
usePtr->setRegisterName(name2range[usePtr->getRegisterName()]);
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
definePtr->setRegisterName(name2range[definePtr->getRegisterName()]);
|
||||
}
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
for (InstructionList::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
|
||||
Instruction& instruction = phiNodes.get(p);
|
||||
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
usePtr->setRegisterName(name2range[usePtr->getRegisterName()]);
|
||||
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
definePtr->setRegisterName(name2range[definePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RegisterAllocatorTools::insertPhiNodeInstructions(ControlGraph& controlGraph, InstructionEmitter& emitter)
|
||||
{
|
||||
Pool& pool = controlGraph.pool;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
DoublyLinkedList<PhiNode>& phiNodes = node.getPhiNodes();
|
||||
|
||||
if (!phiNodes.empty()) {
|
||||
|
||||
// Set the index of the incoming edges.
|
||||
Uint32 index = 0;
|
||||
const DoublyLinkedList<ControlEdge>& predecessors = node.getPredecessors();
|
||||
for (DoublyLinkedList<ControlEdge>::iterator p = predecessors.begin(); !predecessors.done(p); p = predecessors.advance(p))
|
||||
predecessors.get(p).setIndex(index++);
|
||||
|
||||
// Insert the phi node instruction in the instruction list.
|
||||
for (DoublyLinkedList<PhiNode>::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
|
||||
PhiNode& phiNode = phiNodes.get(i);
|
||||
ValueKind kind = phiNode.getKind();
|
||||
|
||||
if (!isStorableKind(kind))
|
||||
continue;
|
||||
|
||||
RegisterClassKind classKind = rckGeneral; // FIX: get class kind from phi node kind.
|
||||
Uint32 nInputs = phiNode.nInputs();
|
||||
|
||||
PhiNodeInstruction& phiNodeInstruction = *new(pool) PhiNodeInstruction(&phiNode, pool, nInputs);
|
||||
|
||||
emitter.defineProducer(phiNode, phiNodeInstruction, 0, classKind, drLow);
|
||||
for (Uint32 whichInput = 0; whichInput < nInputs; whichInput++)
|
||||
emitter.useProducer(phiNode.nthInputVariable(whichInput), phiNodeInstruction, whichInput, classKind, drLow);
|
||||
|
||||
node.addPhiNodeInstruction(phiNodeInstruction);
|
||||
|
||||
if (isDoublewordKind(kind)) {
|
||||
PhiNodeInstruction& phiNodeInstruction = *new(pool) PhiNodeInstruction(&phiNode, pool, nInputs);
|
||||
|
||||
emitter.defineProducer(phiNode, phiNodeInstruction, 0, classKind, drHigh);
|
||||
for (Uint32 whichInput = 0; whichInput < nInputs; whichInput++)
|
||||
emitter.useProducer(phiNode.nthInputVariable(whichInput), phiNodeInstruction, whichInput, classKind, drHigh);
|
||||
|
||||
node.addPhiNodeInstruction(phiNodeInstruction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
|
||||
void RegisterAllocatorTools::printSpillCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
SpillCost* cost = registerAllocator.spillCost;
|
||||
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Spill costs:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\trange %d : ", i));
|
||||
if (cost[i].infinite)
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("infinite\n"));
|
||||
else
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("%f\n", cost[i].cost));
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterAllocatorTools::printSplitCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
SplitCost* cost = registerAllocator.splitCost;
|
||||
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("Split costs:\n"));
|
||||
for (Uint32 i = 1; i < rangeCount; i++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\trange %d : loads = %f stores = %f\n", i, cost[i].loads, cost[i].stores));
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterAllocatorTools::printInstructions(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
LogModuleObject log = UT_LOG_MODULE(RegAlloc);
|
||||
ControlNode** nodes = registerAllocator.controlGraph.dfsList;
|
||||
Uint32 nNodes = registerAllocator.controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("N%d:\n", n));
|
||||
|
||||
InstructionList& phiNodes = nodes[n]->getPhiNodeInstructions();
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
|
||||
if (!phiNodes.empty()) {
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" PhiNodes:\n", n));
|
||||
for(InstructionList::iterator i = phiNodes.begin(); !phiNodes.done(i); i = phiNodes.advance(i)) {
|
||||
phiNodes.get(i).printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
if (!instructions.empty())
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, (" Instructions:\n", n));
|
||||
}
|
||||
|
||||
for(InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
|
||||
instructions.get(i).printPretty(log);
|
||||
UT_OBJECTLOG(log, PR_LOG_ALWAYS, ("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
117
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.h
Normal file
117
mozilla/ef/Compiler/RegisterAllocator/RegisterAllocatorTools.h
Normal file
@@ -0,0 +1,117 @@
|
||||
// -*- mode:C++; tab-width:4; truncate-lines:t -*-
|
||||
//
|
||||
// CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF
|
||||
// NETSCAPE COMMUNICATIONS CORPORATION
|
||||
// Copyright © 1996, 1997 Netscape Communications Corporation. All Rights
|
||||
// Reserved. Use of this Source Code is subject to the terms of the
|
||||
// applicable license agreement from Netscape Communications Corporation.
|
||||
// The copyright notice(s) in this Source Code does not indicate actual or
|
||||
// intended publication of this Source Code.
|
||||
//
|
||||
// $Id: RegisterAllocatorTools.h,v 1.1.2.1 1999-03-02 16:12:05 fur%netscape.com Exp $
|
||||
//
|
||||
|
||||
#ifndef _REGISTER_ALLOCATOR_TOOLS_H_
|
||||
#define _REGISTER_ALLOCATOR_TOOLS_H_
|
||||
|
||||
#include "LogModule.h"
|
||||
#include "RegisterTypes.h"
|
||||
#include <string.h>
|
||||
|
||||
class RegisterAllocator;
|
||||
class ControlGraph;
|
||||
class InstructionEmitter;
|
||||
class VirtualRegisterManager;
|
||||
|
||||
struct RegisterAllocatorTools
|
||||
{
|
||||
//
|
||||
//
|
||||
static void insertPhiNodeInstructions(ControlGraph& controlGraph, InstructionEmitter& emitter);
|
||||
|
||||
//
|
||||
//
|
||||
static void updateInstructionGraph(RegisterAllocator& registerAllocator);
|
||||
|
||||
//
|
||||
//
|
||||
static void removeUnnecessaryCopies(RegisterAllocator& registerAllocator);
|
||||
|
||||
#ifdef DEBUG
|
||||
//
|
||||
//
|
||||
static void testTheInstructionGraph(ControlGraph& controlGraph, VirtualRegisterManager& vrManager);
|
||||
#endif // DEBUG
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
//
|
||||
//
|
||||
static void printInstructions(RegisterAllocator& registerAllocator);
|
||||
|
||||
//
|
||||
//
|
||||
static void printSpillCosts(RegisterAllocator& registerAllocator);
|
||||
|
||||
//
|
||||
//
|
||||
static void printSplitCosts(RegisterAllocator& registerAllocator);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
//
|
||||
// FIX: this should go in a class (LookupTable ?)
|
||||
//
|
||||
|
||||
inline RegisterName findRoot(RegisterName name, RegisterName* table)
|
||||
{
|
||||
RegisterName* stack = table;
|
||||
RegisterName* stackPtr = stack;
|
||||
|
||||
RegisterName newName;
|
||||
while((newName = table[name]) != name) {
|
||||
*--stackPtr = name;
|
||||
name = newName;
|
||||
}
|
||||
|
||||
while (stackPtr != stack)
|
||||
table[*stackPtr++] = name;
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
inline void init(RegisterName* table, Uint32 nameCount)
|
||||
{
|
||||
for (RegisterName r = RegisterName(0); r < nameCount; r = RegisterName(r + 1))
|
||||
table[r] = r;
|
||||
}
|
||||
|
||||
inline Uint32 compress(RegisterName* name2range, RegisterName* table, Uint32 nameCount, Uint32 tableSize)
|
||||
{
|
||||
RegisterName* liveRange = new RegisterName[tableSize];
|
||||
memset(liveRange, '\0', tableSize * sizeof(RegisterName));
|
||||
|
||||
// Update the lookup table.
|
||||
for (RegisterName r = RegisterName(1); r < tableSize; r = RegisterName(r + 1))
|
||||
findRoot(r, table);
|
||||
|
||||
// Count the liveranges.
|
||||
Uint32 liveRangeCount = 1;
|
||||
for (RegisterName s = RegisterName(1); s < tableSize; s = RegisterName(s + 1))
|
||||
if (table[s] == s)
|
||||
liveRange[s] = RegisterName(liveRangeCount++);
|
||||
|
||||
for (RegisterName t = RegisterName(1); t < nameCount; t = RegisterName(t + 1))
|
||||
name2range[t] = liveRange[table[name2range[t]]];
|
||||
|
||||
return liveRangeCount;
|
||||
}
|
||||
|
||||
inline double doLog10(Uint32 power)
|
||||
{
|
||||
double log = 1.0;
|
||||
while (power--)
|
||||
log *= 10.0;
|
||||
return log;
|
||||
}
|
||||
|
||||
#endif // _REGISTER_ALLOCATOR_TOOLS_H_
|
||||
38
mozilla/ef/Compiler/RegisterAllocator/RegisterAssigner.h
Normal file
38
mozilla/ef/Compiler/RegisterAllocator/RegisterAssigner.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_ASSIGNER_H_
|
||||
#define _REGISTER_ASSIGNER_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "VirtualRegister.h"
|
||||
|
||||
class FastBitMatrix;
|
||||
|
||||
class RegisterAssigner
|
||||
{
|
||||
protected:
|
||||
VirtualRegisterManager& vRegManager;
|
||||
|
||||
public:
|
||||
RegisterAssigner(VirtualRegisterManager& vrMan) : vRegManager(vrMan) {}
|
||||
|
||||
virtual bool assignRegisters(FastBitMatrix& interferenceMatrix) = 0;
|
||||
};
|
||||
|
||||
#endif /* _REGISTER_ASSIGNER_H_ */
|
||||
25
mozilla/ef/Compiler/RegisterAllocator/RegisterClass.h
Normal file
25
mozilla/ef/Compiler/RegisterAllocator/RegisterClass.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_CLASS_H_
|
||||
#define _REGISTER_CLASS_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "RegisterTypes.h"
|
||||
|
||||
#endif // _REGISTER_CLASS_H_
|
||||
37
mozilla/ef/Compiler/RegisterAllocator/RegisterPressure.h
Normal file
37
mozilla/ef/Compiler/RegisterAllocator/RegisterPressure.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_PRESSURE_H_
|
||||
#define _REGISTER_PRESSURE_H_
|
||||
|
||||
#include "BitSet.h"
|
||||
#include "HashSet.h"
|
||||
|
||||
struct LowRegisterPressure
|
||||
{
|
||||
typedef BitSet Set;
|
||||
static const bool setIsOrdered = true;
|
||||
};
|
||||
|
||||
struct HighRegisterPressure
|
||||
{
|
||||
typedef HashSet Set;
|
||||
static const bool setIsOrdered = false;
|
||||
};
|
||||
|
||||
#endif // _REGISTER_PRESSURE_H_
|
||||
104
mozilla/ef/Compiler/RegisterAllocator/RegisterTypes.h
Normal file
104
mozilla/ef/Compiler/RegisterAllocator/RegisterTypes.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _REGISTER_TYPES_H_
|
||||
#define _REGISTER_TYPES_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterName -
|
||||
//
|
||||
|
||||
enum RegisterName {
|
||||
rnInvalid = 0,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterClassKind -
|
||||
//
|
||||
|
||||
enum RegisterClassKind {
|
||||
rckInvalid = 0,
|
||||
rckGeneral,
|
||||
rckStackSlot,
|
||||
|
||||
nRegisterClassKind
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterID -
|
||||
//
|
||||
|
||||
enum RegisterID {
|
||||
invalidID = 0
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// RegisterKind -
|
||||
//
|
||||
|
||||
enum RegisterKind {
|
||||
rkCallerSave = 0,
|
||||
rkCalleeSave,
|
||||
};
|
||||
|
||||
struct NameLinkedList {
|
||||
RegisterName name;
|
||||
NameLinkedList* next;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
const registerNameMask = 0x03ffffff;
|
||||
const coloredRegisterMask = 0x04000000;
|
||||
const machineRegisterMask = 0x08000000;
|
||||
const registerClassMask = 0xf0000000;
|
||||
|
||||
const registerNameShift = 0;
|
||||
const coloredRegisterShift = 26;
|
||||
const machineRegisterShift = 27;
|
||||
const registerClassShift = 28;
|
||||
|
||||
#else // DEBUG
|
||||
|
||||
const registerNameMask = 0x0fffffff;
|
||||
const registerClassMask = 0xf0000000;
|
||||
|
||||
const registerNameShift = 0;
|
||||
const registerClassShift = 28;
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
|
||||
inline RegisterClassKind getClass(RegisterID registerID) {return RegisterClassKind((registerID & registerClassMask) >> registerClassShift);}
|
||||
inline RegisterName getName(RegisterID registerID) {return RegisterName((registerID & registerNameMask) >> registerNameShift);}
|
||||
inline void setClass(RegisterID& registerID, RegisterClassKind classKind) {registerID = RegisterID((registerID & ~registerClassMask) | ((classKind << registerClassShift) & registerClassMask));}
|
||||
inline void setName(RegisterID& registerID, RegisterName name) {assert((name & ~registerNameMask) == 0); registerID = RegisterID((registerID & ~registerNameMask) | ((name << registerNameShift) & registerNameMask));}
|
||||
inline RegisterID buildRegisterID(RegisterName name, RegisterClassKind classKind) {return RegisterID(((classKind << registerClassShift) & registerClassMask) | ((name << registerNameShift) & registerNameMask));}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
inline bool isMachineRegister(RegisterID rid) {return (rid & machineRegisterMask) != 0;}
|
||||
inline void setMachineRegister(RegisterID& rid) {rid = RegisterID(rid | machineRegisterMask);}
|
||||
inline bool isColoredRegister(RegisterID rid) {return (rid & coloredRegisterMask) != 0;}
|
||||
inline void setColoredRegister(RegisterID& rid) {rid = RegisterID(rid | coloredRegisterMask);}
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
#endif // _REGISTER_TYPES_H_
|
||||
32
mozilla/ef/Compiler/RegisterAllocator/SSATools.cpp
Normal file
32
mozilla/ef/Compiler/RegisterAllocator/SSATools.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/* -*- 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.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "SSATools.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "Liveness.h"
|
||||
|
||||
void replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager)
|
||||
{
|
||||
if (!controlGraph.hasBackEdges)
|
||||
return;
|
||||
|
||||
Liveness liveness(controlGraph.pool);
|
||||
liveness.buildLivenessAnalysis(controlGraph, vrManager);
|
||||
}
|
||||
29
mozilla/ef/Compiler/RegisterAllocator/SSATools.h
Normal file
29
mozilla/ef/Compiler/RegisterAllocator/SSATools.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _SSA_TOOLS_H_
|
||||
#define _SSA_TOOLS_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
|
||||
class ControlGraph;
|
||||
class VirtualRegisterManager;
|
||||
|
||||
extern void replacePhiNodes(ControlGraph& controlGraph, VirtualRegisterManager& vrManager);
|
||||
|
||||
#endif // _SSA_TOOLS_H_
|
||||
37
mozilla/ef/Compiler/RegisterAllocator/SparseSet.cpp
Normal file
37
mozilla/ef/Compiler/RegisterAllocator/SparseSet.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/* -*- 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.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "SparseSet.h"
|
||||
#include "BitSet.h"
|
||||
#include "Pool.h"
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the set.
|
||||
//
|
||||
void SparseSet::printPretty(LogModuleObject log)
|
||||
{
|
||||
Pool pool;
|
||||
BitSet set(pool, universeSize);
|
||||
|
||||
for (Uint32 i = 0; i < count; i++)
|
||||
set.set(node[i].element);
|
||||
|
||||
set.printPretty(log);
|
||||
}
|
||||
#endif // DEBUG_LOG
|
||||
168
mozilla/ef/Compiler/RegisterAllocator/SparseSet.h
Normal file
168
mozilla/ef/Compiler/RegisterAllocator/SparseSet.h
Normal file
@@ -0,0 +1,168 @@
|
||||
// -*- mode:C++; tab-width:4; truncate-lines:t -*-
|
||||
//
|
||||
// CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF
|
||||
// NETSCAPE COMMUNICATIONS CORPORATION
|
||||
// Copyright © 1996, 1997 Netscape Communications Corporation. All Rights
|
||||
// Reserved. Use of this Source Code is subject to the terms of the
|
||||
// applicable license agreement from Netscape Communications Corporation.
|
||||
// The copyright notice(s) in this Source Code does not indicate actual or
|
||||
// intended publication of this Source Code.
|
||||
//
|
||||
// $Id: SparseSet.h,v 1.1.2.1 1999-03-02 16:12:07 fur%netscape.com Exp $
|
||||
//
|
||||
|
||||
#ifndef _SPARSE_SET_H_
|
||||
#define _SPARSE_SET_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "Pool.h"
|
||||
#include "LogModule.h"
|
||||
#include "BitSet.h"
|
||||
|
||||
class SparseSet
|
||||
{
|
||||
private:
|
||||
|
||||
struct Node {
|
||||
Uint32 element;
|
||||
Uint32 stackIndex;
|
||||
};
|
||||
|
||||
Node* node;
|
||||
Uint32 count;
|
||||
Uint32 universeSize;
|
||||
|
||||
private:
|
||||
|
||||
// No copy constructor.
|
||||
SparseSet(const SparseSet&);
|
||||
|
||||
// Check if the given set's universe is of the same size than this universe.
|
||||
void checkUniverseCompatibility(const SparseSet& set) const {assert(set.universeSize == universeSize);}
|
||||
// Check if pos is valid for this set's universe.
|
||||
void checkMember(Int32 pos) const {assert(pos >=0 && Uint32(pos) < universeSize);}
|
||||
|
||||
public:
|
||||
|
||||
SparseSet(Pool& pool, Uint32 universeSize) : universeSize(universeSize) {node = new(pool) Node[universeSize]; clear();}
|
||||
|
||||
// Clear the sparse set.
|
||||
void clear() {count = 0;}
|
||||
// Clear the element at index.
|
||||
inline void clear(Uint32 index);
|
||||
// Set the element at index.
|
||||
inline void set(Uint32 index);
|
||||
// Return true if the element at index is set.
|
||||
inline bool test(Uint32 index) const;
|
||||
// Union with the given sparse set.
|
||||
inline void or(const SparseSet& set);
|
||||
// Intersection with the given sparse set.
|
||||
inline void and(const SparseSet& set);
|
||||
// Difference with the given sparse set.
|
||||
inline void difference(const SparseSet& set);
|
||||
// Copy set.
|
||||
inline SparseSet& operator = (const SparseSet& set);
|
||||
inline SparseSet& operator = (const BitSet& set);
|
||||
// Return true if the sparse sets are identical.
|
||||
friend bool operator == (const SparseSet& set1, const SparseSet& set2);
|
||||
// Return true if the sparse sets are different.
|
||||
friend bool operator != (const SparseSet& set1, const SparseSet& set2);
|
||||
|
||||
// Logical operators.
|
||||
SparseSet& operator |= (const SparseSet& set) {or(set); return *this;}
|
||||
SparseSet& operator &= (const SparseSet& set) {and(set); return *this;}
|
||||
SparseSet& operator -= (const SparseSet& set) {difference(set); return *this;}
|
||||
|
||||
// Iterator to conform with the set API.
|
||||
typedef Int32 iterator;
|
||||
// Return the iterator for the first element of this set.
|
||||
iterator begin() const {return count - 1;}
|
||||
// Return the next iterator.
|
||||
iterator advance(iterator pos) const {return --pos;}
|
||||
// Return true if the iterator is at the end of the set.
|
||||
bool done(iterator pos) const {return pos < 0;}
|
||||
// Return the element for the given iterator;
|
||||
Uint32 get(iterator pos) const {return node[pos].element;}
|
||||
// Return one element of this set.
|
||||
Uint32 getOne() const {assert(count > 0); return node[0].element;}
|
||||
// Return the size of this set.
|
||||
Uint32 getSize() const {return count;}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Print the set.
|
||||
void printPretty(LogModuleObject log);
|
||||
#endif // DEBUG_LOG
|
||||
};
|
||||
|
||||
inline void SparseSet::clear(Uint32 element)
|
||||
{
|
||||
checkMember(element);
|
||||
Uint32 count = this->count;
|
||||
Node* node = this->node;
|
||||
|
||||
Uint32 stackIndex = node[element].stackIndex;
|
||||
|
||||
if ((stackIndex < count) && (node[stackIndex].element == element)) {
|
||||
Uint32 stackTop = node[count - 1].element;
|
||||
|
||||
node[stackIndex].element = stackTop;
|
||||
node[stackTop].stackIndex = stackIndex;
|
||||
this->count = count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SparseSet::set(Uint32 element)
|
||||
{
|
||||
checkMember(element);
|
||||
Uint32 count = this->count;
|
||||
Node* node = this->node;
|
||||
|
||||
Uint32 stackIndex = node[element].stackIndex;
|
||||
|
||||
if ((stackIndex >= count) || (node[stackIndex].element != element)) {
|
||||
node[count].element = element;
|
||||
node[element].stackIndex = count;
|
||||
this->count = count + 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool SparseSet::test(Uint32 element) const
|
||||
{
|
||||
checkMember(element);
|
||||
Node* node = this->node;
|
||||
|
||||
Uint32 stackIndex = node[element].stackIndex;
|
||||
return ((stackIndex < count) && (node[stackIndex].element == element));
|
||||
}
|
||||
|
||||
inline SparseSet& SparseSet::operator = (const SparseSet& set)
|
||||
{
|
||||
checkUniverseCompatibility(set);
|
||||
Uint32 sourceCount = set.getSize();
|
||||
Node* node = this->node;
|
||||
|
||||
memcpy(node, set.node, sourceCount * sizeof(Node));
|
||||
|
||||
for (Uint32 i = 0; i < sourceCount; i++) {
|
||||
Uint32 element = node[i].element;
|
||||
node[element].stackIndex = i;
|
||||
}
|
||||
|
||||
count = sourceCount;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
inline SparseSet& SparseSet::operator = (const BitSet& set)
|
||||
{
|
||||
// FIX: there's room for optimization here.
|
||||
assert(universeSize == set.getSize());
|
||||
|
||||
clear();
|
||||
for (Int32 i = set.firstOne(); i != -1; i = set.nextOne(i))
|
||||
this->set(i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif // _SPARSE_SET_H_
|
||||
270
mozilla/ef/Compiler/RegisterAllocator/Spilling.cpp
Normal file
270
mozilla/ef/Compiler/RegisterAllocator/Spilling.cpp
Normal file
@@ -0,0 +1,270 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef NEW_LAURENTM_CODE
|
||||
#define INCLUDE_EMITTER
|
||||
#include "CpuInfo.h"
|
||||
#include "Fundamentals.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "InstructionEmitter.h"
|
||||
#include "Spilling.h"
|
||||
|
||||
|
||||
void Spilling::
|
||||
insertSpillCode(ControlNode** dfsList, Uint32 nNodes)
|
||||
{
|
||||
PRUint32 nVirtualRegisters = vRegManager.count();
|
||||
FastBitSet currentLive(vRegManager.pool, nVirtualRegisters);
|
||||
FastBitSet usedInThisInstruction(vRegManager.pool, nVirtualRegisters);
|
||||
RegisterFifo grNeedLoad(nVirtualRegisters);
|
||||
RegisterFifo fpNeedLoad(nVirtualRegisters);
|
||||
|
||||
for (PRInt32 n = nNodes - 1; n >= 0; n--)
|
||||
{
|
||||
PR_ASSERT(grNeedLoad.empty() & fpNeedLoad.empty());
|
||||
ControlNode& node = *dfsList[n];
|
||||
|
||||
currentLive = node.liveAtEnd;
|
||||
|
||||
PRUint32 nGeneralAlive = 0;
|
||||
PRUint32 nFloatingPointAlive = 0;
|
||||
|
||||
// Get the number of registers alive at the end of this node.
|
||||
for (PRInt32 j = currentLive.firstOne(); j != -1; j = currentLive.nextOne(j))
|
||||
{
|
||||
VirtualRegister& vReg = vRegManager.getVirtualRegister(j);
|
||||
if (vReg.spillInfo.willSpill)
|
||||
{
|
||||
currentLive.clear(j);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
nGeneralAlive++;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
nFloatingPointAlive++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if(node.dfsNum == 8) printf("\n________Begin Node %d________\n", node.dfsNum);
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i))
|
||||
{
|
||||
Instruction& instruction = instructions.get(i);
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* defPtr;
|
||||
|
||||
// if(node.dfsNum == 8) { printf("\n");
|
||||
// instruction.printPretty(stdout);
|
||||
// printf("\n"); }
|
||||
|
||||
// Handle definitions
|
||||
for (defPtr = defBegin; defPtr < defEnd; defPtr++)
|
||||
if (defPtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = defPtr->getVirtualRegister();
|
||||
currentLive.clear(vReg.getRegisterIndex());
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
nGeneralAlive--;
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
nFloatingPointAlive--;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for deaths
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = usePtr->getVirtualRegister();
|
||||
if (!currentLive.test(vReg.getRegisterIndex()))
|
||||
// This is the last use of this register.
|
||||
{
|
||||
currentLive.set(vReg.getRegisterIndex());
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
nGeneralAlive++;
|
||||
while (/*(nGeneralAlive > NUMBER_OF_GREGISTERS) &&*/ !grNeedLoad.empty())
|
||||
{
|
||||
PRUint32 toLoad = grNeedLoad.get();
|
||||
currentLive.clear(toLoad);
|
||||
nGeneralAlive--;
|
||||
|
||||
VirtualRegister& nReg = vRegManager.getVirtualRegister(toLoad);
|
||||
Instruction& lastUsingInstruction = *nReg.spillInfo.lastUsingInstruction;
|
||||
emitter.emitLoadAfter(*lastUsingInstruction.getPrimitive(), lastUsingInstruction.getLinks().prev,
|
||||
nReg.getAlias(), *nReg.equivalentRegister[vrcStackSlot]);
|
||||
nReg.releaseSelf();
|
||||
}
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
nFloatingPointAlive++;
|
||||
while (/*(nFloatingPointAlive > NUMBER_OF_FPREGISTERS) &&*/ !fpNeedLoad.empty())
|
||||
{
|
||||
PRUint32 toLoad = fpNeedLoad.get();
|
||||
currentLive.clear(toLoad);
|
||||
nFloatingPointAlive--;
|
||||
|
||||
VirtualRegister& nReg = vRegManager.getVirtualRegister(toLoad);
|
||||
Instruction& lastUsingInstruction = *nReg.spillInfo.lastUsingInstruction;
|
||||
emitter.emitLoadAfter(*lastUsingInstruction.getPrimitive(), lastUsingInstruction.getLinks().prev,
|
||||
nReg.getAlias(), *nReg.equivalentRegister[vrcStackSlot]);
|
||||
nReg.releaseSelf();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle uses
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = usePtr->getVirtualRegister();
|
||||
PRUint32 registerIndex = vReg.getRegisterIndex();
|
||||
|
||||
if (vReg.spillInfo.willSpill) {
|
||||
#if defined(GENERATE_FOR_X86)
|
||||
if (!instruction.switchUseToSpill((usePtr - useBegin), *vReg.equivalentRegister[vrcStackSlot]))
|
||||
#endif
|
||||
{
|
||||
switch (vReg.getClass())
|
||||
{
|
||||
case vrcInteger:
|
||||
if (!grNeedLoad.test(registerIndex))
|
||||
{
|
||||
grNeedLoad.put(registerIndex);
|
||||
VirtualRegister& alias = vRegManager.newVirtualRegister(vrcInteger);
|
||||
if (vReg.isPreColored())
|
||||
alias.preColorRegister(vReg.getPreColor());
|
||||
/* if (vReg.hasSpecialInterference) {
|
||||
alias.specialInterference.sizeTo(NUMBER_OF_REGISTERS);
|
||||
alias.specialInterference = vReg.specialInterference;
|
||||
alias.hasSpecialInterference = true;
|
||||
} */
|
||||
vReg.setAlias(alias);
|
||||
vReg.retainSelf();
|
||||
}
|
||||
break;
|
||||
case vrcFloatingPoint:
|
||||
case vrcFixedPoint:
|
||||
if (!fpNeedLoad.test(registerIndex))
|
||||
{
|
||||
fpNeedLoad.put(registerIndex);
|
||||
VirtualRegister& alias = vRegManager.newVirtualRegister(vReg.getClass());
|
||||
if (vReg.isPreColored())
|
||||
alias.preColorRegister(vReg.getPreColor());
|
||||
/*if (vReg.hasSpecialInterference) {
|
||||
alias.specialInterference.sizeTo(NUMBER_OF_REGISTERS);
|
||||
alias.specialInterference = vReg.specialInterference;
|
||||
alias.hasSpecialInterference = true;
|
||||
} */
|
||||
vReg.setAlias(alias);
|
||||
vReg.retainSelf();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
usePtr->getVirtualRegisterPtr().initialize(vReg.getAlias());
|
||||
usedInThisInstruction.set(registerIndex);
|
||||
vReg.spillInfo.lastUsingInstruction = &instruction;
|
||||
}
|
||||
currentLive.clear(registerIndex);
|
||||
} else { // will not spill
|
||||
currentLive.set(registerIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle definitions
|
||||
for (defPtr = defBegin; defPtr < defEnd; defPtr++)
|
||||
if (defPtr->isVirtualRegister())
|
||||
{
|
||||
VirtualRegister& vReg = defPtr->getVirtualRegister();
|
||||
|
||||
if (vReg.spillInfo.willSpill)
|
||||
#if defined(GENERATE_FOR_X86)
|
||||
if (!instruction.switchDefineToSpill((defPtr - defBegin), *vReg.equivalentRegister[vrcStackSlot]))
|
||||
#endif
|
||||
{
|
||||
if (usedInThisInstruction.test(vReg.getRegisterIndex()))
|
||||
// this virtualRegister was used in this instruction and is also defined. We need to move
|
||||
// this virtual register to its alias first and then save it to memory.
|
||||
{
|
||||
emitter.emitStoreAfter(*instruction.getPrimitive(), &instruction.getLinks(),
|
||||
vReg.getAlias(), *vReg.equivalentRegister[vrcStackSlot]);
|
||||
defPtr->getVirtualRegisterPtr().initialize(vReg.getAlias());
|
||||
}
|
||||
else
|
||||
{
|
||||
emitter.emitStoreAfter(*instruction.getPrimitive(), &instruction.getLinks(),
|
||||
vReg, *vReg.equivalentRegister[vrcStackSlot]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!grNeedLoad.empty())
|
||||
{
|
||||
PRUint32 nl = grNeedLoad.get();
|
||||
VirtualRegister& nlReg = vRegManager.getVirtualRegister(nl);
|
||||
Instruction& lastUse = *nlReg.spillInfo.lastUsingInstruction;
|
||||
|
||||
emitter.emitLoadAfter(*lastUse.getPrimitive(), lastUse.getLinks().prev,
|
||||
nlReg.getAlias(), *nlReg.equivalentRegister[vrcStackSlot]);
|
||||
nlReg.releaseSelf();
|
||||
}
|
||||
while (!fpNeedLoad.empty())
|
||||
{
|
||||
PRUint32 nl = fpNeedLoad.get();
|
||||
VirtualRegister& nlReg = vRegManager.getVirtualRegister(nl);
|
||||
Instruction& lastUse = *nlReg.spillInfo.lastUsingInstruction;
|
||||
|
||||
emitter.emitLoadAfter(*lastUse.getPrimitive(), lastUse.getLinks().prev,
|
||||
nlReg.getAlias(), *nlReg.equivalentRegister[vrcStackSlot]);
|
||||
nlReg.releaseSelf();
|
||||
}
|
||||
|
||||
// if(node.dfsNum == 8) printf("\n________End Node %d________\n", node.dfsNum);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
269
mozilla/ef/Compiler/RegisterAllocator/Spilling.h
Normal file
269
mozilla/ef/Compiler/RegisterAllocator/Spilling.h
Normal file
@@ -0,0 +1,269 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _SPILLING_H_
|
||||
#define _SPILLING_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "SparseSet.h"
|
||||
|
||||
template <class RegisterPressure>
|
||||
class Spilling
|
||||
{
|
||||
private:
|
||||
static void insertStoreAfter(Instruction& instruction, RegisterName name);
|
||||
static void insertLoadBefore(Instruction& instruction, RegisterName name);
|
||||
|
||||
public:
|
||||
static void calculateSpillCosts(RegisterAllocator& registerAllocator);
|
||||
static void insertSpillCode(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
struct SpillCost
|
||||
{
|
||||
double loads;
|
||||
double stores;
|
||||
double copies;
|
||||
double cost;
|
||||
bool infinite;
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::insertSpillCode(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet currentLive(pool, rangeCount);
|
||||
SparseSet needLoad(pool, rangeCount);
|
||||
SparseSet mustSpill(pool, rangeCount);
|
||||
SparseSet& willSpill = *registerAllocator.willSpill;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
|
||||
needLoad.clear();
|
||||
currentLive = liveOut[n];
|
||||
mustSpill = currentLive;
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i);) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
i = instructions.retreat(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
bool foundLiveDefine = false;
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
if (currentLive.test(name2range[definePtr->getRegisterName()])) {
|
||||
foundLiveDefine = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
foundLiveDefine = true;
|
||||
break;
|
||||
}
|
||||
if (defineBegin != defineEnd && !foundLiveDefine) {
|
||||
fprintf(stderr, "!!! Removed instruction because it was only defining unused registers !!!\n");
|
||||
instruction.remove();
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName range = name2range[definePtr->getRegisterName()];
|
||||
#ifdef DEBUG
|
||||
if (needLoad.test(range))
|
||||
if (!mustSpill.test(range) && registerAllocator.spillCost[range].infinite && willSpill.test(range)) {
|
||||
fprintf(stderr, "Tried to spill a register with infinite spill cost\n");
|
||||
abort();
|
||||
}
|
||||
#endif // DEBUG
|
||||
if (willSpill.test(range))
|
||||
insertStoreAfter(instruction, range);
|
||||
|
||||
needLoad.clear(range);
|
||||
}
|
||||
|
||||
if (instruction.getFlags() & ifCopy)
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
if (!currentLive.test(range))
|
||||
for (SparseSet::iterator r = needLoad.begin(); !needLoad.done(r); r = needLoad.advance(r)) {
|
||||
RegisterName load = RegisterName(needLoad.get(r));
|
||||
if (willSpill.test(load))
|
||||
insertLoadBefore(instruction, load);
|
||||
mustSpill.set(load);
|
||||
}
|
||||
needLoad.clear();
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
currentLive.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
currentLive.set(range);
|
||||
needLoad.set(range);
|
||||
}
|
||||
}
|
||||
|
||||
for (SparseSet::iterator l = needLoad.begin(); !needLoad.done(l); l = needLoad.advance(l)) {
|
||||
RegisterName load = RegisterName(needLoad.get(l));
|
||||
if (willSpill.test(load))
|
||||
insertLoadBefore(instructions.first(), load);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::insertLoadBefore(Instruction& /*instruction*/, RegisterName name)
|
||||
{
|
||||
fprintf(stdout, "will insert load for range %d\n", name);
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::insertStoreAfter(Instruction& /*instruction*/, RegisterName name)
|
||||
{
|
||||
fprintf(stdout, "will insert store for range %d\n", name);
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Spilling<RegisterPressure>::calculateSpillCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
Pool& pool = registerAllocator.pool;
|
||||
SparseSet live(pool, rangeCount);
|
||||
SparseSet needLoad(pool, rangeCount);
|
||||
SparseSet mustSpill(pool, rangeCount);
|
||||
|
||||
SparseSet alreadyStored(pool, rangeCount); // FIX: should get this from previous spilling.
|
||||
|
||||
SpillCost* cost = new SpillCost[rangeCount];
|
||||
memset(cost, '\0', rangeCount * sizeof(SpillCost));
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
|
||||
double weight = doLog10(node.loopDepth);
|
||||
|
||||
needLoad.clear();
|
||||
live = liveOut[n];
|
||||
mustSpill = live;
|
||||
|
||||
InstructionList& instructions = nodes[n]->getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister()) {
|
||||
RegisterName range = name2range[definePtr->getRegisterName()];
|
||||
|
||||
if (needLoad.test(range))
|
||||
if (!mustSpill.test(range))
|
||||
cost[range].infinite = true;
|
||||
|
||||
if ((false /* !rematerializable(range) */ || !needLoad.test(range)) && !alreadyStored.test(range))
|
||||
cost[range].stores += weight;
|
||||
|
||||
needLoad.clear(range);
|
||||
}
|
||||
|
||||
if (instruction.getFlags() & ifCopy)
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
if (!live.test(name2range[usePtr->getRegisterName()])) {
|
||||
for (SparseSet::iterator l = needLoad.begin(); !needLoad.done(l); l = needLoad.advance(l)) {
|
||||
Uint32 range = needLoad.get(l);
|
||||
cost[range].loads += weight;
|
||||
mustSpill.set(range);
|
||||
}
|
||||
needLoad.clear();
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
live.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
|
||||
live.set(range);
|
||||
needLoad.set(range);
|
||||
}
|
||||
|
||||
if (instruction.getFlags() & ifCopy) {
|
||||
assert(useBegin != useEnd && useBegin[0].isRegister());
|
||||
assert(defineBegin != defineEnd && defineBegin[0].isRegister());
|
||||
|
||||
RegisterName source = name2range[useBegin[0].getRegisterName()];
|
||||
RegisterName destination = name2range[defineBegin[0].getRegisterName()];
|
||||
|
||||
cost[source].copies += weight;
|
||||
cost[destination].copies += weight;
|
||||
}
|
||||
}
|
||||
|
||||
for (SparseSet::iterator s = needLoad.begin(); !needLoad.done(s); s = needLoad.advance(s))
|
||||
cost[needLoad.get(s)].loads += weight;
|
||||
}
|
||||
|
||||
for (Uint32 r = 0; r < rangeCount; r++) {
|
||||
SpillCost& c = cost[r];
|
||||
c.cost = 2 * (c.loads + c.stores) - c.copies;
|
||||
}
|
||||
|
||||
registerAllocator.spillCost = cost;
|
||||
}
|
||||
|
||||
#endif // _SPILLING_H_
|
||||
239
mozilla/ef/Compiler/RegisterAllocator/Splits.h
Normal file
239
mozilla/ef/Compiler/RegisterAllocator/Splits.h
Normal file
@@ -0,0 +1,239 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _SPLITS_H_
|
||||
#define _SPLITS_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include <string.h>
|
||||
#include "Pool.h"
|
||||
#include "ControlGraph.h"
|
||||
#include "ControlNodes.h"
|
||||
#include "Instruction.h"
|
||||
#include "RegisterAllocator.h"
|
||||
#include "RegisterAllocatorTools.h"
|
||||
|
||||
UT_EXTERN_LOG_MODULE(RegAlloc);
|
||||
|
||||
template <class RegisterPressure>
|
||||
struct Splits
|
||||
{
|
||||
static void calculateSplitCosts(RegisterAllocator& registerAllocator);
|
||||
static bool findSplit(RegisterAllocator& registerAllocator, RegisterName* color, RegisterName range);
|
||||
static void insertSplitCode(RegisterAllocator& registerAllocator);
|
||||
};
|
||||
|
||||
struct SplitCost
|
||||
{
|
||||
double loads;
|
||||
double stores;
|
||||
};
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Splits<RegisterPressure>::insertSplitCode(RegisterAllocator& /*registerAllocator*/)
|
||||
{
|
||||
// FIX
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
bool Splits<RegisterPressure>::findSplit(RegisterAllocator& registerAllocator, RegisterName* color, RegisterName range)
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
NameLinkedList** neighborsWithColor = new(pool) NameLinkedList*[6]; // FIX
|
||||
memset(neighborsWithColor, '\0', 6 * sizeof(NameLinkedList*));
|
||||
|
||||
InterferenceGraph<RegisterPressure>& iGraph = registerAllocator.iGraph;
|
||||
|
||||
for (InterferenceVector* vector = iGraph.getInterferenceVector(range); vector != NULL; vector = vector->next)
|
||||
for (Int32 i = vector->count - 1; i >=0; --i) {
|
||||
RegisterName neighbor = vector->neighbors[i];
|
||||
RegisterName c = color[neighbor];
|
||||
|
||||
if (c < 6) { // FIX
|
||||
NameLinkedList* node = new(pool) NameLinkedList();
|
||||
node->name = neighbor;
|
||||
node->next = neighborsWithColor[c];
|
||||
neighborsWithColor[c] = node;
|
||||
}
|
||||
}
|
||||
|
||||
bool splitAroundName = true;
|
||||
|
||||
LiveRangeGraph<RegisterPressure>& lGraph = registerAllocator.lGraph;
|
||||
RegisterName bestColor = RegisterName(6); // FIX
|
||||
double bestCost = registerAllocator.spillCost[range].cost;
|
||||
SplitCost* splitCost = registerAllocator.splitCost;
|
||||
|
||||
for (RegisterName i = RegisterName(0); i < 6; i = RegisterName(i + 1)) { // FIX
|
||||
|
||||
double splitAroundNameCost = 0.0;
|
||||
bool canSplitAroundName = true;
|
||||
|
||||
SplitCost& sCost = splitCost[range];
|
||||
double addedCost = 2.0 * (sCost.stores + sCost.loads);
|
||||
|
||||
for (NameLinkedList* node = neighborsWithColor[i]; node != NULL; node = node->next) {
|
||||
RegisterName neighbor = node->name;
|
||||
if (lGraph.haveEdge(neighbor, range)) {
|
||||
canSplitAroundName = false;
|
||||
break;
|
||||
} else
|
||||
splitAroundNameCost += addedCost;
|
||||
}
|
||||
if (canSplitAroundName && splitAroundNameCost < bestCost) {
|
||||
bestCost = splitAroundNameCost;
|
||||
bestColor = i;
|
||||
splitAroundName = true;
|
||||
}
|
||||
|
||||
double splitAroundColorCost = 0.0;
|
||||
bool canSplitAroundColor = true;
|
||||
|
||||
for (NameLinkedList* node = neighborsWithColor[i]; node != NULL; node = node->next) {
|
||||
RegisterName neighbor = node->name;
|
||||
if (lGraph.haveEdge(range, neighbor)) {
|
||||
canSplitAroundColor = false;
|
||||
break;
|
||||
} else {
|
||||
SplitCost& sCost = splitCost[neighbor];
|
||||
double addedCost = 2.0 * (sCost.stores + sCost.loads);
|
||||
splitAroundColorCost += addedCost;
|
||||
}
|
||||
}
|
||||
if (canSplitAroundColor && splitAroundColorCost < bestCost) {
|
||||
bestCost = splitAroundColorCost;
|
||||
bestColor = i;
|
||||
splitAroundName = false;
|
||||
}
|
||||
}
|
||||
if (bestColor < RegisterName(6)) {
|
||||
color[range] = bestColor;
|
||||
registerAllocator.splitFound = true;
|
||||
|
||||
NameLinkedList** splitAround = registerAllocator.splitAround;
|
||||
|
||||
if (splitAroundName)
|
||||
for (NameLinkedList* node = neighborsWithColor[bestColor]; node != NULL; node = node->next) {
|
||||
NameLinkedList* newNode = new(pool) NameLinkedList();
|
||||
newNode->name = node->name;
|
||||
newNode->next = splitAround[range];
|
||||
splitAround[range] = newNode;
|
||||
}
|
||||
else
|
||||
for (NameLinkedList* node = neighborsWithColor[bestColor]; node != NULL; node = node->next) {
|
||||
NameLinkedList* newNode = new(pool) NameLinkedList();
|
||||
RegisterName neighbor = node->name;
|
||||
newNode->name = range;
|
||||
newNode->next = splitAround[neighbor];
|
||||
splitAround[neighbor] = newNode;
|
||||
}
|
||||
|
||||
trespass("Found a split");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class RegisterPressure>
|
||||
void Splits<RegisterPressure>::calculateSplitCosts(RegisterAllocator& registerAllocator)
|
||||
{
|
||||
Pool& pool = registerAllocator.pool;
|
||||
Uint32 rangeCount = registerAllocator.rangeCount;
|
||||
RegisterName* name2range = registerAllocator.name2range;
|
||||
|
||||
SplitCost* splitCost = new(pool) SplitCost[rangeCount];
|
||||
memset(splitCost, '\0', rangeCount * sizeof(SplitCost));
|
||||
|
||||
SparseSet live(pool, rangeCount);
|
||||
RegisterPressure::Set* liveIn = registerAllocator.liveness.liveIn;
|
||||
RegisterPressure::Set* liveOut = registerAllocator.liveness.liveOut;
|
||||
|
||||
ControlGraph& controlGraph = registerAllocator.controlGraph;
|
||||
ControlNode** nodes = controlGraph.dfsList;
|
||||
Uint32 nNodes = controlGraph.nNodes;
|
||||
|
||||
for (Uint32 n = 0; n < nNodes; n++) {
|
||||
ControlNode& node = *nodes[n];
|
||||
double weight = doLog10(node.loopDepth);
|
||||
|
||||
live = liveOut[n];
|
||||
|
||||
ControlEdge* successorsEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorsPtr = node.getSuccessorsBegin(); successorsPtr < successorsEnd; successorsPtr++) {
|
||||
ControlNode& successor = successorsPtr->getTarget();
|
||||
|
||||
if (successor.getControlKind() != ckEnd) {
|
||||
RegisterPressure::Set& successorLiveIn = liveIn[successor.dfsNum];
|
||||
|
||||
for (SparseSet::iterator i = live.begin(); !live.done(i); i = live.advance(i)) {
|
||||
RegisterName name = RegisterName(live.get(i));
|
||||
if (!successorLiveIn.test(name))
|
||||
splitCost[name].loads += doLog10(successor.loopDepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InstructionList& instructions = node.getInstructions();
|
||||
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i)) {
|
||||
Instruction& instruction = instructions.get(i);
|
||||
|
||||
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
||||
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
||||
InstructionUse* usePtr;
|
||||
InstructionDefine* defineBegin = instruction.getInstructionDefineBegin();
|
||||
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
|
||||
InstructionDefine* definePtr;
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
splitCost[name2range[definePtr->getRegisterName()]].stores += weight;
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister()) {
|
||||
RegisterName range = name2range[usePtr->getRegisterName()];
|
||||
if (!live.test(range)) {
|
||||
if (&instruction != &instructions.last())
|
||||
splitCost[range].loads += weight;
|
||||
else {
|
||||
ControlEdge* successorsEnd = node.getSuccessorsEnd();
|
||||
for (ControlEdge* successorsPtr = node.getSuccessorsBegin(); successorsPtr < successorsEnd; successorsPtr++)
|
||||
splitCost[range].loads += doLog10(successorsPtr->getTarget().loopDepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (definePtr = defineBegin; definePtr < defineEnd; definePtr++)
|
||||
if (definePtr->isRegister())
|
||||
live.clear(name2range[definePtr->getRegisterName()]);
|
||||
|
||||
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
||||
if (usePtr->isRegister())
|
||||
live.set(name2range[usePtr->getRegisterName()]);
|
||||
}
|
||||
}
|
||||
|
||||
NameLinkedList** splitAround = new(pool) NameLinkedList*[rangeCount];
|
||||
memset(splitAround, '\0', rangeCount * sizeof(NameLinkedList*));
|
||||
registerAllocator.splitAround = splitAround;
|
||||
|
||||
registerAllocator.splitCost = splitCost;
|
||||
registerAllocator.splitFound = false;
|
||||
}
|
||||
|
||||
#endif // _SPLITS_H_
|
||||
186
mozilla/ef/Compiler/RegisterAllocator/Timer.cpp
Normal file
186
mozilla/ef/Compiler/RegisterAllocator/Timer.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
/* -*- 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.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "HashTable.h"
|
||||
#include "Timer.h"
|
||||
#include "Pool.h"
|
||||
|
||||
static Pool pool; // Pool for the Timer class.
|
||||
static HashTable<TimerEntry*> timerEntries(pool); // Timers hashtable.
|
||||
|
||||
const nTimersInABlock = 128; // Number of timers in a block.
|
||||
static PRTime *timers = new(pool) PRTime[nTimersInABlock]; // A block of timers.
|
||||
static Uint8 nextTimer = 0; // nextAvailableTimer.
|
||||
|
||||
//
|
||||
// Calibrate the call to PR_Now().
|
||||
//
|
||||
static PRTime calibrate()
|
||||
{
|
||||
PRTime t = PR_Now();
|
||||
PRTime& a = *new(pool) PRTime();
|
||||
|
||||
// Call 10 times the PR_Now() function.
|
||||
a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now();
|
||||
a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now(); a = PR_Now();
|
||||
t = (PR_Now() - t + 9) / 10;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static PRTime adjust = calibrate();
|
||||
|
||||
//
|
||||
// Return the named timer..
|
||||
//
|
||||
TimerEntry& Timer::getTimerEntry(const char* name)
|
||||
{
|
||||
if (!timerEntries.exists(name)) {
|
||||
TimerEntry* newEntry = new(pool) TimerEntry();
|
||||
newEntry->accumulator = 0;
|
||||
newEntry->running = false;
|
||||
timerEntries.add(name, newEntry);
|
||||
}
|
||||
|
||||
return *timerEntries[name];
|
||||
}
|
||||
|
||||
//
|
||||
// Return a reference to a new timer.
|
||||
//
|
||||
PRTime& Timer::getNewTimer()
|
||||
{
|
||||
if (nextTimer >= nTimersInABlock) {
|
||||
timers = new(pool) PRTime[nTimersInABlock];
|
||||
nextTimer = 0;
|
||||
}
|
||||
return timers[nextTimer++];
|
||||
}
|
||||
|
||||
static Uint32 timersAreFrozen = 0;
|
||||
|
||||
//
|
||||
// Start the named timer.
|
||||
//
|
||||
void Timer::start(const char* name)
|
||||
{
|
||||
if (timersAreFrozen)
|
||||
return;
|
||||
|
||||
freezeTimers();
|
||||
|
||||
TimerEntry& timer = getTimerEntry(name);
|
||||
PR_ASSERT(!timer.running);
|
||||
|
||||
timer.accumulator = 0;
|
||||
timer.running = true;
|
||||
timer.done = false;
|
||||
|
||||
unfreezeTimers();
|
||||
}
|
||||
|
||||
//
|
||||
// Stop the named timer.
|
||||
//
|
||||
void Timer::stop(const char* name)
|
||||
{
|
||||
if (timersAreFrozen)
|
||||
return;
|
||||
|
||||
freezeTimers();
|
||||
|
||||
TimerEntry& timer = getTimerEntry(name);
|
||||
PR_ASSERT(timer.running);
|
||||
timer.running = false;
|
||||
timer.done = true;
|
||||
|
||||
unfreezeTimers();
|
||||
}
|
||||
|
||||
//
|
||||
// Freeze all the running timers.
|
||||
//
|
||||
void Timer::freezeTimers()
|
||||
{
|
||||
PRTime when = PR_Now() - adjust;
|
||||
|
||||
if (timersAreFrozen == 0) {
|
||||
Vector<TimerEntry*> entries = timerEntries;
|
||||
Uint32 count = entries.size();
|
||||
|
||||
for (Uint32 i = 0; i < count; i++) {
|
||||
TimerEntry& entry = *entries[i];
|
||||
if (entry.running) {
|
||||
entry.accumulator += (when - *entry.startTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
timersAreFrozen++;
|
||||
}
|
||||
|
||||
//
|
||||
// Unfreeze all the running timers.
|
||||
//
|
||||
void Timer::unfreezeTimers()
|
||||
{
|
||||
PR_ASSERT(timersAreFrozen != 0);
|
||||
timersAreFrozen--;
|
||||
|
||||
if (timersAreFrozen == 0) {
|
||||
Vector<TimerEntry *> entries = timerEntries;
|
||||
Uint32 count = entries.size();
|
||||
|
||||
PRTime& newStart = getNewTimer();
|
||||
|
||||
for (Uint32 i = 0; i < count; i++) {
|
||||
TimerEntry& entry = *entries[i];
|
||||
if (entry.running) {
|
||||
entry.startTime = &newStart;
|
||||
}
|
||||
}
|
||||
|
||||
newStart = PR_Now();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Print the named timer in the file f.
|
||||
//
|
||||
void Timer::print(FILE* f, const char *name)
|
||||
{
|
||||
if (timersAreFrozen)
|
||||
return;
|
||||
|
||||
freezeTimers();
|
||||
|
||||
TimerEntry& timer = getTimerEntry(name);
|
||||
|
||||
PR_ASSERT(timer.done);
|
||||
PRTime elapsed = timer.accumulator;
|
||||
|
||||
if (elapsed >> 32) {
|
||||
fprintf(f, "[timer %s out of range]\n", name);
|
||||
} else {
|
||||
fprintf(f, "[%dus in %s]\n", Uint32(elapsed), name);
|
||||
}
|
||||
fflush(f);
|
||||
|
||||
unfreezeTimers();
|
||||
}
|
||||
|
||||
80
mozilla/ef/Compiler/RegisterAllocator/Timer.h
Normal file
80
mozilla/ef/Compiler/RegisterAllocator/Timer.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _TIMER_H_
|
||||
#define _TIMER_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "HashTable.h"
|
||||
#include "prtime.h"
|
||||
|
||||
//
|
||||
// Naming convention:
|
||||
// As the class Timer contains only static methods, the timer's name should start with the
|
||||
// module name. Otherwise starting 2 timers with the same name will assert.
|
||||
//
|
||||
|
||||
#ifndef NO_TIMER
|
||||
|
||||
struct TimerEntry
|
||||
{
|
||||
PRTime *startTime; // Current time when we start the timer.
|
||||
PRTime accumulator; // Time spent in this timer.
|
||||
bool running; // True if the timer is running.
|
||||
bool done; // True if the timer was running and was stopped.
|
||||
};
|
||||
|
||||
class Timer
|
||||
{
|
||||
private:
|
||||
|
||||
// Return the named timer.
|
||||
static TimerEntry& getTimerEntry(const char* name);
|
||||
// Return a reference to a new Timer.
|
||||
static PRTime& getNewTimer();
|
||||
|
||||
public:
|
||||
|
||||
// Start the timer.
|
||||
static void start(const char* name);
|
||||
// Stop the timer.
|
||||
static void stop(const char* name);
|
||||
// Freeze all the running timers.
|
||||
static void freezeTimers();
|
||||
// Unfreeze all the running timers.
|
||||
static void unfreezeTimers();
|
||||
// Print the timer.
|
||||
static void print(FILE* f, const char *name);
|
||||
};
|
||||
|
||||
inline void startTimer(const char* name) {Timer::start(name);}
|
||||
inline void stopTimer(const char* name) {Timer::stop(name); Timer::print(stdout, name);}
|
||||
#define START_TIMER_SAFE Timer::freezeTimers();
|
||||
#define END_TIMER_SAFE Timer::unfreezeTimers();
|
||||
#define TIMER_SAFE(x) START_TIMER_SAFE x; END_TIMER_SAFE
|
||||
|
||||
#else /* NO_TIMER */
|
||||
|
||||
inline void startTimer(const char* /*name*/) {}
|
||||
inline void stopTimer(const char* /*name*/) {}
|
||||
#define START_TIMER_SAFE
|
||||
#define END_TIMER_SAFE
|
||||
#define TIMER_SAFE(x) x;
|
||||
|
||||
#endif /* NO_TIMER */
|
||||
#endif /* _TIMER_H_ */
|
||||
40
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.cpp
Normal file
40
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
/* -*- 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.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "VirtualRegister.h"
|
||||
#include "Instruction.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// VirtualRegister -
|
||||
|
||||
#ifdef MANUAL_TEMPLATES
|
||||
template class IndexedPool<VirtualRegister>;
|
||||
#endif
|
||||
|
||||
// Set the defining instruction.
|
||||
//
|
||||
void VirtualRegister::setDefiningInstruction(Instruction& instruction)
|
||||
{
|
||||
if (definingInstruction != NULL) {
|
||||
if ((instruction.getFlags() & ifCopy) && (definingInstruction->getFlags() & ifPhiNode))
|
||||
return;
|
||||
}
|
||||
definingInstruction = &instruction;
|
||||
}
|
||||
|
||||
116
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.h
Normal file
116
mozilla/ef/Compiler/RegisterAllocator/VirtualRegister.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/* -*- 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.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.
|
||||
*/
|
||||
|
||||
#ifndef _VIRTUAL_REGISTER_H_
|
||||
#define _VIRTUAL_REGISTER_H_
|
||||
|
||||
#include "Fundamentals.h"
|
||||
#include "IndexedPool.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "RegisterTypes.h"
|
||||
#include "RegisterClass.h"
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// VirtualRegister - 24b
|
||||
|
||||
class Instruction;
|
||||
|
||||
class VirtualRegister : public IndexedObject<VirtualRegister>
|
||||
{
|
||||
public:
|
||||
|
||||
Instruction* definingInstruction; // Instruction defining this VR.
|
||||
|
||||
// Initialize a VR of the given classKind.
|
||||
VirtualRegister(RegisterClassKind /*classKind*/) : definingInstruction(NULL) {}
|
||||
|
||||
// Return the defining instruction for this VR.
|
||||
Instruction* getDefiningInstruction() const {return definingInstruction;}
|
||||
// Set the defining instruction.
|
||||
void setDefiningInstruction(Instruction& insn);
|
||||
};
|
||||
|
||||
// Return true if the VirtualRegisters are equals. The only way 2 VRs can be equal is if
|
||||
// they have the same index. If they have the same index then they are at the same
|
||||
// address in the indexed pool.
|
||||
//
|
||||
inline bool operator == (const VirtualRegister& regA, const VirtualRegister& regB) {return ®A == ®B;}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// VirtualRegisterManager -
|
||||
|
||||
struct PreColoredRegister
|
||||
{
|
||||
RegisterID id;
|
||||
RegisterName color;
|
||||
};
|
||||
|
||||
class VirtualRegisterManager
|
||||
{
|
||||
private:
|
||||
|
||||
IndexedPool<VirtualRegister> registerPool;
|
||||
PreColoredRegister machineRegister[6];
|
||||
|
||||
public:
|
||||
VirtualRegisterManager()
|
||||
{
|
||||
for (Uint32 i = 0; i < 6; i++)
|
||||
machineRegister[i].id = invalidID;
|
||||
}
|
||||
|
||||
// Return the VirtualRegister at the given index.
|
||||
VirtualRegister& getVirtualRegister(RegisterName name) const {return registerPool.get(name);}
|
||||
|
||||
// Return a new VirtualRegister.
|
||||
RegisterID newVirtualRegister(RegisterClassKind classKind)
|
||||
{
|
||||
VirtualRegister& vReg = *new(registerPool) VirtualRegister(classKind);
|
||||
RegisterID rid;
|
||||
|
||||
setName(rid, RegisterName(vReg.getIndex()));
|
||||
setClass(rid, classKind);
|
||||
return rid;
|
||||
}
|
||||
|
||||
RegisterID newMachineRegister(RegisterName name, RegisterClassKind classKind)
|
||||
{
|
||||
RegisterID rid = machineRegister[name].id;
|
||||
|
||||
if (rid == invalidID) {
|
||||
rid = newVirtualRegister(classKind);
|
||||
DEBUG_ONLY(setMachineRegister(rid));
|
||||
machineRegister[name].id = rid;
|
||||
machineRegister[name].color = name;
|
||||
}
|
||||
|
||||
return rid;
|
||||
}
|
||||
|
||||
PreColoredRegister* getMachineRegistersBegin() const {return (PreColoredRegister*) machineRegister;} // FIX
|
||||
PreColoredRegister* getMachineRegistersEnd() const {return (PreColoredRegister*) &machineRegister[6];} // FIX
|
||||
|
||||
// Return the VirtualRegister universe size.
|
||||
Uint32 getSize() {return registerPool.getSize();}
|
||||
|
||||
void setSize(Uint32 size) {registerPool.setSize(size);}
|
||||
};
|
||||
|
||||
#endif // _VIRTUAL_REGISTER_H_
|
||||
@@ -1,197 +0,0 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = public
|
||||
|
||||
PROGRAM = viewer
|
||||
|
||||
CPPSRCS = \
|
||||
$(TOOLKIT_CPPSRCS) \
|
||||
nsBaseDialog.cpp \
|
||||
nsFindDialog.cpp \
|
||||
nsXPBaseWindow.cpp \
|
||||
nsTableInspectorDialog.cpp \
|
||||
nsImageInspectorDialog.cpp \
|
||||
nsPrintSetupDialog.cpp \
|
||||
nsBrowserWindow.cpp \
|
||||
nsEditorMode.cpp \
|
||||
nsSetupRegistry.cpp \
|
||||
nsThrobber.cpp \
|
||||
nsViewerApp.cpp \
|
||||
nsWebCrawler.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORT_RESOURCE_SAMPLES := \
|
||||
$(wildcard $(srcdir)/samples/test*.html) \
|
||||
$(wildcard $(srcdir)/samples/toolbarTest*.xul) \
|
||||
$(wildcard $(srcdir)/samples/treeTest*.xul) \
|
||||
$(wildcard $(srcdir)/samples/treeTest*.css) \
|
||||
$(wildcard $(srcdir)/samples/slider*.xul) \
|
||||
$(wildcard $(srcdir)/samples/scrollbar*.xul) \
|
||||
$(srcdir)/resources/find.html \
|
||||
$(srcdir)/resources/printsetup.html \
|
||||
$(srcdir)/resources/image_props.html \
|
||||
$(srcdir)/samples/aform.css \
|
||||
$(srcdir)/samples/bform.css \
|
||||
$(srcdir)/samples/cform.css \
|
||||
$(srcdir)/samples/demoform.css \
|
||||
$(srcdir)/samples/mozform.css \
|
||||
$(srcdir)/samples/xulTest.css \
|
||||
$(srcdir)/samples/Anieyes.gif \
|
||||
$(srcdir)/samples/gear1.gif \
|
||||
$(srcdir)/samples/rock_gra.gif \
|
||||
$(srcdir)/samples/beeptest.html \
|
||||
$(srcdir)/samples/soundtest.html \
|
||||
$(srcdir)/samples/bg.jpg \
|
||||
$(srcdir)/samples/raptor.jpg \
|
||||
$(srcdir)/samples/test.wav \
|
||||
$(srcdir)/samples/checkboxTest.xul \
|
||||
$(NULL)
|
||||
|
||||
EXPORT_RESOURCE_THROBBER := $(wildcard $(srcdir)/throbber/anim*.gif)
|
||||
|
||||
ifeq (,$(filter beos os2 rhapsody photon,$(MOZ_WIDGET_TOOLKIT)))
|
||||
DIRS += unix
|
||||
UNIX_VIEWER_TK_LIBS = $(DIST)/lib/libviewer_$(MOZ_WIDGET_TOOLKIT)_s.a
|
||||
else
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),beos)
|
||||
BEOS_PROGRAM_RESOURCE = $(srcdir)/viewer-beos.rsrc
|
||||
TOOLKIT_CPPSRCS = nsBeOSMain.cpp
|
||||
endif
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),photon)
|
||||
TOOLKIT_CPPSRCS = nsPhMain.cpp nsPhMenu.cpp
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk)
|
||||
GTK_GLUE = -lgtksuperwin
|
||||
endif
|
||||
|
||||
ifdef MOZ_OJI
|
||||
JSJ_LIB = -ljsj
|
||||
endif
|
||||
|
||||
XP_DIST_LIBS = \
|
||||
-lraptorgfx \
|
||||
-lmozjs \
|
||||
-lxpcom \
|
||||
$(JSJ_LIB) \
|
||||
$(NULL)
|
||||
|
||||
XP_NS_UNDERBAR_CRAP = \
|
||||
$(MOZ_NECKO_UTIL_LIBS) \
|
||||
$(MOZ_TIMER_LIBS) \
|
||||
$(MOZ_WIDGET_SUPPORT_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
XP_LIBS = \
|
||||
$(XP_NS_UNDERBAR_CRAP) \
|
||||
$(XP_DIST_LIBS) \
|
||||
$(NSPR_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_FULLCIRCLE
|
||||
XP_LIBS += $(FULLCIRCLE_LIBS)
|
||||
endif
|
||||
|
||||
LIBS = \
|
||||
$(UNIX_VIEWER_TK_LIBS) \
|
||||
$(GTK_GLUE) \
|
||||
$(XP_LIBS) \
|
||||
$(TK_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
MOTIF_LIBS = -lviewer_motif_s $(XP_LIBS) $(MOZ_MOTIF_LDFLAGS)
|
||||
QT_LIBS = -lviewer_qt_s $(XP_LIBS) $(MOZ_QT_LDFLAGS)
|
||||
XLIB_LIBS = -lviewer_xlib_s $(XP_LIBS) $(MOZ_XLIB_LDFLAGS)
|
||||
GTK_LIBS = -lviewer_gtk_s -lgtksuperwin $(XP_LIBS) $(MOZ_GTK_LDFLAGS)
|
||||
|
||||
EXTRA_DEPS = \
|
||||
$(addprefix $(DIST)/,$(patsubst -l%,bin/lib%.$(DLL_SUFFIX),$(XP_DIST_LIBS:-l%_s=lib/lib%_s.a))) \
|
||||
$(UNIX_VIEWER_TK_LIBS) \
|
||||
$(XP_NS_UNDERBAR_CRAP) \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
CXXFLAGS += $(MOZ_TOOLKIT_REGISTRY_CFLAGS)
|
||||
|
||||
install:: $(PROGRAM) $(srcdir)/mozilla-viewer.sh
|
||||
$(INSTALL) $(EXPORT_RESOURCE_SAMPLES) $(DIST)/bin/res/samples
|
||||
$(INSTALL) $(EXPORT_RESOURCE_THROBBER) $(DIST)/bin/res/throbber
|
||||
$(INSTALL) $(srcdir)/resources/viewer.properties $(DIST)/bin/res
|
||||
$(INSTALL) $(srcdir)/mozilla-viewer.sh $(DIST)/bin
|
||||
|
||||
$(PROGRAM)_gtk: $(PROGOBJS) $(EXTRA_DEPS) Makefile Makefile.in $(DIST)/lib/libviewer_gtk_s.a
|
||||
$(CCC) -o $@ $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(GTK_LIBS) $(OS_LIBS)
|
||||
$(MOZ_POST_PROGRAM_COMMAND) $@
|
||||
|
||||
$(PROGRAM)_motif: $(PROGOBJS) $(EXTRA_DEPS) Makefile Makefile.in $(DIST)/lib/libviewer_motif_s.a
|
||||
$(CCC) -o $@ $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(MOTIF_LIBS) $(OS_LIBS)
|
||||
$(MOZ_POST_PROGRAM_COMMAND) $@
|
||||
|
||||
$(PROGRAM)_qt: $(PROGOBJS) $(EXTRA_DEPS) Makefile Makefile.in $(DIST)/lib/libviewer_qt_s.a
|
||||
$(CCC) -o $@ $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(QT_LIBS) $(OS_LIBS)
|
||||
$(MOZ_POST_PROGRAM_COMMAND) $@
|
||||
|
||||
$(PROGRAM)_xlib: $(PROGOBJS) $(EXTRA_DEPS) Makefile Makefile.in $(DIST)/lib/libviewer_xlib_s.a
|
||||
$(CCC) -o $@ $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(XLIB_LIBS) $(OS_LIBS)
|
||||
$(MOZ_POST_PROGRAM_COMMAND) $@
|
||||
|
||||
ifdef MOZ_ENABLE_GTK
|
||||
install:: $(PROGRAM)_gtk
|
||||
$(INSTALL) -m 555 $< $(DIST)/bin
|
||||
|
||||
clobber::
|
||||
rm -f $(PROGRAM)_gtk
|
||||
endif
|
||||
|
||||
ifdef MOZ_ENABLE_MOTIF
|
||||
install:: $(PROGRAM)_motif
|
||||
$(INSTALL) -m 555 $< $(DIST)/bin
|
||||
|
||||
clobber::
|
||||
rm -f $(PROGRAM)_motif
|
||||
endif
|
||||
|
||||
ifdef MOZ_ENABLE_QT
|
||||
install:: $(PROGRAM)_qt
|
||||
$(INSTALL) -m 555 $< $(DIST)/bin
|
||||
|
||||
clobber::
|
||||
rm -f $(PROGRAM)_qt
|
||||
endif
|
||||
|
||||
ifdef MOZ_ENABLE_XLIB
|
||||
install:: $(PROGRAM)_xlib
|
||||
$(INSTALL) -m 555 $< $(DIST)/bin
|
||||
|
||||
clobber::
|
||||
rm -f $(PROGRAM)_xlib
|
||||
endif
|
||||
|
||||
@@ -1,179 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "gdksuperwin.h"
|
||||
#include "gtkmozbox.h"
|
||||
|
||||
#include "nsBrowserWindow.h"
|
||||
#include "resources.h"
|
||||
#include "nscore.h"
|
||||
|
||||
#include "stdio.h"
|
||||
|
||||
typedef GtkItemFactoryCallback GIFC;
|
||||
|
||||
void gtk_ifactory_cb (nsBrowserWindow *nbw,
|
||||
guint callback_action,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
nbw->DispatchMenuItem(callback_action);
|
||||
}
|
||||
|
||||
GtkItemFactoryEntry menu_items[] =
|
||||
{
|
||||
{ "/_File", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/File/_New Window", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_WINDOW_OPEN, nsnull },
|
||||
{ "/File/_Open...", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_FILE_OPEN, nsnull },
|
||||
{ "/File/_View Source", nsnull, (GIFC)gtk_ifactory_cb, VIEW_SOURCE, nsnull },
|
||||
{ "/File/_Samples", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/File/Samples/demo #0", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO0, nsnull },
|
||||
{ "/File/Samples/demo #1", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO1, nsnull },
|
||||
{ "/File/Samples/demo #2", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO2, nsnull },
|
||||
{ "/File/Samples/demo #3", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO3, nsnull },
|
||||
{ "/File/Samples/demo #4", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO4, nsnull },
|
||||
{ "/File/Samples/demo #5", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO5, nsnull },
|
||||
{ "/File/Samples/demo #6", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO6, nsnull },
|
||||
{ "/File/Samples/demo #7", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO7, nsnull },
|
||||
{ "/File/Samples/demo #8", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO8, nsnull },
|
||||
{ "/File/Samples/demo #9", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO9, nsnull },
|
||||
{ "/File/Samples/demo #10", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO10, nsnull },
|
||||
{ "/File/Samples/demo #11", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO11, nsnull },
|
||||
{ "/File/Samples/demo #12", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO12, nsnull },
|
||||
{ "/File/Samples/demo #13", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO13, nsnull },
|
||||
{ "/File/Samples/demo #14", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO14, nsnull },
|
||||
{ "/File/Samples/demo #15", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO15, nsnull },
|
||||
{ "/File/Samples/demo #16", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO16, nsnull },
|
||||
{ "/File/Samples/demo #17", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO17, nsnull },
|
||||
{ "/File/_Test Sites", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOP100, nsnull },
|
||||
{ "/File/XPToolkit Tests", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/File/XPToolkit Tests/Toolbar Test 1", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_XPTOOLKITTOOLBAR1, nsnull },
|
||||
{ "/File/XPToolkit Tests/Tree Test 1", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_XPTOOLKITTREE1, nsnull },
|
||||
{ "/File/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/File/Print Preview", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_ONE_COLUMN, nsnull },
|
||||
{ "/File/Print", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_PRINT, nsnull },
|
||||
{ "/File/Print Setup", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_PRINT_SETUP, nsnull },
|
||||
{ "/File/sep2", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/File/_Exit", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EXIT, nsnull },
|
||||
|
||||
{ "/_Edit", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/Edit/Cu_t", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_CUT, nsnull },
|
||||
{ "/Edit/_Copy", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_COPY, nsnull },
|
||||
{ "/Edit/_Paste", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_PASTE, nsnull },
|
||||
{ "/Edit/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Edit/Select All", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_SELECTALL, nsnull },
|
||||
{ "/Edit/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Edit/Find in Page", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_FINDINPAGE, nsnull },
|
||||
|
||||
//#ifdef DEBUG // turning off for now
|
||||
{ "/_Debug", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/Debug/_Visual Debugging", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_VISUAL_DEBUGGING,nsnull },
|
||||
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Debug/Event Debugging/Toggle Paint Flashing", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_PAINT_FLASHING,nsnull },
|
||||
{ "/Debug/Event Debugging/Toggle Paint Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_PAINT_DUMPING,nsnull },
|
||||
{ "/Debug/Event Debugging/Toggle Invalidate Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_INVALIDATE_DUMPING,nsnull },
|
||||
{ "/Debug/Event Debugging/Toggle Event Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_EVENT_DUMPING,nsnull },
|
||||
{ "/Debug/Event Debugging/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Debug/Event Debugging/Toggle Motion Event Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_MOTION_EVENT_DUMPING,nsnull },
|
||||
{ "/Debug/Event Debugging/Toggle Crossing Event Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_CROSSING_EVENT_DUMPING,nsnull },
|
||||
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Debug/_Reflow Test", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_REFLOW_TEST, nsnull },
|
||||
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Debug/Dump _Content", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_CONTENT, nsnull },
|
||||
{ "/Debug/Dump _Frames", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_FRAMES, nsnull },
|
||||
{ "/Debug/Dump _Views", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_VIEWS, nsnull },
|
||||
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Debug/Dump _Style Sheets", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_STYLE_SHEETS, nsnull },
|
||||
{ "/Debug/Dump _Style Contexts", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_STYLE_CONTEXTS, nsnull},
|
||||
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Debug/Show Content Size", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SHOW_CONTENT_SIZE,nsnull },
|
||||
{ "/Debug/Show Frame Size", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SHOW_FRAME_SIZE, nsnull },
|
||||
{ "/Debug/Show Style Size", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SHOW_STYLE_SIZE, nsnull },
|
||||
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Debug/Debug Save", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEBUGSAVE, nsnull },
|
||||
{ "/Debug/Debug Output Text", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DISPLAYTEXT, nsnull },
|
||||
{ "/Debug/Debug Output HTML", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DISPLAYHTML, nsnull },
|
||||
{ "/Debug/Debug Toggle Selection", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_SELECTION,nsnull },
|
||||
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Debug/Debug Robot", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEBUGROBOT, nsnull },
|
||||
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Debug/Show Content Quality", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SHOW_CONTENT_QUALITY, nsnull },
|
||||
{ "/_Style", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/Style/Select _Style Sheet", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/Style/Select Style Sheet/List Available Sheets", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_LIST, nsnull },
|
||||
{ "/Style/Select Style Sheet/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Style/Select Style Sheet/Select Default", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_DEFAULT, nsnull },
|
||||
{ "/Style/Select Style Sheet/sep1", nsnull, nsnull, 0, "<Separator>" },
|
||||
{ "/Style/Select Style Sheet/Select Alternative 1", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_ONE, nsnull },
|
||||
{ "/Style/Select Style Sheet/Select Alternative 2", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_TWO, nsnull },
|
||||
{ "/Style/Select Style Sheet/Select Alternative 3", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_THREE, nsnull },
|
||||
{ "/Style/Select Style Sheet/Select Alternative 4", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_FOUR, nsnull },
|
||||
{ "/Style/_Compatibility Mode", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/Style/Compatibility Mode/Nav Quirks", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_NAV_QUIRKS_MODE, nsnull },
|
||||
{ "/Style/Compatibility Mode/Standard", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_STANDARD_MODE, nsnull },
|
||||
|
||||
{ "/Style/_Widget Render Mode", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/Style/Widget Render Mode/Native", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_NATIVE_WIDGET_MODE, nsnull },
|
||||
{ "/Style/Widget Render Mode/Gfx", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_GFX_WIDGET_MODE, nsnull },
|
||||
//#endif
|
||||
|
||||
{ "/_Tools", nsnull, nsnull, 0, "<Branch>" },
|
||||
{ "/Tools/_JavaScript Console", nsnull, (GIFC)gtk_ifactory_cb, JS_CONSOLE, nsnull },
|
||||
{ "/Tools/_Editor Mode", nsnull, (GIFC)gtk_ifactory_cb, EDITOR_MODE, nsnull }
|
||||
};
|
||||
|
||||
void CreateViewerMenus(nsIWidget * aParent,
|
||||
gpointer data,
|
||||
GtkWidget ** aMenuBarOut)
|
||||
{
|
||||
NS_ASSERTION(nsnull != aParent,"null parent.");
|
||||
NS_ASSERTION(nsnull != aMenuBarOut,"null out param.");
|
||||
|
||||
GtkItemFactory *item_factory;
|
||||
GtkWidget *menubar;
|
||||
|
||||
GdkSuperWin *gdkSuperWin;
|
||||
GtkWidget *mozBox;
|
||||
|
||||
gdkSuperWin = (GdkSuperWin*)aParent->GetNativeData(NS_NATIVE_WIDGET);
|
||||
|
||||
int nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
|
||||
item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", nsnull);
|
||||
|
||||
gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, data);
|
||||
|
||||
menubar = gtk_item_factory_get_widget (item_factory, "<main>");
|
||||
|
||||
gtk_menu_bar_set_shadow_type (GTK_MENU_BAR(menubar), GTK_SHADOW_NONE);
|
||||
|
||||
NS_ASSERTION(GDK_IS_SUPERWIN(gdkSuperWin), "code assumes a gdksuperwin.");
|
||||
mozBox = gtk_mozbox_new(gdkSuperWin->bin_window);
|
||||
NS_ASSERTION((mozBox != NULL), "failed to create mozBox.");
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(mozBox), menubar);
|
||||
gtk_mozbox_set_position(GTK_MOZBOX(mozBox), 0, 0 );
|
||||
gtk_widget_show(mozBox);
|
||||
gtk_widget_show(menubar);
|
||||
|
||||
*aMenuBarOut = menubar;
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = xpwidgets support
|
||||
|
||||
#
|
||||
# Dont build the DSO under the 'build' directory as windows does.
|
||||
#
|
||||
# The DSOs get built in the toolkit dir itself. Do this so that
|
||||
# multiple implementations of widget can be built on the same
|
||||
# source tree.
|
||||
#
|
||||
ifndef MOZ_MONOLITHIC_TOOLKIT
|
||||
|
||||
ifdef MOZ_ENABLE_GTK
|
||||
DIRS += gtksuperwin
|
||||
DIRS += gtk
|
||||
endif
|
||||
|
||||
ifdef MOZ_ENABLE_MOTIF
|
||||
DIRS += motif
|
||||
endif
|
||||
|
||||
ifdef MOZ_ENABLE_XLIB
|
||||
DIRS += xlib
|
||||
endif
|
||||
|
||||
ifdef MOZ_ENABLE_QT
|
||||
DIRS += qt
|
||||
endif
|
||||
|
||||
else
|
||||
DIRS += $(MOZ_WIDGET_TOOLKIT)
|
||||
endif
|
||||
|
||||
# unix_services are only useful in unix, duh...
|
||||
ifeq (,$(filter beos os2 rhapsody photon,$(MOZ_WIDGET_TOOLKIT)))
|
||||
DIRS += unix_services
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
LIBRARY_NAME = widget_gtk
|
||||
|
||||
REQUIRES = util img xpcom raptor netlib
|
||||
|
||||
CPPSRCS = \
|
||||
nsAppShell.cpp \
|
||||
nsButton.cpp \
|
||||
nsCheckButton.cpp \
|
||||
nsClipboard.cpp \
|
||||
nsComboBox.cpp \
|
||||
nsContextMenu.cpp \
|
||||
nsDragService.cpp \
|
||||
nsFilePicker.cpp \
|
||||
nsFileWidget.cpp \
|
||||
nsFontRetrieverService.cpp \
|
||||
nsFontSizeIterator.cpp \
|
||||
nsGtkEventHandler.cpp \
|
||||
nsGtkUtils.cpp \
|
||||
nsLabel.cpp \
|
||||
nsListBox.cpp \
|
||||
nsLookAndFeel.cpp \
|
||||
nsMenu.cpp \
|
||||
nsMenuBar.cpp \
|
||||
nsMenuItem.cpp \
|
||||
nsPopUpMenu.cpp \
|
||||
nsRadioButton.cpp \
|
||||
nsScrollbar.cpp \
|
||||
nsSound.cpp \
|
||||
nsTextAreaWidget.cpp \
|
||||
nsTextHelper.cpp \
|
||||
nsTextWidget.cpp \
|
||||
nsToolkit.cpp \
|
||||
nsWidget.cpp \
|
||||
nsWidgetFactory.cpp \
|
||||
nsWindow.cpp \
|
||||
$(NULL)
|
||||
|
||||
SHARED_LIBRARY_LIBS = $(DIST)/lib/libraptorbasewidget_s.a
|
||||
|
||||
EXTRA_DSO_LDOPTS = \
|
||||
$(MKSHLIB_FORCE_ALL) \
|
||||
$(SHARED_LIBRARY_LIBS) \
|
||||
$(MKSHLIB_UNFORCE_ALL) \
|
||||
$(MOZ_COMPONENT_LIBS) \
|
||||
-lraptorgfx \
|
||||
$(NULL)
|
||||
|
||||
ifndef MOZ_MONOLITHIC_TOOLKIT
|
||||
EXTRA_DSO_LDOPTS += -L$(DIST)/lib -lgtksuperwin $(MOZ_GTK_LDFLAGS)
|
||||
else
|
||||
EXTRA_DSO_LDOPTS += $(TK_LIBS)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifndef MOZ_MONOLITHIC_TOOLKIT
|
||||
CXXFLAGS += $(MOZ_GTK_CFLAGS)
|
||||
CFLAGS += $(MOZ_GTK_CFLAGS)
|
||||
else
|
||||
CXXFLAGS += $(TK_CFLAGS)
|
||||
CFLAGS += $(TK_CFLAGS)
|
||||
endif
|
||||
|
||||
DEFINES += -D_IMPL_NS_WIDGET -DUSE_XIM
|
||||
|
||||
ifeq ($(OS_ARCH), Linux)
|
||||
DEFINES += -D_BSD_SOURCE
|
||||
endif
|
||||
|
||||
INCLUDES += \
|
||||
-I$(srcdir)/../xpwidgets \
|
||||
-I$(srcdir) \
|
||||
$(NULL)
|
||||
|
||||
$(LIBRARY) $(SHARED_LIBRARY): $(SHARED_LIBRARY_LIBS) Makefile
|
||||
|
||||
@@ -1,292 +0,0 @@
|
||||
/* XPM */
|
||||
static char * mozilla_icon_xpm[] = {
|
||||
"32 32 257 2",
|
||||
" c None",
|
||||
". c #AA7303",
|
||||
"+ c #A67003",
|
||||
"@ c #B77C03",
|
||||
"# c #8D6003",
|
||||
"$ c #8D6004",
|
||||
"% c #6C4A04",
|
||||
"& c #3A2804",
|
||||
"* c #6B4802",
|
||||
"= c #9B6903",
|
||||
"- c #5A2C04",
|
||||
"; c #411B04",
|
||||
"> c #9D6A03",
|
||||
", c #7A5203",
|
||||
"' c #510D04",
|
||||
") c #6B1104",
|
||||
"! c #7D5503",
|
||||
"~ c #674604",
|
||||
"{ c #C21E04",
|
||||
"] c #C21D04",
|
||||
"^ c #523804",
|
||||
"/ c #513702",
|
||||
"( c #552904",
|
||||
"_ c #DD2204",
|
||||
": c #DF2204",
|
||||
"< c #582904",
|
||||
"[ c #5F3F02",
|
||||
"} c #6B2504",
|
||||
"| c #FE2604",
|
||||
"1 c #AB7303",
|
||||
"2 c #9B6904",
|
||||
"3 c #C31F04",
|
||||
"4 c #FE2704",
|
||||
"5 c #A81904",
|
||||
"6 c #926304",
|
||||
"7 c #4D3302",
|
||||
"8 c #483104",
|
||||
"9 c #C61E04",
|
||||
"0 c #B11B04",
|
||||
"a c #891604",
|
||||
"b c #761204",
|
||||
"c c #614304",
|
||||
"d c #775102",
|
||||
"e c #795102",
|
||||
"f c #785102",
|
||||
"g c #C58603",
|
||||
"h c #642404",
|
||||
"i c #B21A04",
|
||||
"j c #1F0604",
|
||||
"k c #550E04",
|
||||
"l c #631004",
|
||||
"m c #402404",
|
||||
"n c #AF7703",
|
||||
"o c #3D2902",
|
||||
"p c #7F5602",
|
||||
"q c #805604",
|
||||
"r c #0C0904",
|
||||
"s c #080604",
|
||||
"t c #080706",
|
||||
"u c #090604",
|
||||
"v c #060404",
|
||||
"w c #620F04",
|
||||
"x c #7A1304",
|
||||
"y c #030204",
|
||||
"z c #570E04",
|
||||
"A c #721204",
|
||||
"B c #270704",
|
||||
"C c #080504",
|
||||
"D c #0A0604",
|
||||
"E c #533804",
|
||||
"F c #A56F02",
|
||||
"G c #B87C03",
|
||||
"H c #3B2804",
|
||||
"I c #A51904",
|
||||
"J c #FC2704",
|
||||
"K c #D62004",
|
||||
"L c #691004",
|
||||
"M c #C01E04",
|
||||
"N c #6D1004",
|
||||
"O c #9C1804",
|
||||
"P c #B31C04",
|
||||
"Q c #150404",
|
||||
"R c #801404",
|
||||
"S c #DD2304",
|
||||
"T c #120404",
|
||||
"U c #130404",
|
||||
"V c #500C04",
|
||||
"W c #CC1E04",
|
||||
"X c #AA1A04",
|
||||
"Y c #100904",
|
||||
"Z c #B47A03",
|
||||
"` c #A77103",
|
||||
" . c #513704",
|
||||
".. c #891704",
|
||||
"+. c #F62604",
|
||||
"@. c #BA1D04",
|
||||
"#. c #3C0A04",
|
||||
"$. c #EB2304",
|
||||
"%. c #DE2304",
|
||||
"&. c #560E04",
|
||||
"*. c #E82304",
|
||||
"=. c #FE2804",
|
||||
"-. c #BE1D04",
|
||||
";. c #F12404",
|
||||
">. c #661004",
|
||||
",. c #020204",
|
||||
"'. c #5E0F04",
|
||||
"). c #A61A04",
|
||||
"!. c #4A3204",
|
||||
"~. c #BC7E03",
|
||||
"{. c #8E6002",
|
||||
"]. c #684604",
|
||||
"^. c #390D04",
|
||||
"/. c #EE2404",
|
||||
"(. c #FE2904",
|
||||
"_. c #7D1304",
|
||||
":. c #8C1504",
|
||||
"<. c #200604",
|
||||
"[. c #A81A04",
|
||||
"}. c #E72204",
|
||||
"|. c #DA2004",
|
||||
"1. c #070204",
|
||||
"2. c #280704",
|
||||
"3. c #543904",
|
||||
"4. c #9F6C02",
|
||||
"5. c #674602",
|
||||
"6. c #B47B04",
|
||||
"7. c #311004",
|
||||
"8. c #B11C04",
|
||||
"9. c #AA1B04",
|
||||
"0. c #6A1104",
|
||||
"a. c #801504",
|
||||
"b. c #2B0704",
|
||||
"c. c #09090A",
|
||||
"d. c #450B04",
|
||||
"e. c #360904",
|
||||
"f. c #DC2204",
|
||||
"g. c #EE2504",
|
||||
"h. c #C11D04",
|
||||
"i. c #6F1104",
|
||||
"j. c #704B04",
|
||||
"k. c #9C6902",
|
||||
"l. c #A56F03",
|
||||
"m. c #5F4004",
|
||||
"n. c #8D1604",
|
||||
"o. c #440A04",
|
||||
"p. c #1A0504",
|
||||
"q. c #931604",
|
||||
"r. c #621004",
|
||||
"s. c #7F1404",
|
||||
"t. c #921704",
|
||||
"u. c #F82504",
|
||||
"v. c #F52504",
|
||||
"w. c #981804",
|
||||
"x. c #241804",
|
||||
"y. c #5B3E04",
|
||||
"z. c #D82204",
|
||||
"A. c #D02004",
|
||||
"B. c #DA2104",
|
||||
"C. c #D52104",
|
||||
"D. c #2A1A04",
|
||||
"E. c #AC7403",
|
||||
"F. c #2B1C04",
|
||||
"G. c #D04004",
|
||||
"H. c #FC3C04",
|
||||
"I. c #F94E04",
|
||||
"J. c #881504",
|
||||
"K. c #FC2604",
|
||||
"L. c #792804",
|
||||
"M. c #AC7503",
|
||||
"N. c #9A6803",
|
||||
"O. c #782804",
|
||||
"P. c #F66504",
|
||||
"Q. c #F94B04",
|
||||
"R. c #F46804",
|
||||
"S. c #F46604",
|
||||
"T. c #F76504",
|
||||
"U. c #FB4204",
|
||||
"V. c #C13D04",
|
||||
"W. c #5D0E04",
|
||||
"X. c #DA2204",
|
||||
"Y. c #741604",
|
||||
"Z. c #8C5E03",
|
||||
"`. c #885B03",
|
||||
" + c #8B1904",
|
||||
".+ c #DE2204",
|
||||
"++ c #D22D04",
|
||||
"@+ c #C42D04",
|
||||
"#+ c #580E04",
|
||||
"$+ c #9F1804",
|
||||
"%+ c #895D04",
|
||||
"&+ c #D62204",
|
||||
"*+ c #371904",
|
||||
"=+ c #2C1A04",
|
||||
"-+ c #4A0C04",
|
||||
";+ c #140404",
|
||||
">+ c #AB1A04",
|
||||
",+ c #DA2304",
|
||||
"'+ c #6A4702",
|
||||
")+ c #754F02",
|
||||
"!+ c #821404",
|
||||
"~+ c #462B04",
|
||||
"{+ c #B37A03",
|
||||
"]+ c #B17803",
|
||||
"^+ c #714C04",
|
||||
"/+ c #580F04",
|
||||
"(+ c #E32204",
|
||||
"_+ c #DD2104",
|
||||
":+ c #611D04",
|
||||
"<+ c #BA7F03",
|
||||
"[+ c #B27803",
|
||||
"}+ c #6F1D04",
|
||||
"|+ c #FD2704",
|
||||
"1+ c #F22504",
|
||||
"2+ c #634304",
|
||||
"3+ c #875B03",
|
||||
"4+ c #734F02",
|
||||
"5+ c #805704",
|
||||
"6+ c #1D0504",
|
||||
"7+ c #DB2204",
|
||||
"8+ c #EA2404",
|
||||
"9+ c #2E0804",
|
||||
"0+ c #815803",
|
||||
"a+ c #941704",
|
||||
"b+ c #C11E04",
|
||||
"c+ c #391B04",
|
||||
"d+ c #A77104",
|
||||
"e+ c #B67C04",
|
||||
"f+ c #371D04",
|
||||
"g+ c #360A04",
|
||||
"h+ c #573A04",
|
||||
"i+ c #372604",
|
||||
"j+ c #3E2104",
|
||||
"k+ c #B57A03",
|
||||
"l+ c #B57B03",
|
||||
"m+ c #603F04",
|
||||
"n+ c #430A04",
|
||||
"o+ c #351904",
|
||||
"p+ c #A36E03",
|
||||
"q+ c #BE8103",
|
||||
"r+ c #1D1404",
|
||||
"s+ c #483004",
|
||||
"t+ c #A26E03",
|
||||
"u+ c #6D4B02",
|
||||
"v+ c #825804",
|
||||
"w+ c #0B0804",
|
||||
"x+ c #976603",
|
||||
"y+ c #815703",
|
||||
"z+ c #926404",
|
||||
"A+ c #895D03",
|
||||
"B+ c #614202",
|
||||
"C+ c #9A6804",
|
||||
"D+ c #C88704",
|
||||
"E+ c #C18303",
|
||||
"F+ c #654302",
|
||||
"G+ c #744F02",
|
||||
"H+ c #704B02",
|
||||
" ",
|
||||
" . ",
|
||||
" + @ ",
|
||||
" # $ ",
|
||||
" % & * ",
|
||||
" = - ; > ",
|
||||
" , ' ) ! ",
|
||||
" ~ { ] ^ ",
|
||||
" / ( _ : < [ ",
|
||||
" . } | | } 1 ",
|
||||
" 2 3 | 4 5 6 ",
|
||||
" 7 8 9 0 a b c ",
|
||||
" d e f f f d d d d d d g h i j k l m n d d d d d d d d d d d o ",
|
||||
" p q r s s s s t s s u v w x y z A B C D D D D D s s s s E F ",
|
||||
" G H I J 4 | 4 | K L L M N O P Q R | S T U V W X Y Z ",
|
||||
" ` ...+.| 4 @.#.$.4 | %.&.*.4 =.-.;.>.,.'.).!.~. ",
|
||||
" {.].^./.(.X _.;.| :.T <.[.| }.z | |.1.2.3.4. ",
|
||||
" 5.6.7.8.9.0.a.b.c.d.e.f.g.h.&.| i.u j.k. ",
|
||||
" l.m.n.o.p.q._.r.a.s.t.u.v.w.x.Z ",
|
||||
" {.y.P z.R A.v.x j B.| C.D.E. ",
|
||||
" F.G.H.I.4 | 4 t.J.f.K.L.M. ",
|
||||
" N.O.P.Q.R.S.T.U.V.W.X.4 Y.Z. ",
|
||||
" `. +4 =.| | .+++@+#+$+| K %+ ",
|
||||
" %+&+| | | I *+=+-+;+>+,+&+x.'+ ",
|
||||
" )+=+X.=.| !+~+{+]+^+,./+(+_+:+<+ ",
|
||||
" [+}+|+1+) 2+3+ 4+5+6+7+8+9+0+ ",
|
||||
" $ a+b+c+d+ e+f+0.g+h+ ",
|
||||
" i+A j+k+ l+m+n+o+p+ ",
|
||||
" q+r+s+t+ u+v+w+x+ ",
|
||||
" y+z+A+ B+C+2 ",
|
||||
" D+ E+F+ ",
|
||||
" G+ H+ "};
|
||||
@@ -1,63 +0,0 @@
|
||||
/* XPM */
|
||||
static char * mozicon50_xpm[] = {
|
||||
"50 51 9 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"+ c #FF0000",
|
||||
"@ c #808000",
|
||||
"# c #800000",
|
||||
"$ c #FF6633",
|
||||
"% c #990066",
|
||||
"& c #FF00FF",
|
||||
"* c #222222",
|
||||
" ",
|
||||
" @ ",
|
||||
" $@ ",
|
||||
" @@ ",
|
||||
" @@$ ",
|
||||
" $@*@ ",
|
||||
" @@.@ ",
|
||||
" @..@ ",
|
||||
" $@..@@ ",
|
||||
" $@##*@ ",
|
||||
" @*#+.@ ",
|
||||
" @.++.@$ ",
|
||||
" $@.++.@$ ",
|
||||
" @*#++#*@ ",
|
||||
" @.++++.@ ",
|
||||
" $@.++++.@$ ",
|
||||
" @*#++++**@ ",
|
||||
" @.#++++#.@ ",
|
||||
" $@.++####.@ ",
|
||||
" @@*+#*##*.@@ ",
|
||||
"*@@@@@@@@@@@@@@@@@@@.#+..*##*#@@@@@@@@@@@@@@@@@@@*",
|
||||
" *@@*................+#..*###.................@@* ",
|
||||
" %@@@.#++++++++++++#**#*#++.###++*...#+++#.*@@* ",
|
||||
" *@@.#+++++++++#.##++#+#+*.#+++#..##++#.@@@% ",
|
||||
" $@..+++++++.#++++++##++++#++#...++*.@@$ ",
|
||||
" @@*.#+++++.#+++++*.#++++##++#.*...@@ ",
|
||||
" $@@.#+++#*++++#....#+++*#+++...*@$ ",
|
||||
" *@@..++#*++#**.*.*+++#.#++*..@@$ ",
|
||||
" $@*.++******#+++++#+#+++..@@ ",
|
||||
" $@@.##..*$#**#+#*#++++..@@ ",
|
||||
" $@@.#+#***##...#++++.*@@ ",
|
||||
" %@@*++++++++#.#++++.@@ ",
|
||||
" @.#+++++++++.##+++.@$ ",
|
||||
" @.+$$$$$+$$$#*#+++*@@ ",
|
||||
" $@*+$$$$$$$+$#.#+++#.@ ",
|
||||
" @*#+++++++++++.#++++.@ ",
|
||||
" @.#+++++++#*++.##+++.@$ ",
|
||||
" $@.+++++++....#..+#++*@@ ",
|
||||
" @@*+++++#.*@@@...*+++#.@ ",
|
||||
" @.#++++#.@@@ @@..#++++.@ ",
|
||||
" @.++++*.@@$ %@@..+++#.@@ ",
|
||||
" $@.+++..@@* $@*.#+#**@ ",
|
||||
" @@#+#.*@$% $@@.##..@ ",
|
||||
" @.##.@@ @@..#.@$ ",
|
||||
" $@.*.@@$ @@**.@$ ",
|
||||
" $@.*@@ %$@@.*@ ",
|
||||
" @.@@$ *@@.@ ",
|
||||
" @@@$ %@@@$ ",
|
||||
" $@@% %@@@ ",
|
||||
" @@ $@ ",
|
||||
" $ * "};
|
||||
@@ -1,459 +0,0 @@
|
||||
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "prmon.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAppShell.h"
|
||||
#include "nsIAppShell.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsICmdLineService.h"
|
||||
#include "nsGtkEventHandler.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef MOZ_GLE
|
||||
#include <gle/gle.h>
|
||||
#endif
|
||||
|
||||
#include "nsIWidget.h"
|
||||
#include "nsIPref.h"
|
||||
|
||||
|
||||
#include "glib.h"
|
||||
|
||||
struct OurGdkIOClosure {
|
||||
GdkInputFunction function;
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
our_gdk_io_invoke(GIOChannel* source, GIOCondition condition, gpointer data)
|
||||
{
|
||||
OurGdkIOClosure* ioc = (OurGdkIOClosure*) data;
|
||||
if (ioc) {
|
||||
(*ioc->function)(ioc->data, g_io_channel_unix_get_fd(source),
|
||||
GDK_INPUT_READ);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
our_gdk_io_destroy(gpointer data)
|
||||
{
|
||||
OurGdkIOClosure* ioc = (OurGdkIOClosure*) data;
|
||||
if (ioc) {
|
||||
g_free(ioc);
|
||||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
our_gdk_input_add (gint source,
|
||||
GdkInputFunction function,
|
||||
gpointer data,
|
||||
gint priority)
|
||||
{
|
||||
guint result;
|
||||
OurGdkIOClosure *closure = g_new (OurGdkIOClosure, 1);
|
||||
GIOChannel *channel;
|
||||
|
||||
closure->function = function;
|
||||
closure->data = data;
|
||||
|
||||
channel = g_io_channel_unix_new (source);
|
||||
result = g_io_add_watch_full (channel, priority, G_IO_IN,
|
||||
our_gdk_io_invoke,
|
||||
closure, our_gdk_io_destroy);
|
||||
g_io_channel_unref (channel);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// XPCOM CIDs
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
static NS_DEFINE_CID(kCmdLineServiceCID, NS_COMMANDLINE_SERVICE_CID);
|
||||
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
||||
|
||||
// a linked, ordered list of event queues and their tokens
|
||||
class EventQueueToken {
|
||||
public:
|
||||
EventQueueToken(nsIEventQueue *aQueue, const gint aToken);
|
||||
virtual ~EventQueueToken();
|
||||
nsIEventQueue *mQueue;
|
||||
gint mToken;
|
||||
EventQueueToken *mNext;
|
||||
};
|
||||
|
||||
EventQueueToken::EventQueueToken(nsIEventQueue *aQueue, const gint aToken) {
|
||||
mQueue = aQueue;
|
||||
NS_IF_ADDREF(mQueue);
|
||||
mToken = aToken;
|
||||
mNext = 0;
|
||||
}
|
||||
|
||||
EventQueueToken::~EventQueueToken(){
|
||||
NS_IF_RELEASE(mQueue);
|
||||
}
|
||||
|
||||
class EventQueueTokenQueue {
|
||||
public:
|
||||
EventQueueTokenQueue();
|
||||
virtual ~EventQueueTokenQueue();
|
||||
nsresult PushToken(nsIEventQueue *aQueue, gint aToken);
|
||||
PRBool PopToken(nsIEventQueue *aQueue, gint *aToken);
|
||||
|
||||
private:
|
||||
EventQueueToken *mHead;
|
||||
};
|
||||
|
||||
EventQueueTokenQueue::EventQueueTokenQueue() {
|
||||
mHead = 0;
|
||||
}
|
||||
|
||||
EventQueueTokenQueue::~EventQueueTokenQueue() {
|
||||
|
||||
// if we reach this point with an empty token queue, well, fab. however,
|
||||
// we expect the first event queue to still be active. so we take
|
||||
// special care to unhook that queue (not that failing to do so seems
|
||||
// to hurt anything). more queues than that would be an error.
|
||||
//NS_ASSERTION(!mHead || !mHead->mNext, "event queue token list deleted when not empty");
|
||||
// (and skip the assertion for now. we're leaking event queues because they
|
||||
// are referenced by things that leak, so this assertion goes off a lot.)
|
||||
if (mHead) {
|
||||
gdk_input_remove(mHead->mToken);
|
||||
delete mHead;
|
||||
// and leak the rest. it's an error, anyway
|
||||
}
|
||||
}
|
||||
|
||||
nsresult EventQueueTokenQueue::PushToken(nsIEventQueue *aQueue, gint aToken) {
|
||||
EventQueueToken *newToken = new EventQueueToken(aQueue, aToken);
|
||||
NS_ASSERTION(newToken, "couldn't allocate token queue element");
|
||||
if (!newToken)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
newToken->mNext = mHead;
|
||||
mHead = newToken;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool EventQueueTokenQueue::PopToken(nsIEventQueue *aQueue, gint *aToken) {
|
||||
EventQueueToken *token, *lastToken;
|
||||
PRBool found = PR_FALSE;
|
||||
NS_ASSERTION(mHead, "attempt to retrieve event queue token from empty queue");
|
||||
if (mHead)
|
||||
NS_ASSERTION(mHead->mQueue == aQueue, "retrieving event queue from past head of queue queue");
|
||||
|
||||
token = mHead;
|
||||
lastToken = 0;
|
||||
while (token && token->mQueue != aQueue) {
|
||||
lastToken = token;
|
||||
token = token->mNext;
|
||||
}
|
||||
if (token) {
|
||||
if (lastToken)
|
||||
lastToken->mNext = token->mNext;
|
||||
else
|
||||
mHead = token->mNext;
|
||||
found = PR_TRUE;
|
||||
*aToken = token->mToken;
|
||||
delete token;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsAppShell constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsAppShell::nsAppShell()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mDispatchListener = 0;
|
||||
mEventQueueTokens = new EventQueueTokenQueue();
|
||||
// throw on error would really be civilized here
|
||||
NS_ASSERTION(mEventQueueTokens, "couldn't allocate event queue token queue");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsAppShell destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsAppShell::~nsAppShell()
|
||||
{
|
||||
delete mEventQueueTokens;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsISupports implementation macro
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsAppShell, nsIAppShell)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsAppShell::SetDispatchListener(nsDispatchListener* aDispatchListener)
|
||||
{
|
||||
mDispatchListener = aDispatchListener;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void event_processor_callback(gpointer data,
|
||||
gint source,
|
||||
GdkInputCondition condition)
|
||||
{
|
||||
nsIEventQueue *eventQueue = (nsIEventQueue*)data;
|
||||
if (eventQueue)
|
||||
eventQueue->ProcessPendingEvents();
|
||||
}
|
||||
|
||||
#define PREF_NCOLS "browser.ncols"
|
||||
#define PREF_INSTALLCMAP "browser.installcmap"
|
||||
|
||||
static void
|
||||
HandleColormapPrefs( void )
|
||||
{
|
||||
PRInt32 ivalue = 0;
|
||||
PRBool bvalue;
|
||||
nsresult rv;
|
||||
|
||||
/* The default is to do nothing. INSTALLCMAP has precedence over
|
||||
NCOLS. Ignore the fact we can't do this if it fails, as it is
|
||||
not critical */
|
||||
|
||||
NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv);
|
||||
if (NS_FAILED(rv) || (!prefs))
|
||||
return;
|
||||
|
||||
/* first check ncols */
|
||||
|
||||
rv = prefs->GetIntPref(PREF_NCOLS, &ivalue);
|
||||
if (NS_SUCCEEDED(rv) && ivalue >= 0 && ivalue <= 255 ) {
|
||||
gdk_rgb_set_min_colors( ivalue );
|
||||
return;
|
||||
}
|
||||
|
||||
/* next check installcmap */
|
||||
|
||||
rv = prefs->GetBoolPref(PREF_INSTALLCMAP, &bvalue);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if ( PR_TRUE == bvalue )
|
||||
gdk_rgb_set_min_colors( 255 ); // force it
|
||||
else
|
||||
gdk_rgb_set_min_colors( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the application shell
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP nsAppShell::Create(int *bac, char **bav)
|
||||
{
|
||||
gchar *home=nsnull;
|
||||
gchar *path=nsnull;
|
||||
|
||||
int argc = bac ? *bac : 0;
|
||||
char **argv = bav;
|
||||
#if 1
|
||||
nsresult rv;
|
||||
|
||||
NS_WITH_SERVICE(nsICmdLineService, cmdLineArgs, kCmdLineServiceCID, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = cmdLineArgs->GetArgc(&argc);
|
||||
if(NS_FAILED(rv))
|
||||
argc = bac ? *bac : 0;
|
||||
|
||||
rv = cmdLineArgs->GetArgv(&argv);
|
||||
if(NS_FAILED(rv))
|
||||
argv = bav;
|
||||
}
|
||||
#endif
|
||||
|
||||
gtk_set_locale ();
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
// It is most convenient for us to intercept our events after
|
||||
// they have been converted to GDK, but before GTK+ gets them
|
||||
gdk_event_handler_set (handle_gdk_event, NULL, NULL);
|
||||
|
||||
#ifdef MOZ_GLE
|
||||
gle_init (&argc, &argv);
|
||||
#endif
|
||||
|
||||
// delete the cmdLineArgs thing?
|
||||
|
||||
HandleColormapPrefs();
|
||||
gdk_rgb_init();
|
||||
|
||||
home = g_get_home_dir();
|
||||
if ((char*)nsnull != home) {
|
||||
path = g_strdup_printf("%s%c%s", home, G_DIR_SEPARATOR, ".gtkrc");
|
||||
if ((char *)nsnull != path) {
|
||||
gtk_rc_parse(path);
|
||||
g_free(path);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Spinup - do any preparation necessary for running a message loop
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsAppShell::Spinup()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Spindown - do any cleanup necessary for finishing a message loop
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsAppShell::Spindown()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Run
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsAppShell::Run()
|
||||
{
|
||||
NS_ADDREF_THIS();
|
||||
nsresult rv = NS_OK;
|
||||
nsIEventQueue * EQueue = nsnull;
|
||||
|
||||
// Get the event queue service
|
||||
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ASSERTION("Could not obtain event queue service", PR_FALSE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Got the event queue from the service\n");
|
||||
#endif /* DEBUG */
|
||||
|
||||
//Get the event queue for the thread.
|
||||
rv = eventQService->GetThreadEventQueue(PR_GetCurrentThread(), &EQueue);
|
||||
|
||||
// If a queue already present use it.
|
||||
if (EQueue)
|
||||
goto done;
|
||||
|
||||
// Create the event queue for the thread
|
||||
rv = eventQService->CreateThreadEventQueue();
|
||||
if (NS_OK != rv) {
|
||||
NS_ASSERTION("Could not create the thread event queue", PR_FALSE);
|
||||
return rv;
|
||||
}
|
||||
//Get the event queue for the thread
|
||||
rv = eventQService->GetThreadEventQueue(PR_GetCurrentThread(), &EQueue);
|
||||
if (NS_OK != rv) {
|
||||
NS_ASSERTION("Could not obtain the thread event queue", PR_FALSE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
done:
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Calling gdk_input_add with event queue\n");
|
||||
#endif /* DEBUG */
|
||||
|
||||
// (has to be called explicitly for this, the primordial appshell, because
|
||||
// of startup ordering problems.)
|
||||
ListenToEventQueue(EQueue, PR_TRUE);
|
||||
|
||||
gtk_main();
|
||||
|
||||
NS_IF_RELEASE(EQueue);
|
||||
Release();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Exit a message handler loop
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP nsAppShell::Exit()
|
||||
{
|
||||
gtk_main_quit ();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// does nothing. used by xp code with non-gtk expectations.
|
||||
// this method will be removed once xp eventloops are working.
|
||||
NS_IMETHODIMP nsAppShell::GetNativeEvent(PRBool &aRealEvent, void *& aEvent)
|
||||
{
|
||||
aRealEvent = PR_FALSE;
|
||||
aEvent = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// simply executes one iteration of the event loop. used by xp code with
|
||||
// non-gtk expectations.
|
||||
// this method will be removed once xp eventloops are working.
|
||||
NS_IMETHODIMP nsAppShell::DispatchNativeEvent(PRBool aRealEvent, void *aEvent)
|
||||
{
|
||||
g_main_iteration(PR_TRUE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsAppShell::ListenToEventQueue(nsIEventQueue *aQueue,
|
||||
PRBool aListen)
|
||||
{
|
||||
// tell gdk to listen to the event queue or not
|
||||
|
||||
gint queueToken;
|
||||
if (aListen) {
|
||||
queueToken = our_gdk_input_add(aQueue->GetEventQueueSelectFD(),
|
||||
event_processor_callback,
|
||||
aQueue, G_PRIORITY_DEFAULT_IDLE);
|
||||
mEventQueueTokens->PushToken(aQueue, queueToken);
|
||||
} else {
|
||||
if (mEventQueueTokens->PopToken(aQueue, &queueToken))
|
||||
gdk_input_remove(queueToken);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsAppShell_h__
|
||||
#define nsAppShell_h__
|
||||
|
||||
#include "nsIAppShell.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/**
|
||||
* Native GTK+ Application shell wrapper
|
||||
*/
|
||||
|
||||
class EventQueueTokenQueue;
|
||||
|
||||
class nsAppShell : public nsIAppShell
|
||||
{
|
||||
public:
|
||||
nsAppShell();
|
||||
virtual ~nsAppShell();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIAPPSHELL
|
||||
|
||||
private:
|
||||
nsDispatchListener *mDispatchListener;
|
||||
EventQueueTokenQueue *mEventQueueTokens;
|
||||
};
|
||||
|
||||
#endif // nsAppShell_h__
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "nsGtkEventHandler.h"
|
||||
|
||||
#include "nsButton.h"
|
||||
#include "nsString.h"
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsButton, nsWidget)
|
||||
NS_IMPL_RELEASE_INHERITED(nsButton, nsWidget)
|
||||
NS_IMPL_QUERY_INTERFACE2(nsButton, nsIButton, nsIWidget)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsButton constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsButton::nsButton() : nsWidget() , nsIButton()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the native Button widget
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsButton::CreateNative(GtkObject *parentWindow)
|
||||
{
|
||||
#ifdef USE_SUPERWIN
|
||||
if (!GDK_IS_SUPERWIN(parentWindow)) {
|
||||
g_print("Damn, brother. That's not a superwin.\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
GdkSuperWin *superwin = GDK_SUPERWIN(parentWindow);
|
||||
|
||||
mMozBox = gtk_mozbox_new(superwin->bin_window);
|
||||
|
||||
#endif
|
||||
|
||||
mWidget = gtk_button_new_with_label("");
|
||||
gtk_widget_set_name(mWidget, "nsButton");
|
||||
|
||||
#ifdef USE_SUPERWIN
|
||||
|
||||
// make sure that we put the scrollbar into the mozbox
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(mMozBox), mWidget);
|
||||
|
||||
#endif /* USE_SUPERWIN */
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsButton destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsButton::~nsButton()
|
||||
{
|
||||
}
|
||||
|
||||
void nsButton::InitCallbacks(char * aName)
|
||||
{
|
||||
InstallButtonPressSignal(mWidget);
|
||||
InstallButtonReleaseSignal(mWidget);
|
||||
|
||||
InstallEnterNotifySignal(mWidget);
|
||||
InstallLeaveNotifySignal(mWidget);
|
||||
|
||||
// These are needed so that the events will go to us and not our parent.
|
||||
AddToEventMask(mWidget,
|
||||
GDK_BUTTON_PRESS_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_ENTER_NOTIFY_MASK |
|
||||
GDK_EXPOSURE_MASK |
|
||||
GDK_FOCUS_CHANGE_MASK |
|
||||
GDK_KEY_PRESS_MASK |
|
||||
GDK_KEY_RELEASE_MASK |
|
||||
GDK_LEAVE_NOTIFY_MASK |
|
||||
GDK_POINTER_MOTION_MASK);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set this button label
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsButton::SetLabel(const nsString& aText)
|
||||
{
|
||||
NS_ALLOC_STR_BUF(label, aText, 256);
|
||||
|
||||
gtk_label_set(GTK_LABEL(GTK_BIN (mWidget)->child), label);
|
||||
|
||||
NS_FREE_STR_BUF(label);
|
||||
return (NS_OK);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get this button label
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsButton::GetLabel(nsString& aBuffer)
|
||||
{
|
||||
char * text;
|
||||
|
||||
gtk_label_get(GTK_LABEL(GTK_BIN (mWidget)->child), &text);
|
||||
aBuffer.SetLength(0);
|
||||
aBuffer.Append(text);
|
||||
|
||||
return (NS_OK);
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// set font for button
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
/* virtual */
|
||||
void nsButton::SetFontNative(GdkFont *aFont)
|
||||
{
|
||||
GtkStyle *style = gtk_style_copy(GTK_BIN (mWidget)->child->style);
|
||||
// gtk_style_copy ups the ref count of the font
|
||||
gdk_font_unref (style->font);
|
||||
|
||||
style->font = aFont;
|
||||
gdk_font_ref(style->font);
|
||||
|
||||
gtk_widget_set_style(GTK_BIN (mWidget)->child, style);
|
||||
|
||||
gtk_style_unref(style);
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsButton_h__
|
||||
#define nsButton_h__
|
||||
|
||||
#include "nsWidget.h"
|
||||
#include "nsIButton.h"
|
||||
|
||||
/**
|
||||
* Native GTK+ button wrapper
|
||||
*/
|
||||
class nsButton : public nsWidget,
|
||||
public nsIButton
|
||||
{
|
||||
|
||||
public:
|
||||
nsButton();
|
||||
virtual ~nsButton();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIButton part
|
||||
NS_IMETHOD SetLabel(const nsString& aText);
|
||||
NS_IMETHOD GetLabel(nsString& aBuffer);
|
||||
|
||||
virtual void SetFontNative(GdkFont *aFont);
|
||||
|
||||
protected:
|
||||
NS_METHOD CreateNative(GtkObject *parentWindow);
|
||||
virtual void InitCallbacks(char * aName = nsnull);
|
||||
};
|
||||
|
||||
#endif // nsButton_h__
|
||||
@@ -1,250 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsCheckButton.h"
|
||||
#include "nsString.h"
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsCheckButton, nsWidget)
|
||||
NS_IMPL_RELEASE_INHERITED(nsCheckButton, nsWidget)
|
||||
NS_IMPL_QUERY_INTERFACE2(nsCheckButton, nsICheckButton, nsIWidget)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsCheckButton constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsCheckButton::nsCheckButton() : nsWidget() , nsICheckButton()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mLabel = nsnull;
|
||||
mCheckButton = nsnull;
|
||||
mState = PR_FALSE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsCheckButton destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsCheckButton::~nsCheckButton()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsCheckButton::OnDestroySignal(GtkWidget* aGtkWidget)
|
||||
{
|
||||
if (aGtkWidget == mCheckButton) {
|
||||
mCheckButton = nsnull;
|
||||
}
|
||||
else if (aGtkWidget == mLabel) {
|
||||
mLabel = nsnull;
|
||||
}
|
||||
else {
|
||||
nsWidget::OnDestroySignal(aGtkWidget);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the native CheckButton widget
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsCheckButton::CreateNative(GtkObject *parentWindow)
|
||||
{
|
||||
mWidget = gtk_event_box_new();
|
||||
mCheckButton = gtk_check_button_new();
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(mWidget), mCheckButton);
|
||||
|
||||
gtk_widget_show(mCheckButton);
|
||||
|
||||
gtk_widget_set_name(mWidget, "nsCheckButton");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsCheckButton::InitCallbacks(char * aName)
|
||||
{
|
||||
InstallButtonPressSignal(mCheckButton);
|
||||
InstallButtonReleaseSignal(mCheckButton);
|
||||
|
||||
InstallEnterNotifySignal(mWidget);
|
||||
InstallLeaveNotifySignal(mWidget);
|
||||
|
||||
// These are needed so that the events will go to us and not our parent.
|
||||
AddToEventMask(mWidget,
|
||||
GDK_BUTTON_PRESS_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_ENTER_NOTIFY_MASK |
|
||||
GDK_EXPOSURE_MASK |
|
||||
GDK_FOCUS_CHANGE_MASK |
|
||||
GDK_KEY_PRESS_MASK |
|
||||
GDK_KEY_RELEASE_MASK |
|
||||
GDK_LEAVE_NOTIFY_MASK |
|
||||
GDK_POINTER_MOTION_MASK);
|
||||
|
||||
// Add in destroy callback
|
||||
gtk_signal_connect(GTK_OBJECT(mCheckButton),
|
||||
"destroy",
|
||||
GTK_SIGNAL_FUNC(DestroySignal),
|
||||
this);
|
||||
|
||||
InstallSignal((GtkWidget *)mCheckButton,
|
||||
(gchar *)"toggled",
|
||||
GTK_SIGNAL_FUNC(nsCheckButton::ToggledSignal));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set this button label
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsCheckButton::SetState(const PRBool aState)
|
||||
{
|
||||
mState = aState;
|
||||
|
||||
if (mWidget && mCheckButton)
|
||||
{
|
||||
GtkToggleButton * item = GTK_TOGGLE_BUTTON(mCheckButton);
|
||||
|
||||
item->active = (gboolean) mState;
|
||||
|
||||
gtk_widget_queue_draw(GTK_WIDGET(item));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set this button label
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsCheckButton::GetState(PRBool& aState)
|
||||
{
|
||||
aState = mState;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set this Checkbox label
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsCheckButton::SetLabel(const nsString& aText)
|
||||
{
|
||||
if (mWidget) {
|
||||
NS_ALLOC_STR_BUF(label, aText, 256);
|
||||
if (mLabel) {
|
||||
gtk_label_set(GTK_LABEL(mLabel), label);
|
||||
} else {
|
||||
mLabel = gtk_label_new(label);
|
||||
gtk_misc_set_alignment (GTK_MISC (mLabel), 0.0, 0.5);
|
||||
gtk_container_add(GTK_CONTAINER(mCheckButton), mLabel);
|
||||
gtk_widget_show(mLabel);
|
||||
gtk_signal_connect(GTK_OBJECT(mLabel),
|
||||
"destroy",
|
||||
GTK_SIGNAL_FUNC(DestroySignal),
|
||||
this);
|
||||
}
|
||||
NS_FREE_STR_BUF(label);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get this button label
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsCheckButton::GetLabel(nsString& aBuffer)
|
||||
{
|
||||
aBuffer.SetLength(0);
|
||||
if (mWidget) {
|
||||
char * text;
|
||||
if (mLabel) {
|
||||
gtk_label_get(GTK_LABEL(mLabel), &text);
|
||||
aBuffer.Append(text);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
nsCheckButton::OnToggledSignal(const gboolean aState)
|
||||
{
|
||||
// Untoggle the sonofabitch
|
||||
if (mWidget && mCheckButton)
|
||||
{
|
||||
GtkToggleButton * item = GTK_TOGGLE_BUTTON(mCheckButton);
|
||||
|
||||
item->active = !item->active;
|
||||
|
||||
gtk_widget_queue_draw(GTK_WIDGET(item));
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* static */ gint
|
||||
nsCheckButton::ToggledSignal(GtkWidget * aWidget,
|
||||
gpointer aData)
|
||||
{
|
||||
NS_ASSERTION( nsnull != aWidget, "widget is null");
|
||||
|
||||
nsCheckButton * button = (nsCheckButton *) aData;
|
||||
|
||||
NS_ASSERTION( nsnull != button, "instance pointer is null");
|
||||
|
||||
button->OnToggledSignal(GTK_TOGGLE_BUTTON(aWidget)->active);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// SetBackgroundColor for CheckButton
|
||||
/*virtual*/
|
||||
void nsCheckButton::SetBackgroundColorNative(GdkColor *aColorNor,
|
||||
GdkColor *aColorBri,
|
||||
GdkColor *aColorDark)
|
||||
{
|
||||
// use same style copy as SetFont
|
||||
GtkStyle *style = gtk_style_copy(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0))->style);
|
||||
|
||||
style->bg[GTK_STATE_NORMAL]=*aColorNor;
|
||||
|
||||
// Mouse over button
|
||||
style->bg[GTK_STATE_PRELIGHT]=*aColorBri;
|
||||
|
||||
// Button is down
|
||||
style->bg[GTK_STATE_ACTIVE]=*aColorDark;
|
||||
|
||||
// other states too? (GTK_STATE_ACTIVE, GTK_STATE_PRELIGHT,
|
||||
// GTK_STATE_SELECTED, GTK_STATE_INSENSITIVE)
|
||||
gtk_widget_set_style(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0)), style);
|
||||
// set style for eventbox too
|
||||
gtk_widget_set_style(mWidget, style);
|
||||
|
||||
gtk_style_unref(style);
|
||||
}
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsCheckButton_h__
|
||||
#define nsCheckButton_h__
|
||||
|
||||
#include "nsWidget.h"
|
||||
#include "nsICheckButton.h"
|
||||
|
||||
/**
|
||||
* Native GTK+ Checkbox wrapper
|
||||
*/
|
||||
|
||||
|
||||
class nsCheckButton : public nsWidget,
|
||||
public nsICheckButton
|
||||
{
|
||||
|
||||
public:
|
||||
nsCheckButton();
|
||||
virtual ~nsCheckButton();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsICheckButton part
|
||||
NS_IMETHOD SetLabel(const nsString &aText);
|
||||
NS_IMETHOD GetLabel(nsString &aBuffer);
|
||||
NS_IMETHOD SetState(const PRBool aState);
|
||||
NS_IMETHOD GetState(PRBool& aState);
|
||||
|
||||
virtual void OnToggledSignal(const gboolean aState);
|
||||
|
||||
protected:
|
||||
NS_IMETHOD CreateNative(GtkObject *parentWindow);
|
||||
virtual void InitCallbacks(char * aName = nsnull);
|
||||
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
|
||||
|
||||
// Sets background for checkbutton
|
||||
virtual void SetBackgroundColorNative(GdkColor *aColorNor,
|
||||
GdkColor *aColorBri,
|
||||
GdkColor *aColorDark);
|
||||
|
||||
GtkWidget *mLabel;
|
||||
GtkWidget *mCheckButton;
|
||||
|
||||
// We need to maintain our own state to be in sync with the
|
||||
// gecko check controlling frame.
|
||||
PRBool mState;
|
||||
|
||||
private:
|
||||
|
||||
static gint ToggledSignal(GtkWidget * aWidget,
|
||||
gpointer aData);
|
||||
};
|
||||
|
||||
#endif // nsCheckButton_h__
|
||||
@@ -1,872 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsClipboard.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsIClipboardOwner.h"
|
||||
#include "nsITransferable.h" // kTextMime
|
||||
#include "nsISupportsPrimitives.h"
|
||||
|
||||
#include "nsIWidget.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsPrimitiveHelpers.h"
|
||||
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
|
||||
// The class statics:
|
||||
GtkWidget* nsClipboard::sWidget = 0;
|
||||
|
||||
|
||||
#if defined(DEBUG_mcafee) || defined(DEBUG_pavlov)
|
||||
#define DEBUG_CLIPBOARD
|
||||
#endif
|
||||
|
||||
enum {
|
||||
TARGET_NONE,
|
||||
TARGET_TEXT_PLAIN,
|
||||
TARGET_TEXT_XIF,
|
||||
TARGET_TEXT_UNICODE,
|
||||
TARGET_TEXT_HTML,
|
||||
TARGET_AOLMAIL,
|
||||
TARGET_IMAGE_PNG,
|
||||
TARGET_IMAGE_JPEG,
|
||||
TARGET_IMAGE_GIF,
|
||||
// compatibility types
|
||||
TARGET_UTF8,
|
||||
TARGET_UNKNOWN,
|
||||
TARGET_LAST
|
||||
};
|
||||
|
||||
static GdkAtom sSelTypes[TARGET_LAST];
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsClipboard constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsClipboard::nsClipboard() : nsBaseClipboard()
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print("nsClipboard::nsClipboard()\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
//NS_INIT_REFCNT();
|
||||
mIgnoreEmptyNotification = PR_FALSE;
|
||||
mClipboardOwner = nsnull;
|
||||
mTransferable = nsnull;
|
||||
mSelectionData.data = nsnull;
|
||||
mSelectionData.length = 0;
|
||||
|
||||
// initialize the widget, etc we're binding to
|
||||
Init();
|
||||
}
|
||||
|
||||
// XXX if GTK's internal code changes this isn't going to work
|
||||
// copied from gtk code because it is a static function we can't get to it.
|
||||
// need to bug owen taylor about getting this code public.
|
||||
|
||||
typedef struct _GtkSelectionTargetList GtkSelectionTargetList;
|
||||
|
||||
struct _GtkSelectionTargetList {
|
||||
GdkAtom selection;
|
||||
GtkTargetList *list;
|
||||
};
|
||||
|
||||
static const char *gtk_selection_handler_key = "gtk-selection-handlers";
|
||||
|
||||
void __gtk_selection_target_list_remove (GtkWidget *widget)
|
||||
{
|
||||
GtkSelectionTargetList *sellist;
|
||||
GList *tmp_list;
|
||||
GList *lists;
|
||||
lists = (GList*)gtk_object_get_data (GTK_OBJECT (widget), gtk_selection_handler_key);
|
||||
tmp_list = lists;
|
||||
while (tmp_list)
|
||||
{
|
||||
sellist = (GtkSelectionTargetList*)tmp_list->data;
|
||||
gtk_target_list_unref (sellist->list);
|
||||
g_free (sellist);
|
||||
tmp_list = tmp_list->next;
|
||||
}
|
||||
g_list_free (lists);
|
||||
gtk_object_set_data (GTK_OBJECT (widget), gtk_selection_handler_key, NULL);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsClipboard destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsClipboard::~nsClipboard()
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf("nsClipboard::~nsClipboard()\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
// Remove all our event handlers:
|
||||
if (sWidget &&
|
||||
(gdk_selection_owner_get(GDK_SELECTION_PRIMARY) == sWidget->window))
|
||||
gtk_selection_remove_all(sWidget);
|
||||
|
||||
// free the selection data, if any
|
||||
if (mSelectionData.data != nsnull)
|
||||
g_free(mSelectionData.data);
|
||||
|
||||
nsClipboard *cb = (nsClipboard*)gtk_object_get_data(GTK_OBJECT(sWidget), "cb");
|
||||
if (cb != nsnull)
|
||||
{
|
||||
NS_RELEASE(cb);
|
||||
gtk_object_remove_data(GTK_OBJECT(sWidget), "cb");
|
||||
}
|
||||
|
||||
if (sWidget)
|
||||
{
|
||||
gtk_widget_destroy(sWidget);
|
||||
sWidget = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GTK Weirdness!
|
||||
// This is here in the hope of being able to call
|
||||
// gtk_selection_add_targets(w, GDK_SELECTION_PRIMARY,
|
||||
// targets,
|
||||
// 1);
|
||||
// instead of
|
||||
// gtk_selection_add_target(sWidget,
|
||||
// GDK_SELECTION_PRIMARY,
|
||||
// GDK_SELECTION_TYPE_STRING,
|
||||
// GDK_SELECTION_TYPE_STRING);
|
||||
// but it turns out that this changes the whole gtk selection model;
|
||||
// when calling add_targets copy uses selection_clear_event and the
|
||||
// data structure needs to be filled in in a way that we haven't
|
||||
// figured out; when using add_target copy uses selection_get and
|
||||
// the data structure is already filled in as much as it needs to be.
|
||||
// Some gtk internals wizard will need to solve this mystery before
|
||||
// we can use add_targets().
|
||||
//static GtkTargetEntry targets[] = {
|
||||
// { "strings n stuff", GDK_SELECTION_TYPE_STRING, GDK_SELECTION_TYPE_STRING }
|
||||
//};
|
||||
//
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void nsClipboard::Init(void)
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print("nsClipboard::Init\n");
|
||||
#endif
|
||||
|
||||
sSelTypes[TARGET_NONE] = GDK_NONE;
|
||||
sSelTypes[TARGET_TEXT_PLAIN] = gdk_atom_intern(kTextMime, FALSE);
|
||||
sSelTypes[TARGET_TEXT_XIF] = gdk_atom_intern(kXIFMime, FALSE);
|
||||
sSelTypes[TARGET_TEXT_UNICODE] = gdk_atom_intern(kUnicodeMime, FALSE);
|
||||
sSelTypes[TARGET_UTF8] = gdk_atom_intern("UTF8", FALSE);
|
||||
sSelTypes[TARGET_TEXT_HTML] = gdk_atom_intern(kHTMLMime, FALSE);
|
||||
sSelTypes[TARGET_AOLMAIL] = gdk_atom_intern(kAOLMailMime, FALSE);
|
||||
sSelTypes[TARGET_IMAGE_PNG] = gdk_atom_intern(kPNGImageMime, FALSE);
|
||||
sSelTypes[TARGET_IMAGE_JPEG] = gdk_atom_intern(kJPEGImageMime, FALSE);
|
||||
sSelTypes[TARGET_IMAGE_GIF] = gdk_atom_intern(kGIFImageMime, FALSE);
|
||||
// compatibility with other apps
|
||||
|
||||
|
||||
// create invisible widget to use for the clipboard
|
||||
sWidget = gtk_invisible_new();
|
||||
|
||||
// add the clipboard pointer to the widget so we can get it.
|
||||
gtk_object_set_data(GTK_OBJECT(sWidget), "cb", this);
|
||||
|
||||
NS_ADDREF_THIS();
|
||||
|
||||
// Handle selection requests if we called gtk_selection_add_target:
|
||||
gtk_signal_connect(GTK_OBJECT(sWidget), "selection_get",
|
||||
GTK_SIGNAL_FUNC(nsClipboard::SelectionGetCB),
|
||||
nsnull);
|
||||
|
||||
// When someone else takes the selection away:
|
||||
gtk_signal_connect(GTK_OBJECT(sWidget), "selection_clear_event",
|
||||
GTK_SIGNAL_FUNC(nsClipboard::SelectionClearCB),
|
||||
nsnull);
|
||||
|
||||
// Set up the paste handler:
|
||||
gtk_signal_connect(GTK_OBJECT(sWidget), "selection_received",
|
||||
GTK_SIGNAL_FUNC(nsClipboard::SelectionReceivedCB),
|
||||
nsnull);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsClipboard::SetNativeClipboardData()
|
||||
{
|
||||
mIgnoreEmptyNotification = PR_TRUE;
|
||||
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf(" nsClipboard::SetNativeClipboardData()\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
// make sure we have a good transferable
|
||||
if (nsnull == mTransferable) {
|
||||
printf("nsClipboard::SetNativeClipboardData(): no transferable!\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// are we already the owner?
|
||||
if (gdk_selection_owner_get(GDK_SELECTION_PRIMARY) == sWidget->window)
|
||||
{
|
||||
// if so, clear all the targets
|
||||
__gtk_selection_target_list_remove(sWidget);
|
||||
// gtk_selection_remove_all(sWidget);
|
||||
}
|
||||
|
||||
// we arn't already the owner, so we will become it
|
||||
gint have_selection = gtk_selection_owner_set(sWidget,
|
||||
GDK_SELECTION_PRIMARY,
|
||||
GDK_CURRENT_TIME);
|
||||
if (have_selection == 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// get flavor list that includes all flavors that can be written (including ones
|
||||
// obtained through conversion)
|
||||
nsCOMPtr<nsISupportsArray> flavorList;
|
||||
nsresult errCode = mTransferable->FlavorsTransferableCanExport ( getter_AddRefs(flavorList) );
|
||||
if ( NS_FAILED(errCode) )
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRUint32 cnt;
|
||||
flavorList->Count(&cnt);
|
||||
for ( PRUint32 i=0; i<cnt; ++i )
|
||||
{
|
||||
nsCOMPtr<nsISupports> genericFlavor;
|
||||
flavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) );
|
||||
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericFlavor) );
|
||||
if ( currentFlavor ) {
|
||||
nsXPIDLCString flavorStr;
|
||||
currentFlavor->ToString(getter_Copies(flavorStr));
|
||||
gint format = GetFormat(flavorStr);
|
||||
|
||||
// add these types as selection targets
|
||||
RegisterFormat(format);
|
||||
}
|
||||
}
|
||||
|
||||
mIgnoreEmptyNotification = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsClipboard::AddTarget(GdkAtom aAtom)
|
||||
{
|
||||
gtk_selection_add_target(sWidget,
|
||||
GDK_SELECTION_PRIMARY,
|
||||
aAtom, aAtom);
|
||||
}
|
||||
|
||||
gint nsClipboard::GetFormat(const char* aMimeStr)
|
||||
{
|
||||
gint type = TARGET_NONE;
|
||||
nsCAutoString mimeStr ( CBufDescriptor(NS_CONST_CAST(char*,aMimeStr), PR_TRUE, PL_strlen(aMimeStr)+1) );
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" nsClipboard::GetFormat(%s)\n", aMimeStr);
|
||||
#endif
|
||||
if (mimeStr.Equals(kTextMime)) {
|
||||
type = TARGET_TEXT_PLAIN;
|
||||
} else if (mimeStr.Equals("STRING")) {
|
||||
type = TARGET_TEXT_PLAIN;
|
||||
} else if (mimeStr.Equals(kXIFMime)) {
|
||||
type = TARGET_TEXT_XIF;
|
||||
} else if (mimeStr.Equals(kUnicodeMime)) {
|
||||
type = TARGET_TEXT_UNICODE;
|
||||
} else if (mimeStr.Equals(kHTMLMime)) {
|
||||
type = TARGET_TEXT_HTML;
|
||||
} else if (mimeStr.Equals(kAOLMailMime)) {
|
||||
type = TARGET_AOLMAIL;
|
||||
} else if (mimeStr.Equals(kPNGImageMime)) {
|
||||
type = TARGET_IMAGE_PNG;
|
||||
} else if (mimeStr.Equals(kJPEGImageMime)) {
|
||||
type = TARGET_IMAGE_JPEG;
|
||||
} else if (mimeStr.Equals(kGIFImageMime)) {
|
||||
type = TARGET_IMAGE_GIF;
|
||||
}
|
||||
|
||||
#ifdef WE_DO_DND
|
||||
else if (mimeStr.Equals(kDropFilesMime)) {
|
||||
format = CF_HDROP;
|
||||
} else {
|
||||
format = ::RegisterClipboardFormat(aMimeStr);
|
||||
}
|
||||
#endif
|
||||
return type;
|
||||
}
|
||||
|
||||
void nsClipboard::RegisterFormat(gint format)
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" nsClipboard::RegisterFormat(%s)\n", gdk_atom_name(sSelTypes[format]));
|
||||
#endif
|
||||
|
||||
/* when doing the selection_add_target, each case should have the same last parameter
|
||||
which matches the case match */
|
||||
switch(format)
|
||||
{
|
||||
case TARGET_TEXT_PLAIN:
|
||||
// text/plain (default)
|
||||
AddTarget(sSelTypes[format]);
|
||||
|
||||
// STRING (what X uses)
|
||||
AddTarget(GDK_SELECTION_TYPE_STRING);
|
||||
break;
|
||||
|
||||
|
||||
case TARGET_TEXT_XIF:
|
||||
// text/xif (default)
|
||||
AddTarget(sSelTypes[format]);
|
||||
break;
|
||||
|
||||
|
||||
case TARGET_TEXT_UNICODE:
|
||||
// text/unicode (default)
|
||||
AddTarget(sSelTypes[format]);
|
||||
|
||||
// UTF8 (what X uses)
|
||||
AddTarget(sSelTypes[TARGET_UTF8]);
|
||||
break;
|
||||
|
||||
|
||||
case TARGET_TEXT_HTML:
|
||||
// text/html (default)
|
||||
AddTarget(sSelTypes[format]);
|
||||
break;
|
||||
|
||||
|
||||
case TARGET_AOLMAIL:
|
||||
// text/aolmail (default)
|
||||
AddTarget(sSelTypes[format]);
|
||||
break;
|
||||
|
||||
|
||||
case TARGET_IMAGE_PNG:
|
||||
// image/png (default)
|
||||
AddTarget(sSelTypes[format]);
|
||||
break;
|
||||
|
||||
|
||||
case TARGET_IMAGE_JPEG:
|
||||
// image/jpeg (default)
|
||||
AddTarget(sSelTypes[format]);
|
||||
break;
|
||||
|
||||
|
||||
case TARGET_IMAGE_GIF:
|
||||
// image/gif (default)
|
||||
AddTarget(sSelTypes[format]);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
// if we don't match something above, then just add it like its something we know about...
|
||||
AddTarget(sSelTypes[format]);
|
||||
}
|
||||
}
|
||||
|
||||
PRBool nsClipboard::DoRealConvert(GdkAtom type)
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" nsClipboard::DoRealConvert(%li)\n {\n", type);
|
||||
#endif
|
||||
int e = 0;
|
||||
// Set a flag saying that we're blocking waiting for the callback:
|
||||
mBlocking = PR_TRUE;
|
||||
|
||||
//
|
||||
// ask X what kind of data we can get
|
||||
//
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" Doing real conversion of atom type '%s'\n", gdk_atom_name(type));
|
||||
#endif
|
||||
gtk_selection_convert(sWidget,
|
||||
GDK_SELECTION_PRIMARY,
|
||||
type,
|
||||
GDK_CURRENT_TIME);
|
||||
|
||||
// Now we need to wait until the callback comes in ...
|
||||
// i is in case we get a runaway (yuck).
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf(" Waiting for the callback... mBlocking = %d\n", mBlocking);
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
for (e=0; mBlocking == PR_TRUE && e < 1000; ++e)
|
||||
{
|
||||
gtk_main_iteration_do(PR_TRUE);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" }\n");
|
||||
#endif
|
||||
|
||||
if (mSelectionData.length > 0)
|
||||
return PR_TRUE;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/* return PR_TRUE if we have converted or PR_FALSE if we havn't and need to keep being called */
|
||||
PRBool nsClipboard::DoConvert(gint format)
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" nsClipboard::DoConvert(%s)\n", gdk_atom_name(sSelTypes[format]));
|
||||
#endif
|
||||
|
||||
/* when doing the selection_add_target, each case should have the same last parameter
|
||||
which matches the case match */
|
||||
PRBool r = PR_FALSE;
|
||||
|
||||
switch(format)
|
||||
{
|
||||
case TARGET_TEXT_PLAIN:
|
||||
r = DoRealConvert(sSelTypes[format]);
|
||||
if (r) return r;
|
||||
r = DoRealConvert(GDK_SELECTION_TYPE_STRING);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case TARGET_TEXT_XIF:
|
||||
r = DoRealConvert(sSelTypes[format]);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case TARGET_TEXT_UNICODE:
|
||||
r = DoRealConvert(sSelTypes[format]);
|
||||
if (r) return r;
|
||||
r = DoRealConvert(sSelTypes[TARGET_UTF8]);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case TARGET_TEXT_HTML:
|
||||
r = DoRealConvert(sSelTypes[format]);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case TARGET_AOLMAIL:
|
||||
r = DoRealConvert(sSelTypes[format]);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case TARGET_IMAGE_PNG:
|
||||
r = DoRealConvert(sSelTypes[format]);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case TARGET_IMAGE_JPEG:
|
||||
r = DoRealConvert(sSelTypes[format]);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case TARGET_IMAGE_GIF:
|
||||
r = DoRealConvert(sSelTypes[format]);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_print("DoConvert called with bogus format\n");
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// The blocking Paste routine
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP
|
||||
nsClipboard::GetNativeClipboardData(nsITransferable * aTransferable)
|
||||
{
|
||||
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf("nsClipboard::GetNativeClipboardData()\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
// make sure we have a good transferable
|
||||
if (nsnull == aTransferable) {
|
||||
printf(" GetNativeClipboardData: Transferable is null!\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// get flavor list that includes all acceptable flavors (including ones obtained through
|
||||
// conversion)
|
||||
nsCOMPtr<nsISupportsArray> flavorList;
|
||||
nsresult errCode = aTransferable->FlavorsTransferableCanImport ( getter_AddRefs(flavorList) );
|
||||
if ( NS_FAILED(errCode) )
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Walk through flavors and see which flavor matches the one being pasted:
|
||||
PRUint32 cnt;
|
||||
flavorList->Count(&cnt);
|
||||
nsCAutoString foundFlavor;
|
||||
for ( PRUint32 i = 0; i < cnt; ++i ) {
|
||||
nsCOMPtr<nsISupports> genericFlavor;
|
||||
flavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) );
|
||||
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericFlavor) );
|
||||
if ( currentFlavor ) {
|
||||
nsXPIDLCString flavorStr;
|
||||
currentFlavor->ToString ( getter_Copies(flavorStr) );
|
||||
gint format = GetFormat(flavorStr);
|
||||
if (DoConvert(format)) {
|
||||
foundFlavor = flavorStr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf(" Got the callback: '%s', %d\n",
|
||||
mSelectionData.data, mSelectionData.length);
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
// We're back from the callback, no longer blocking:
|
||||
mBlocking = PR_FALSE;
|
||||
|
||||
//
|
||||
// Now we have data in mSelectionData.data.
|
||||
// We just have to copy it to the transferable.
|
||||
//
|
||||
|
||||
#if 0
|
||||
// pinkerton - we have the flavor already from above, so we don't need
|
||||
// to re-derrive it.
|
||||
nsString *name = new nsString((const char*)gdk_atom_name(mSelectionData.type));
|
||||
int format = GetFormat(*name);
|
||||
df->SetString((const char*)gdk_atom_name(sSelTypes[format]));
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsISupports> genericDataWrapper;
|
||||
nsPrimitiveHelpers::CreatePrimitiveForData ( foundFlavor, mSelectionData.data, mSelectionData.length, getter_AddRefs(genericDataWrapper) );
|
||||
aTransferable->SetTransferData(foundFlavor,
|
||||
genericDataWrapper,
|
||||
mSelectionData.length);
|
||||
|
||||
//delete name;
|
||||
|
||||
// transferable is now copying the data, so we can free it.
|
||||
// g_free(mSelectionData.data);
|
||||
mSelectionData.data = nsnull;
|
||||
mSelectionData.length = 0;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the data from a paste comes in (recieved from gdk_selection_convert)
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aSelectionData gtk selection stuff
|
||||
* @param aTime time the selection was requested
|
||||
*/
|
||||
void
|
||||
nsClipboard::SelectionReceivedCB (GtkWidget *aWidget,
|
||||
GtkSelectionData *aSelectionData,
|
||||
guint aTime)
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf(" nsClipboard::SelectionReceivedCB\n {\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
nsClipboard *cb =(nsClipboard *)gtk_object_get_data(GTK_OBJECT(aWidget),
|
||||
"cb");
|
||||
if (!cb)
|
||||
{
|
||||
g_print("no clipboard found.. this is bad.\n");
|
||||
return;
|
||||
}
|
||||
cb->SelectionReceiver(aWidget, aSelectionData);
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" }\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* local method (called from nsClipboard::SelectionReceivedCB)
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aSelectionData gtk selection stuff
|
||||
*/
|
||||
void
|
||||
nsClipboard::SelectionReceiver (GtkWidget *aWidget,
|
||||
GtkSelectionData *aSD)
|
||||
{
|
||||
gint type;
|
||||
|
||||
mBlocking = PR_FALSE;
|
||||
|
||||
if (aSD->length < 0)
|
||||
{
|
||||
printf(" Error retrieving selection: length was %d\n",
|
||||
aSD->length);
|
||||
return;
|
||||
}
|
||||
|
||||
type = TARGET_NONE;
|
||||
for (int i=0; i < TARGET_LAST; i++)
|
||||
{
|
||||
if (sSelTypes[i] == aSD->type)
|
||||
{
|
||||
type = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GDK_TARGET_STRING:
|
||||
case TARGET_UTF8:
|
||||
case TARGET_TEXT_PLAIN:
|
||||
case TARGET_TEXT_XIF:
|
||||
case TARGET_TEXT_UNICODE:
|
||||
case TARGET_TEXT_HTML:
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" Copying mSelectionData pointer -- ");
|
||||
#endif
|
||||
mSelectionData = *aSD;
|
||||
mSelectionData.data = g_new(guchar, aSD->length + 1);
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" Data = %s\n Length = %i\n", aSD->data, aSD->length);
|
||||
#endif
|
||||
memcpy(mSelectionData.data,
|
||||
aSD->data,
|
||||
aSD->length);
|
||||
// Null terminate in case anyone cares,
|
||||
// and so we can print the string for debugging:
|
||||
mSelectionData.data[aSD->length] = '\0';
|
||||
mSelectionData.length = aSD->length;
|
||||
return;
|
||||
|
||||
default:
|
||||
mSelectionData = *aSD;
|
||||
mSelectionData.data = g_new(guchar, aSD->length + 1);
|
||||
memcpy(mSelectionData.data,
|
||||
aSD->data,
|
||||
aSD->length);
|
||||
mSelectionData.length = aSD->length;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Some platforms support deferred notification for putting data on the clipboard
|
||||
* This method forces the data onto the clipboard in its various formats
|
||||
* This may be used if the application going away.
|
||||
*
|
||||
* @result NS_OK if successful.
|
||||
*/
|
||||
NS_IMETHODIMP nsClipboard::ForceDataToClipboard()
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf(" nsClipboard::ForceDataToClipboard()\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
// make sure we have a good transferable
|
||||
if (nsnull == mTransferable) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsClipboard::HasDataMatchingFlavors(nsISupportsArray* aFlavorList, PRBool * outResult)
|
||||
{
|
||||
*outResult = PR_TRUE; // say we always do.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is the callback which is called when another app
|
||||
* requests the selection.
|
||||
*
|
||||
* @param widget The widget
|
||||
* @param aSelectionData Selection data
|
||||
* @param info Value passed in from the callback init
|
||||
* @param time Time when the selection request came in
|
||||
*/
|
||||
void nsClipboard::SelectionGetCB(GtkWidget *widget,
|
||||
GtkSelectionData *aSelectionData,
|
||||
guint aInfo,
|
||||
guint aTime)
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf("nsClipboard::SelectionGetCB\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
nsClipboard *cb = (nsClipboard *)gtk_object_get_data(GTK_OBJECT(widget),
|
||||
"cb");
|
||||
|
||||
void *clipboardData;
|
||||
PRUint32 dataLength;
|
||||
nsresult rv;
|
||||
|
||||
// Make sure we have a transferable:
|
||||
if (!cb->mTransferable) {
|
||||
printf("Clipboard has no transferable!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" aInfo == %d -", aInfo);
|
||||
#endif
|
||||
|
||||
char* dataFlavor = nsnull;
|
||||
|
||||
// switch aInfo (atom) to our enum
|
||||
int type = (int)aInfo;
|
||||
for (int i=0; i < TARGET_LAST; i++)
|
||||
{
|
||||
if (sSelTypes[i] == aInfo)
|
||||
{
|
||||
type = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case GDK_TARGET_STRING:
|
||||
case TARGET_TEXT_PLAIN:
|
||||
dataFlavor = kTextMime;
|
||||
break;
|
||||
case TARGET_TEXT_XIF:
|
||||
dataFlavor = kXIFMime;
|
||||
break;
|
||||
case TARGET_TEXT_UNICODE:
|
||||
case TARGET_UTF8:
|
||||
dataFlavor = kUnicodeMime;
|
||||
break;
|
||||
case TARGET_TEXT_HTML:
|
||||
dataFlavor = kHTMLMime;
|
||||
break;
|
||||
case TARGET_AOLMAIL:
|
||||
dataFlavor = kAOLMailMime;
|
||||
break;
|
||||
case TARGET_IMAGE_PNG:
|
||||
dataFlavor = kPNGImageMime;
|
||||
break;
|
||||
case TARGET_IMAGE_JPEG:
|
||||
dataFlavor = kJPEGImageMime;
|
||||
break;
|
||||
case TARGET_IMAGE_GIF:
|
||||
dataFlavor = kGIFImageMime;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
/* handle outside things */
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print("- aInfo is for %s\n", gdk_atom_name(aInfo));
|
||||
#endif
|
||||
|
||||
// Get data out of transferable.
|
||||
nsCOMPtr<nsISupports> genericDataWrapper;
|
||||
rv = cb->mTransferable->GetTransferData(dataFlavor,
|
||||
getter_AddRefs(genericDataWrapper),
|
||||
&dataLength);
|
||||
nsPrimitiveHelpers::CreateDataFromPrimitive ( dataFlavor, genericDataWrapper, &clipboardData, dataLength );
|
||||
if (NS_SUCCEEDED(rv) && clipboardData && dataLength > 0) {
|
||||
size_t size = 1;
|
||||
// find the number of bytes in the data for the below thing
|
||||
// size_t size = sizeof((void*)((unsigned char)clipboardData[0]));
|
||||
// g_print("************ ***************** ******************* %i\n", size);
|
||||
|
||||
gtk_selection_data_set(aSelectionData,
|
||||
aInfo, size*8,
|
||||
(unsigned char *)clipboardData,
|
||||
dataLength);
|
||||
nsCRT::free ( NS_REINTERPRET_CAST(char*, clipboardData) );
|
||||
}
|
||||
else
|
||||
printf("Transferable didn't support the data flavor\n");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called when another app requests selection ownership
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aEvent the GdkEvent for the selection
|
||||
* @param aData value passed in from the callback init
|
||||
*/
|
||||
void nsClipboard::SelectionClearCB(GtkWidget *aWidget,
|
||||
GdkEventSelection *aEvent,
|
||||
gpointer aData)
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf(" nsClipboard::SelectionClearCB\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
nsClipboard *cb = (nsClipboard *)gtk_object_get_data(GTK_OBJECT(aWidget),
|
||||
"cb");
|
||||
|
||||
cb->EmptyClipboard();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The routine called when another app asks for the content of the selection
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aSelectionData gtk selection stuff
|
||||
* @param aData value passed in from the callback init
|
||||
*/
|
||||
void
|
||||
nsClipboard::SelectionRequestCB (GtkWidget *aWidget,
|
||||
GtkSelectionData *aSelectionData,
|
||||
gpointer aData)
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf(" nsClipboard::SelectionRequestCB\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
}
|
||||
|
||||
/**
|
||||
* ...
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aSelectionData gtk selection stuff
|
||||
* @param aData value passed in from the callback init
|
||||
*/
|
||||
void
|
||||
nsClipboard::SelectionNotifyCB (GtkWidget *aWidget,
|
||||
GtkSelectionData *aSelectionData,
|
||||
gpointer aData)
|
||||
{
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf(" nsClipboard::SelectionNotifyCB\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsClipboard_h__
|
||||
#define nsClipboard_h__
|
||||
|
||||
#include "nsBaseClipboard.h"
|
||||
#include <gtk/gtk.h>
|
||||
#include <gtk/gtkinvisible.h>
|
||||
|
||||
class nsITransferable;
|
||||
class nsIClipboardOwner;
|
||||
class nsIWidget;
|
||||
|
||||
/**
|
||||
* Native Gtk Clipboard wrapper
|
||||
*/
|
||||
|
||||
class nsClipboard : public nsBaseClipboard
|
||||
{
|
||||
|
||||
public:
|
||||
nsClipboard();
|
||||
virtual ~nsClipboard();
|
||||
|
||||
// nsIClipboard
|
||||
NS_IMETHOD ForceDataToClipboard();
|
||||
NS_IMETHOD HasDataMatchingFlavors(nsISupportsArray* aFlavorList, PRBool * outResult);
|
||||
|
||||
// invisible widget. also used by dragndrop
|
||||
static GtkWidget *sWidget;
|
||||
|
||||
protected:
|
||||
NS_IMETHOD SetNativeClipboardData();
|
||||
NS_IMETHOD GetNativeClipboardData(nsITransferable * aTransferable);
|
||||
|
||||
PRBool mIgnoreEmptyNotification;
|
||||
|
||||
void AddTarget(GdkAtom aAtom);
|
||||
|
||||
gint GetFormat(const char* aMimeStr);
|
||||
void RegisterFormat(gint format);
|
||||
|
||||
|
||||
PRBool DoRealConvert(GdkAtom type);
|
||||
PRBool DoConvert(gint format);
|
||||
|
||||
void Init(void);
|
||||
|
||||
// Used for communicating pasted data
|
||||
// from the asynchronous X routines back to a blocking paste:
|
||||
GtkSelectionData mSelectionData;
|
||||
PRBool mBlocking;
|
||||
|
||||
void SelectionReceiver(GtkWidget *aWidget,
|
||||
GtkSelectionData *aSD);
|
||||
|
||||
/**
|
||||
* This is the callback which is called when another app
|
||||
* requests the selection.
|
||||
*
|
||||
* @param widget The widget
|
||||
* @param aSelectionData Selection data
|
||||
* @param info Value passed in from the callback init
|
||||
* @param time Time when the selection request came in
|
||||
*/
|
||||
static void SelectionGetCB(GtkWidget *aWidget,
|
||||
GtkSelectionData *aSelectionData,
|
||||
guint /*info*/,
|
||||
guint /*time*/);
|
||||
|
||||
/**
|
||||
* Called when another app requests selection ownership
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aEvent the GdkEvent for the selection
|
||||
* @param aData value passed in from the callback init
|
||||
*/
|
||||
static void SelectionClearCB(GtkWidget *aWidget,
|
||||
GdkEventSelection *aEvent,
|
||||
gpointer aData);
|
||||
|
||||
/**
|
||||
* The routine called when another app asks for the content of the selection
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aSelectionData gtk selection stuff
|
||||
* @param aData value passed in from the callback init
|
||||
*/
|
||||
static void SelectionRequestCB(GtkWidget *aWidget,
|
||||
GtkSelectionData *aSelectionData,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* Called when the data from a paste comes in
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aSelectionData gtk selection stuff
|
||||
* @param aTime time the selection was requested
|
||||
*/
|
||||
static void SelectionReceivedCB(GtkWidget *aWidget,
|
||||
GtkSelectionData *aSelectionData,
|
||||
guint aTime);
|
||||
|
||||
|
||||
static void SelectionNotifyCB(GtkWidget *aWidget,
|
||||
GtkSelectionData *aSelectionData,
|
||||
gpointer aData);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // nsClipboard_h__
|
||||
@@ -1,357 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "nsComboBox.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#define DBG 0
|
||||
|
||||
#define INITIAL_MAX_ITEMS 128
|
||||
#define ITEMS_GROWSIZE 128
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsComboBox, nsWidget)
|
||||
NS_IMPL_RELEASE_INHERITED(nsComboBox, nsWidget)
|
||||
NS_IMPL_QUERY_INTERFACE3(nsComboBox, nsIComboBox, nsIListWidget, nsIWidget)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsComboBox constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsComboBox::nsComboBox() : nsWidget(), nsIListWidget(), nsIComboBox()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mMultiSelect = PR_FALSE;
|
||||
mItems = nsnull;
|
||||
mNumItems = 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsComboBox:: destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsComboBox::~nsComboBox()
|
||||
{
|
||||
if (mItems) {
|
||||
for (GList *items = mItems; items; items = (GList*) g_list_next(items)){
|
||||
g_free(items->data);
|
||||
}
|
||||
g_list_free(mItems);
|
||||
}
|
||||
gtk_widget_destroy(mCombo);
|
||||
}
|
||||
|
||||
void nsComboBox::InitCallbacks(char * aName)
|
||||
{
|
||||
InstallButtonPressSignal(mWidget);
|
||||
InstallButtonReleaseSignal(mWidget);
|
||||
|
||||
InstallEnterNotifySignal(mWidget);
|
||||
InstallLeaveNotifySignal(mWidget);
|
||||
|
||||
// These are needed so that the events will go to us and not our parent.
|
||||
AddToEventMask(mWidget,
|
||||
GDK_BUTTON_PRESS_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_ENTER_NOTIFY_MASK |
|
||||
GDK_EXPOSURE_MASK |
|
||||
GDK_FOCUS_CHANGE_MASK |
|
||||
GDK_KEY_PRESS_MASK |
|
||||
GDK_KEY_RELEASE_MASK |
|
||||
GDK_LEAVE_NOTIFY_MASK |
|
||||
GDK_POINTER_MOTION_MASK);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// initializer
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NS_METHOD nsComboBox::SetMultipleSelection(PRBool aMultipleSelections)
|
||||
{
|
||||
mMultiSelect = aMultipleSelections;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// AddItemAt
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NS_METHOD nsComboBox::AddItemAt(nsString &aItem, PRInt32 aPosition)
|
||||
{
|
||||
NS_ALLOC_STR_BUF(val, aItem, 256);
|
||||
mItems = g_list_insert( mItems, g_strdup(val), aPosition );
|
||||
mNumItems++;
|
||||
if (mCombo) {
|
||||
gtk_combo_set_popdown_strings( GTK_COMBO( mCombo ), mItems );
|
||||
}
|
||||
NS_FREE_STR_BUF(val);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Finds an item at a postion
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRInt32 nsComboBox::FindItem(nsString &aItem, PRInt32 aStartPos)
|
||||
{
|
||||
NS_ALLOC_STR_BUF(val, aItem, 256);
|
||||
int i;
|
||||
PRInt32 inx = -1;
|
||||
GList *items = g_list_nth(mItems, aStartPos);
|
||||
for(i=0; items != NULL; items = (GList *) g_list_next(items), i++ )
|
||||
{
|
||||
if(!strcmp(val, (gchar *) items->data))
|
||||
{
|
||||
inx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
NS_FREE_STR_BUF(val);
|
||||
return inx;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// CountItems - Get Item Count
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRInt32 nsComboBox::GetItemCount()
|
||||
{
|
||||
return (PRInt32)mNumItems;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Removes an Item at a specified location
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool nsComboBox::RemoveItemAt(PRInt32 aPosition)
|
||||
{
|
||||
if (aPosition >= 0 && aPosition < mNumItems) {
|
||||
|
||||
g_free(g_list_nth(mItems, aPosition)->data);
|
||||
mItems = g_list_remove_link(mItems, g_list_nth(mItems, aPosition));
|
||||
mNumItems--;
|
||||
if (mCombo) {
|
||||
gtk_combo_set_popdown_strings(GTK_COMBO( mCombo ), mItems);
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
else
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Removes an Item at a specified location
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool nsComboBox::GetItemAt(nsString& anItem, PRInt32 aPosition)
|
||||
{
|
||||
if (aPosition >= 0 && aPosition < mNumItems) {
|
||||
anItem = (gchar *) g_list_nth(mItems, aPosition)->data;
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Gets the selected of selected item
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsComboBox::GetSelectedItem(nsString& aItem)
|
||||
{
|
||||
aItem.Truncate();
|
||||
if (mCombo) {
|
||||
aItem = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(mCombo)->entry));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Gets the list of selected otems
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRInt32 nsComboBox::GetSelectedIndex()
|
||||
{
|
||||
nsString nsstring;
|
||||
GetSelectedItem(nsstring);
|
||||
return FindItem(nsstring, 0);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// SelectItem
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsComboBox::SelectItem(PRInt32 aPosition)
|
||||
{
|
||||
GList *pos;
|
||||
if (!mItems)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
pos = g_list_nth(mItems, aPosition);
|
||||
if (!pos)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mCombo) {
|
||||
gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(mCombo)->entry),
|
||||
(gchar *) pos->data);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// GetSelectedCount
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRInt32 nsComboBox::GetSelectedCount()
|
||||
{
|
||||
if (!mMultiSelect) {
|
||||
PRInt32 inx = GetSelectedIndex();
|
||||
return (inx == -1? 0 : 1);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// GetSelectedIndices
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsComboBox::GetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize)
|
||||
{
|
||||
// this is an error
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Deselect
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsComboBox::Deselect()
|
||||
{
|
||||
if (mMultiSelect) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the native GtkCombo widget
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsComboBox::CreateNative(GtkObject *parentWindow)
|
||||
{
|
||||
mWidget = ::gtk_event_box_new();
|
||||
|
||||
::gtk_widget_set_name(mWidget, "nsComboBox");
|
||||
mCombo = ::gtk_combo_new();
|
||||
gtk_widget_show(mCombo);
|
||||
|
||||
/* make the stuff uneditable */
|
||||
gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(mCombo)->entry), PR_FALSE);
|
||||
|
||||
gtk_signal_connect(GTK_OBJECT(mCombo),
|
||||
"destroy",
|
||||
GTK_SIGNAL_FUNC(DestroySignal),
|
||||
this);
|
||||
gtk_signal_connect(GTK_OBJECT(GTK_COMBO(mCombo)->popwin),
|
||||
"unmap",
|
||||
GTK_SIGNAL_FUNC(UnmapSignal),
|
||||
this);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(mWidget), mCombo);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsComboBox::OnDestroySignal(GtkWidget* aGtkWidget)
|
||||
{
|
||||
if (aGtkWidget == mCombo) {
|
||||
mCombo = nsnull;
|
||||
}
|
||||
else {
|
||||
nsWidget::OnDestroySignal(aGtkWidget);
|
||||
}
|
||||
}
|
||||
|
||||
gint
|
||||
nsComboBox::UnmapSignal(GtkWidget* aGtkWidget, nsComboBox* aCombo)
|
||||
{
|
||||
if (!aCombo) return PR_FALSE;
|
||||
aCombo->OnUnmapSignal(aGtkWidget);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nsComboBox::OnUnmapSignal(GtkWidget * aWidget)
|
||||
{
|
||||
if (!aWidget) return;
|
||||
|
||||
// Generate a NS_CONTROL_CHANGE event and send it to the frame
|
||||
nsGUIEvent event;
|
||||
event.eventStructType = NS_GUI_EVENT;
|
||||
nsPoint point(0,0);
|
||||
InitEvent(event, NS_CONTROL_CHANGE, &point);
|
||||
DispatchWindowEvent(&event);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get handle for style
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
/*virtual*/
|
||||
void nsComboBox::SetFontNative(GdkFont *aFont)
|
||||
{
|
||||
GtkStyle *style = gtk_style_copy(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0))->style);
|
||||
// gtk_style_copy ups the ref count of the font
|
||||
gdk_font_unref (style->font);
|
||||
|
||||
style->font = aFont;
|
||||
gdk_font_ref(style->font);
|
||||
|
||||
gtk_widget_set_style(GTK_BIN (mWidget)->child, style);
|
||||
|
||||
gtk_style_unref(style);
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsComboBox_h__
|
||||
#define nsComboBox_h__
|
||||
|
||||
#include "nsWidget.h"
|
||||
#include "nsIComboBox.h"
|
||||
|
||||
/**
|
||||
* Native GTK+ Listbox wrapper
|
||||
*/
|
||||
|
||||
class nsComboBox : public nsWidget,
|
||||
public nsIListWidget,
|
||||
public nsIComboBox
|
||||
{
|
||||
|
||||
public:
|
||||
nsComboBox();
|
||||
virtual ~nsComboBox();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIComboBox interface
|
||||
NS_IMETHOD AddItemAt(nsString &aItem, PRInt32 aPosition);
|
||||
virtual PRInt32 FindItem(nsString &aItem, PRInt32 aStartPos);
|
||||
virtual PRInt32 GetItemCount();
|
||||
virtual PRBool RemoveItemAt(PRInt32 aPosition);
|
||||
virtual PRBool GetItemAt(nsString& anItem, PRInt32 aPosition);
|
||||
NS_IMETHOD GetSelectedItem(nsString& aItem);
|
||||
virtual PRInt32 GetSelectedIndex();
|
||||
NS_IMETHOD SelectItem(PRInt32 aPosition);
|
||||
NS_IMETHOD Deselect() ;
|
||||
|
||||
// nsIComboBox interface
|
||||
NS_IMETHOD SetMultipleSelection(PRBool aMultipleSelections);
|
||||
PRInt32 GetSelectedCount();
|
||||
NS_IMETHOD GetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize);
|
||||
|
||||
virtual void SetFontNative(GdkFont *aFont);
|
||||
|
||||
protected:
|
||||
NS_IMETHOD CreateNative(GtkObject *parentWindow);
|
||||
virtual void InitCallbacks(char * aName = nsnull);
|
||||
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
|
||||
virtual void OnUnmapSignal(GtkWidget* aWidget);
|
||||
static gint UnmapSignal(GtkWidget* aGtkWidget, nsComboBox* aCombo);
|
||||
|
||||
GtkWidget *mCombo; /* workaround for gtkcombo bug */
|
||||
GList *mItems;
|
||||
PRBool mMultiSelect;
|
||||
int mNumItems;
|
||||
};
|
||||
|
||||
#endif // nsComboBox_h__
|
||||
@@ -1,744 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "nsContextMenu.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIMenuBar.h"
|
||||
#include "nsIMenuItem.h"
|
||||
#include "nsIMenuListener.h"
|
||||
#include "nsString.h"
|
||||
#include "nsGtkEventHandler.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
|
||||
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
|
||||
static NS_DEFINE_CID(kMenuItemCID, NS_MENUITEM_CID);
|
||||
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsresult nsContextMenu::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
*aInstancePtr = NULL;
|
||||
|
||||
if (aIID.Equals(nsIMenu::GetIID())) {
|
||||
*aInstancePtr = (void*)(nsIMenu*) this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kISupportsIID)) {
|
||||
*aInstancePtr = (void*)(nsISupports*)(nsIMenu*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(nsIMenuListener::GetIID())) {
|
||||
*aInstancePtr = (void*)(nsIMenuListener*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMPL_ADDREF(nsContextMenu)
|
||||
NS_IMPL_RELEASE(nsContextMenu)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsContextMenu constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsContextMenu::nsContextMenu()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mNumMenuItems = 0;
|
||||
mMenu = nsnull;
|
||||
mParent = nsnull;
|
||||
mListener = nsnull;
|
||||
mConstructCalled = PR_FALSE;
|
||||
|
||||
mDOMNode = nsnull;
|
||||
mWebShell = nsnull;
|
||||
mDOMElement = nsnull;
|
||||
|
||||
mAlignment = "topleft";
|
||||
mAnchorAlignment = "none";
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsContextMenu destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsContextMenu::~nsContextMenu()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the proper widget
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::Create(nsISupports *aParent,
|
||||
const nsString& anAlignment,
|
||||
const nsString& anAnchorAlignment)
|
||||
{
|
||||
if(aParent)
|
||||
{
|
||||
nsIWidget *parent = nsnull;
|
||||
aParent->QueryInterface(nsIWidget::GetIID(), (void**) &parent);
|
||||
if(parent)
|
||||
{
|
||||
mParent = parent;
|
||||
NS_RELEASE(parent);
|
||||
}
|
||||
}
|
||||
|
||||
mAlignment = anAlignment;
|
||||
mAnchorAlignment = anAnchorAlignment;
|
||||
|
||||
mMenu = gtk_menu_new();
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (mMenu), "map",
|
||||
GTK_SIGNAL_FUNC(menu_map_handler),
|
||||
this);
|
||||
gtk_signal_connect (GTK_OBJECT (mMenu), "unmap",
|
||||
GTK_SIGNAL_FUNC(menu_unmap_handler),
|
||||
this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::GetParent(nsISupports*& aParent)
|
||||
{
|
||||
aParent = nsnull;
|
||||
if (nsnull != mParent) {
|
||||
return mParent->QueryInterface(kISupportsIID,
|
||||
(void**)&aParent);
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::AddItem(nsISupports * aItem)
|
||||
{
|
||||
if(aItem)
|
||||
{
|
||||
nsIMenuItem * menuitem = nsnull;
|
||||
aItem->QueryInterface(nsIMenuItem::GetIID(),
|
||||
(void**)&menuitem);
|
||||
if(menuitem)
|
||||
{
|
||||
AddMenuItem(menuitem); // nsMenu now owns this
|
||||
NS_RELEASE(menuitem);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsIMenu * menu = nsnull;
|
||||
aItem->QueryInterface(nsIMenu::GetIID(),
|
||||
(void**)&menu);
|
||||
if(menu)
|
||||
{
|
||||
AddMenu(menu); // nsMenu now owns this
|
||||
NS_RELEASE(menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::AddMenuItem(nsIMenuItem * aMenuItem)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
void *voidData;
|
||||
|
||||
aMenuItem->GetNativeData(voidData);
|
||||
widget = GTK_WIDGET(voidData);
|
||||
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
|
||||
|
||||
// XXX add aMenuItem to internal data structor list
|
||||
// Need to be adding an nsISupports *, not nsIMenuItem *
|
||||
nsISupports * supports = nsnull;
|
||||
aMenuItem->QueryInterface(kISupportsIID,
|
||||
(void**)&supports);
|
||||
{
|
||||
mMenuItemVoidArray.AppendElement(supports);
|
||||
mNumMenuItems++;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::AddMenu(nsIMenu * aMenu)
|
||||
{
|
||||
nsString Label;
|
||||
GtkWidget *newmenu=nsnull;
|
||||
char *labelStr;
|
||||
void *voidData=NULL;
|
||||
|
||||
aMenu->GetLabel(Label);
|
||||
labelStr = Label.ToNewCString();
|
||||
|
||||
// Create nsMenuItem
|
||||
nsIMenuItem * pnsMenuItem = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(kMenuItemCID,
|
||||
nsnull,
|
||||
nsIMenuItem::GetIID(),
|
||||
(void**)&pnsMenuItem);
|
||||
if (NS_OK == rv) {
|
||||
nsISupports * supports = nsnull;
|
||||
QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pnsMenuItem->Create(supports, labelStr, PR_FALSE); //PR_TRUE);
|
||||
NS_RELEASE(supports);
|
||||
|
||||
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
AddItem(supports); // Parent should now own menu item
|
||||
NS_RELEASE(supports);
|
||||
|
||||
void * menuitem = nsnull;
|
||||
pnsMenuItem->GetNativeData(menuitem);
|
||||
|
||||
voidData = NULL;
|
||||
aMenu->GetNativeData(&voidData);
|
||||
newmenu = GTK_WIDGET(voidData);
|
||||
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), newmenu);
|
||||
|
||||
NS_RELEASE(pnsMenuItem);
|
||||
}
|
||||
|
||||
nsCRT::free(labelStr);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::AddSeparator()
|
||||
{
|
||||
// Create nsMenuItem
|
||||
nsIMenuItem * pnsMenuItem = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(
|
||||
kMenuItemCID, nsnull, nsIMenuItem::GetIID(), (void**)&pnsMenuItem);
|
||||
if (NS_OK == rv) {
|
||||
nsString tmp = "separator";
|
||||
nsISupports * supports = nsnull;
|
||||
QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pnsMenuItem->Create(supports, tmp, PR_TRUE);
|
||||
NS_RELEASE(supports);
|
||||
|
||||
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
AddItem(supports); // Parent should now own menu item
|
||||
NS_RELEASE(supports);
|
||||
|
||||
NS_RELEASE(pnsMenuItem);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::GetItemCount(PRUint32 &aCount)
|
||||
{
|
||||
// this should be right.. does it need to be +1 ?
|
||||
aCount = g_list_length(GTK_MENU_SHELL(mMenu)->children);
|
||||
//g_print("nsMenu::GetItemCount = %i\n", aCount);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::GetItemAt(const PRUint32 aCount, nsISupports *& aMenuItem)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::InsertItemAt(const PRUint32 aCount, nsISupports * aMenuItem)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::InsertSeparator(const PRUint32 aCount)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::RemoveItem(const PRUint32 aCount)
|
||||
{
|
||||
#if 0
|
||||
// this may work here better than Removeall(), but i'm not sure how to test this one
|
||||
nsISupports *item = mMenuItemVoidArray[aPos];
|
||||
delete item;
|
||||
mMenuItemVoidArray.RemoveElementAt(aPos);
|
||||
#endif
|
||||
/*
|
||||
gtk_menu_shell_remove (GTK_MENU_SHELL (mMenu), item);
|
||||
|
||||
nsCRT::free(labelStr);
|
||||
|
||||
voidData = NULL;
|
||||
|
||||
aMenu->GetNativeData(&voidData);
|
||||
newmenu = GTK_WIDGET(voidData);
|
||||
|
||||
gtk_menu_item_remove_submenu (GTK_MENU_ITEM (item));
|
||||
*/
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::RemoveAll()
|
||||
{
|
||||
//g_print("nsMenu::RemoveAll()\n");
|
||||
#undef DEBUG_pavlov
|
||||
#ifdef DEBUG_pavlov
|
||||
// this doesn't work quite right, but this is about all that should really be needed
|
||||
int i=0;
|
||||
nsIMenu *menu = nsnull;
|
||||
nsIMenuItem *menuitem = nsnull;
|
||||
nsISupports *item = nsnull;
|
||||
|
||||
for (i=mMenuItemVoidArray.Count(); i>0; i--)
|
||||
{
|
||||
item = (nsISupports*)mMenuItemVoidArray[i-1];
|
||||
|
||||
if(nsnull != item)
|
||||
{
|
||||
if (NS_OK == item->QueryInterface(nsIMenuItem::GetIID(), (void**)&menuitem))
|
||||
{
|
||||
// we do this twice because we have to do it once for QueryInterface,
|
||||
// then we want to get rid of it.
|
||||
// g_print("remove nsMenuItem\n");
|
||||
NS_RELEASE(menuitem);
|
||||
NS_RELEASE(item);
|
||||
menuitem = nsnull;
|
||||
} else if (NS_OK == item->QueryInterface(nsIMenu::GetIID(), (void**)&menu)) {
|
||||
#ifdef NOISY_MENUS
|
||||
g_print("remove nsMenu\n");
|
||||
#endif
|
||||
NS_RELEASE(menu);
|
||||
NS_RELEASE(item);
|
||||
menu = nsnull;
|
||||
}
|
||||
// mMenuItemVoidArray.RemoveElementAt(i-1);
|
||||
}
|
||||
}
|
||||
mMenuItemVoidArray.Clear();
|
||||
|
||||
return NS_OK;
|
||||
#else
|
||||
for (int i = mMenuItemVoidArray.Count(); i > 0; i--) {
|
||||
if(nsnull != mMenuItemVoidArray[i-1]) {
|
||||
nsIMenuItem * menuitem = nsnull;
|
||||
((nsISupports*)mMenuItemVoidArray[i-1])->QueryInterface(nsIMenuItem::GetIID(),
|
||||
(void**)&menuitem);
|
||||
if(menuitem) {
|
||||
void *gtkmenuitem = nsnull;
|
||||
menuitem->GetNativeData(gtkmenuitem);
|
||||
if (gtkmenuitem) {
|
||||
gtk_widget_ref(GTK_WIDGET(gtkmenuitem));
|
||||
//gtk_widget_destroy(GTK_WIDGET(gtkmenuitem));
|
||||
g_print("%p, %p\n",
|
||||
GTK_WIDGET(GTK_CONTAINER(GTK_MENU_SHELL(GTK_MENU(mMenu)))),
|
||||
GTK_WIDGET(GTK_WIDGET(gtkmenuitem)->parent));
|
||||
gtk_container_remove(GTK_CONTAINER(GTK_MENU_SHELL(GTK_MENU(mMenu))),
|
||||
GTK_WIDGET(gtkmenuitem));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
nsIMenu * menu= nsnull;
|
||||
((nsISupports*)mMenuItemVoidArray[i-1])->QueryInterface(nsIMenu::GetIID(),
|
||||
(void**)&menu);
|
||||
if(menu)
|
||||
{
|
||||
void * gtkmenu = nsnull;
|
||||
menu->GetNativeData(>kmenu);
|
||||
|
||||
if(gtkmenu){
|
||||
g_print("nsMenu::RemoveAll() trying to remove nsMenu");
|
||||
|
||||
//gtk_menu_item_remove_submenu (GTK_MENU_ITEM (item));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
//g_print("end RemoveAll\n");
|
||||
return NS_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::GetNativeData(void ** aData)
|
||||
{
|
||||
*aData = (void *)mMenu;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::AddMenuListener(nsIMenuListener * aMenuListener)
|
||||
{
|
||||
mListener = aMenuListener;
|
||||
NS_ADDREF(mListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::RemoveMenuListener(nsIMenuListener * aMenuListener)
|
||||
{
|
||||
if (aMenuListener == mListener) {
|
||||
NS_IF_RELEASE(mListener);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// nsIMenuListener interface
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsContextMenu::MenuItemSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
if (nsnull != mListener) {
|
||||
mListener->MenuSelected(aMenuEvent);
|
||||
}
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
void menu_popup_position(GtkMenu *menu,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gpointer data)
|
||||
{
|
||||
nsContextMenu *cm = (nsContextMenu*)data;
|
||||
*x = cm->GetX();
|
||||
*y = cm->GetY();
|
||||
}
|
||||
|
||||
nsEventStatus nsContextMenu::MenuSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
MenuConstruct(aMenuEvent,
|
||||
mParent,
|
||||
mDOMNode,
|
||||
mWebShell);
|
||||
|
||||
//GtkWidget *parent = GTK_WIDGET(mParent->GetNativeData(NS_NATIVE_WIDGET));
|
||||
gtk_menu_popup (GTK_MENU(mMenu),
|
||||
(GtkWidget*)nsnull, (GtkWidget*)nsnull,
|
||||
menu_popup_position,
|
||||
this, 1, GDK_CURRENT_TIME);
|
||||
/*
|
||||
if (nsnull != mListener) {
|
||||
mListener->MenuSelected(aMenuEvent);
|
||||
}
|
||||
*/
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsIMenuItem * nsContextMenu::FindMenuItem(nsIContextMenu * aMenu, PRUint32 aId)
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsContextMenu::MenuDeselected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
if (nsnull != mListener) {
|
||||
mListener->MenuDeselected(aMenuEvent);
|
||||
}
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsContextMenu::MenuConstruct(const nsMenuEvent &aMenuEvent,
|
||||
nsIWidget *aParentWindow,
|
||||
void *menuNode,
|
||||
void *aWebShell)
|
||||
{
|
||||
//g_print("nsMenu::MenuConstruct called \n");
|
||||
if(menuNode){
|
||||
SetDOMNode((nsIDOMNode*)menuNode);
|
||||
}
|
||||
|
||||
if(!aWebShell){
|
||||
aWebShell = mWebShell;
|
||||
}
|
||||
|
||||
// First open the menu.
|
||||
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
|
||||
if (domElement)
|
||||
domElement->SetAttribute("open", "true");
|
||||
|
||||
// Begin menuitem inner loop
|
||||
nsCOMPtr<nsIDOMNode> menuitemNode;
|
||||
((nsIDOMNode*)mDOMNode)->GetFirstChild(getter_AddRefs(menuitemNode));
|
||||
|
||||
unsigned short menuIndex = 0;
|
||||
|
||||
while (menuitemNode) {
|
||||
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
|
||||
if (menuitemElement) {
|
||||
nsString menuitemNodeType;
|
||||
nsString menuitemName;
|
||||
menuitemElement->GetNodeName(menuitemNodeType);
|
||||
if (menuitemNodeType.Equals("menuitem")) {
|
||||
// LoadMenuItem
|
||||
LoadMenuItem(this,
|
||||
menuitemElement,
|
||||
menuitemNode,
|
||||
menuIndex,
|
||||
(nsIWebShell*)aWebShell);
|
||||
} else if (menuitemNodeType.Equals("separator")) {
|
||||
AddSeparator();
|
||||
} else if (menuitemNodeType.Equals("menu")) {
|
||||
// Load a submenu
|
||||
LoadSubMenu(this, menuitemElement, menuitemNode);
|
||||
}
|
||||
}
|
||||
|
||||
++menuIndex;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
|
||||
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
|
||||
} // end menu item innner loop
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsContextMenu::MenuDestruct(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
// Close the node.
|
||||
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
|
||||
if (domElement)
|
||||
domElement->RemoveAttribute("open");
|
||||
|
||||
//g_print("nsMenu::MenuDestruct called \n");
|
||||
mConstructCalled = PR_FALSE;
|
||||
RemoveAll();
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
void nsContextMenu::LoadMenuItem(nsIMenu *pParentMenu,
|
||||
nsIDOMElement *menuitemElement,
|
||||
nsIDOMNode *menuitemNode,
|
||||
unsigned short menuitemIndex,
|
||||
nsIWebShell *aWebShell)
|
||||
{
|
||||
static const char* NS_STRING_TRUE = "true";
|
||||
nsString disabled;
|
||||
nsString menuitemName;
|
||||
nsString menuitemCmd;
|
||||
|
||||
menuitemElement->GetAttribute(nsAutoString("disabled"), disabled);
|
||||
menuitemElement->GetAttribute(nsAutoString("name"), menuitemName);
|
||||
menuitemElement->GetAttribute(nsAutoString("cmd"), menuitemCmd);
|
||||
|
||||
// Create nsMenuItem
|
||||
nsIMenuItem * pnsMenuItem = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(kMenuItemCID,
|
||||
nsnull,
|
||||
nsIMenuItem::GetIID(),
|
||||
(void**)&pnsMenuItem);
|
||||
if (NS_OK == rv) {
|
||||
pnsMenuItem->Create(pParentMenu, menuitemName, PR_FALSE);
|
||||
|
||||
nsISupports * supports = nsnull;
|
||||
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pParentMenu->AddItem(supports); // Parent should now own menu item
|
||||
NS_RELEASE(supports);
|
||||
|
||||
if(disabled == NS_STRING_TRUE) {
|
||||
pnsMenuItem->SetEnabled(PR_FALSE);
|
||||
}
|
||||
|
||||
// Create MenuDelegate - this is the intermediator inbetween
|
||||
// the DOM node and the nsIMenuItem
|
||||
// The nsWebShellWindow wacthes for Document changes and then notifies the
|
||||
// the appropriate nsMenuDelegate object
|
||||
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(menuitemNode));
|
||||
if (!domElement) {
|
||||
//return NS_ERROR_FAILURE;
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString cmdAtom("onclick");
|
||||
nsString cmdName;
|
||||
|
||||
domElement->GetAttribute(cmdAtom, cmdName);
|
||||
|
||||
pnsMenuItem->SetCommand(cmdName);
|
||||
// DO NOT use passed in webshell because of messed up windows dynamic loading
|
||||
// code.
|
||||
pnsMenuItem->SetWebShell(mWebShell);
|
||||
pnsMenuItem->SetDOMElement(domElement);
|
||||
|
||||
NS_RELEASE(pnsMenuItem);
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
void nsContextMenu::LoadSubMenu(nsIMenu *pParentMenu,
|
||||
nsIDOMElement *menuElement,
|
||||
nsIDOMNode *menuNode)
|
||||
{
|
||||
nsString menuName;
|
||||
menuElement->GetAttribute(nsAutoString("name"), menuName);
|
||||
//printf("Creating Menu [%s] \n", menuName.ToNewCString()); // this leaks
|
||||
|
||||
// Create nsMenu
|
||||
nsIMenu * pnsMenu = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(kMenuCID,
|
||||
nsnull,
|
||||
nsIMenu::GetIID(),
|
||||
(void**)&pnsMenu);
|
||||
if (NS_OK == rv) {
|
||||
// Call Create
|
||||
nsISupports * supports = nsnull;
|
||||
pParentMenu->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pnsMenu->Create(supports, menuName);
|
||||
NS_RELEASE(supports); // Balance QI
|
||||
|
||||
// Set nsMenu Name
|
||||
pnsMenu->SetLabel(menuName);
|
||||
|
||||
supports = nsnull;
|
||||
pnsMenu->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pParentMenu->AddItem(supports); // parent takes ownership
|
||||
NS_RELEASE(supports);
|
||||
|
||||
pnsMenu->SetWebShell(mWebShell);
|
||||
pnsMenu->SetDOMNode(menuNode);
|
||||
|
||||
/*
|
||||
// Begin menuitem inner loop
|
||||
unsigned short menuIndex = 0;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> menuitemNode;
|
||||
menuNode->GetFirstChild(getter_AddRefs(menuitemNode));
|
||||
while (menuitemNode) {
|
||||
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
|
||||
if (menuitemElement) {
|
||||
nsString menuitemNodeType;
|
||||
menuitemElement->GetNodeName(menuitemNodeType);
|
||||
|
||||
#ifdef DEBUG_saari
|
||||
printf("Type [%s] %d\n", menuitemNodeType.ToNewCString(), menuitemNodeType.Equals("separator"));
|
||||
#endif
|
||||
|
||||
if (menuitemNodeType.Equals("menuitem")) {
|
||||
// Load a menuitem
|
||||
LoadMenuItem(pnsMenu, menuitemElement, menuitemNode, menuIndex, mWebShell);
|
||||
} else if (menuitemNodeType.Equals("separator")) {
|
||||
pnsMenu->AddSeparator();
|
||||
} else if (menuitemNodeType.Equals("menu")) {
|
||||
// Add a submenu
|
||||
LoadSubMenu(pnsMenu, menuitemElement, menuitemNode);
|
||||
}
|
||||
}
|
||||
++menuIndex;
|
||||
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
|
||||
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
|
||||
} // end menu item innner loop
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
void nsContextMenu::LoadMenuItem(nsIContextMenu *pParentMenu,
|
||||
nsIDOMElement *menuitemElement,
|
||||
nsIDOMNode *menuitemNode,
|
||||
unsigned short menuitemIndex,
|
||||
nsIWebShell *aWebShell)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
void nsContextMenu::LoadSubMenu(nsIContextMenu *pParentMenu,
|
||||
nsIDOMElement *menuElement,
|
||||
nsIDOMNode *menuNode)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::SetLocation(PRInt32 aX, PRInt32 aY)
|
||||
{
|
||||
mX = aX;
|
||||
mY = aY;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// local methods
|
||||
gint nsContextMenu::GetX(void)
|
||||
{
|
||||
return mX;
|
||||
}
|
||||
|
||||
gint nsContextMenu::GetY(void)
|
||||
{
|
||||
return mY;
|
||||
}
|
||||
// end silly local methods
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::SetDOMNode(nsIDOMNode *aMenuNode)
|
||||
{
|
||||
mDOMNode = aMenuNode;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::SetDOMElement(nsIDOMElement *aMenuElement)
|
||||
{
|
||||
mDOMElement = aMenuElement;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsContextMenu::SetWebShell(nsIWebShell *aWebShell)
|
||||
{
|
||||
mWebShell = aWebShell;
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsContextMenu_h__
|
||||
#define nsContextMenu_h__
|
||||
|
||||
#include "nsIContextMenu.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIWebShell.h"
|
||||
|
||||
class nsIMenuListener;
|
||||
|
||||
/**
|
||||
* Native Win32 button wrapper
|
||||
*/
|
||||
|
||||
class nsContextMenu : public nsIContextMenu, public nsIMenuListener
|
||||
{
|
||||
|
||||
public:
|
||||
nsContextMenu();
|
||||
virtual ~nsContextMenu();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
//nsIMenuListener interface
|
||||
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuConstruct(const nsMenuEvent & aMenuEvent,
|
||||
nsIWidget * aParentWindow,
|
||||
void * menubarNode,
|
||||
void * aWebShell);
|
||||
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
|
||||
|
||||
// nsIMenu Methods
|
||||
NS_IMETHOD Create(nsISupports * aParent,
|
||||
const nsString& anAlignment,
|
||||
const nsString& aAnchorAlign);
|
||||
NS_IMETHOD GetParent(nsISupports *&aParent);
|
||||
|
||||
NS_IMETHOD AddItem(nsISupports * aItem);
|
||||
|
||||
NS_IMETHOD AddSeparator();
|
||||
NS_IMETHOD GetItemCount(PRUint32 &aCount);
|
||||
NS_IMETHOD GetItemAt(const PRUint32 aPos, nsISupports *& aMenuItem);
|
||||
NS_IMETHOD InsertItemAt(const PRUint32 aPos, nsISupports * aMenuItem);
|
||||
NS_IMETHOD RemoveItem(const PRUint32 aPos);
|
||||
NS_IMETHOD RemoveAll();
|
||||
NS_IMETHOD GetNativeData(void** aData);
|
||||
|
||||
NS_IMETHOD AddMenuListener(nsIMenuListener * aMenuListener);
|
||||
NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener);
|
||||
|
||||
//
|
||||
NS_IMETHOD AddMenuItem(nsIMenuItem * aMenuItem);
|
||||
NS_IMETHOD AddMenu(nsIMenu * aMenu);
|
||||
NS_IMETHOD InsertSeparator(const PRUint32 aCount);
|
||||
|
||||
NS_IMETHOD SetDOMNode(nsIDOMNode * menuNode);
|
||||
NS_IMETHOD SetDOMElement(nsIDOMElement * menuElement);
|
||||
NS_IMETHOD SetWebShell(nsIWebShell * aWebShell);
|
||||
NS_IMETHOD SetLocation(PRInt32 aX, PRInt32 aY);
|
||||
|
||||
gint GetX(void);
|
||||
gint GetY(void);
|
||||
|
||||
|
||||
protected:
|
||||
nsIMenuBar * GetMenuBar(nsIMenu * aMenu);
|
||||
nsIWidget * GetParentWidget();
|
||||
char* GetACPString(nsString& aStr);
|
||||
|
||||
void LoadMenuItem(nsIMenu * pParentMenu,
|
||||
nsIDOMElement * menuitemElement,
|
||||
nsIDOMNode * menuitemNode,
|
||||
unsigned short menuitemIndex,
|
||||
nsIWebShell * aWebShell);
|
||||
|
||||
void LoadSubMenu(nsIMenu * pParentMenu,
|
||||
nsIDOMElement * menuElement,
|
||||
nsIDOMNode * menuNode);
|
||||
|
||||
void LoadMenuItem(nsIContextMenu * pParentMenu,
|
||||
nsIDOMElement * menuitemElement,
|
||||
nsIDOMNode * menuitemNode,
|
||||
unsigned short menuitemIndex,
|
||||
nsIWebShell * aWebShell);
|
||||
|
||||
void LoadSubMenu(nsIContextMenu * pParentMenu,
|
||||
nsIDOMElement * menuElement,
|
||||
nsIDOMNode * menuNode);
|
||||
|
||||
nsIMenuItem * FindMenuItem(nsIContextMenu * aMenu, PRUint32 aId);
|
||||
|
||||
nsString mLabel;
|
||||
PRUint32 mNumMenuItems;
|
||||
GtkWidget *mMenu;
|
||||
|
||||
nsVoidArray mMenuItemVoidArray;
|
||||
|
||||
nsIWidget *mParent;
|
||||
nsIMenuListener * mListener;
|
||||
|
||||
PRBool mConstructCalled;
|
||||
nsIDOMNode * mDOMNode;
|
||||
nsIWebShell * mWebShell;
|
||||
nsIDOMElement * mDOMElement;
|
||||
|
||||
nsString mAlignment;
|
||||
nsString mAnchorAlignment;
|
||||
|
||||
PRInt32 mX;
|
||||
PRInt32 mY;
|
||||
};
|
||||
|
||||
#endif // nsContextMenu_h__
|
||||
@@ -1,592 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsDragService.h"
|
||||
|
||||
#include "nsITransferable.h"
|
||||
#include "nsString.h"
|
||||
#include "nsClipboard.h"
|
||||
#include "nsIRegion.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsPrimitiveHelpers.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsXPIDLString.h"
|
||||
|
||||
#include "nsWidgetsCID.h"
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsDragService, nsBaseDragService)
|
||||
NS_IMPL_RELEASE_INHERITED(nsDragService, nsBaseDragService)
|
||||
NS_IMPL_QUERY_INTERFACE2(nsDragService, nsIDragService, nsIDragSession)
|
||||
|
||||
#define DEBUG_DRAG 1
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// DragService constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsDragService::nsDragService()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mWidget = nsnull;
|
||||
mNumFlavors = 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// DragService destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsDragService::~nsDragService()
|
||||
{
|
||||
}
|
||||
|
||||
enum {
|
||||
TARGET_STRING,
|
||||
TARGET_ROOTWIN
|
||||
};
|
||||
|
||||
static GtkTargetEntry target_table[] = {
|
||||
{ "STRING", 0, TARGET_STRING },
|
||||
{ "text/plain", 0, TARGET_STRING },
|
||||
{ "application/x-rootwin-drop", 0, TARGET_ROOTWIN }
|
||||
};
|
||||
|
||||
static guint n_targets = sizeof(target_table) / sizeof(target_table[0]);
|
||||
|
||||
|
||||
NS_IMETHODIMP nsDragService::StartDragSession()
|
||||
{
|
||||
printf("nsDragService::StartDragSession()\n");
|
||||
nsBaseDragService::StartDragSession();
|
||||
|
||||
/*
|
||||
gtk_drag_source_set(mWidget,
|
||||
GDK_MODIFIER_MASK,
|
||||
targetlist,
|
||||
mNumFlavors,
|
||||
action);
|
||||
*/
|
||||
gtk_drag_source_set(mWidget,
|
||||
GDK_MODIFIER_MASK,
|
||||
target_table,
|
||||
n_targets,
|
||||
mActionType);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDragService::EndDragSession()
|
||||
{
|
||||
printf("nsDragService::EndDragSession()\n");
|
||||
nsBaseDragService::EndDragSession();
|
||||
|
||||
gtk_drag_source_unset(mWidget);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsDragService::InvokeDragSession (nsISupportsArray *aTransferableArray,
|
||||
nsIScriptableRegion *aRegion,
|
||||
PRUint32 aActionType)
|
||||
{
|
||||
mWidget = gtk_get_event_widget(gtk_get_current_event());
|
||||
|
||||
// add the flavors from the transferables. Cache this array for the send data proc
|
||||
GtkTargetList *targetlist = RegisterDragItemsAndFlavors(aTransferableArray);
|
||||
|
||||
switch (aActionType)
|
||||
{
|
||||
case DRAGDROP_ACTION_NONE:
|
||||
mActionType = GDK_ACTION_DEFAULT;
|
||||
break;
|
||||
case DRAGDROP_ACTION_COPY:
|
||||
mActionType = GDK_ACTION_COPY;
|
||||
break;
|
||||
case DRAGDROP_ACTION_MOVE:
|
||||
mActionType = GDK_ACTION_MOVE;
|
||||
break;
|
||||
case DRAGDROP_ACTION_LINK:
|
||||
mActionType = GDK_ACTION_LINK;
|
||||
break;
|
||||
}
|
||||
|
||||
StartDragSession();
|
||||
|
||||
// XXX 3rd param ??? & last param should be a real event...
|
||||
gtk_drag_begin(mWidget, targetlist, mActionType, 1, gtk_get_current_event());
|
||||
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
// we have to synthesize the native event because we may be called from JavaScript
|
||||
// through XPConnect. In that case, we only have a DOM event and no way to
|
||||
// get to the native event. As a consequence, we just always fake it.
|
||||
Point globalMouseLoc;
|
||||
::GetMouse(&globalMouseLoc);
|
||||
::LocalToGlobal(&globalMouseLoc);
|
||||
WindowPtr theWindow = nsnull;
|
||||
if ( ::FindWindow(globalMouseLoc, &theWindow) != inContent ) {
|
||||
// debugging sanity check
|
||||
#ifdef NS_DEBUG
|
||||
DebugStr("\pAbout to start drag, but FindWindow() != inContent; g");
|
||||
#endif
|
||||
}
|
||||
EventRecord theEvent;
|
||||
theEvent.what = mouseDown;
|
||||
theEvent.message = reinterpret_cast<UInt32>(theWindow);
|
||||
theEvent.when = 0;
|
||||
theEvent.where = globalMouseLoc;
|
||||
theEvent.modifiers = 0;
|
||||
|
||||
RgnHandle theDragRgn = ::NewRgn();
|
||||
BuildDragRegion ( aDragRgn, globalMouseLoc, theDragRgn );
|
||||
|
||||
// register drag send proc which will call us back when asked for the actual
|
||||
// flavor data (instead of placing it all into the drag manager)
|
||||
::SetDragSendProc ( theDragRef, sDragSendDataUPP, this );
|
||||
|
||||
// start the drag. Be careful, mDragRef will be invalid AFTER this call (it is
|
||||
// reset by the dragTrackingHandler).
|
||||
::TrackDrag ( theDragRef, &theEvent, theDragRgn );
|
||||
|
||||
// clean up after ourselves
|
||||
::DisposeRgn ( theDragRgn );
|
||||
result = ::DisposeDrag ( theDragRef );
|
||||
NS_ASSERTION ( result == noErr, "Error disposing drag" );
|
||||
mDragRef = 0L;
|
||||
mDataItems = nsnull;
|
||||
|
||||
return NS_OK;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
GtkTargetList *
|
||||
nsDragService::RegisterDragItemsAndFlavors(nsISupportsArray *inArray)
|
||||
{
|
||||
unsigned int numDragItems = 0;
|
||||
inArray->Count(&numDragItems);
|
||||
|
||||
GtkTargetList *targetlist;
|
||||
targetlist = gtk_target_list_new(nsnull, numDragItems);
|
||||
|
||||
for (unsigned int i = 0; i < numDragItems; ++i)
|
||||
{
|
||||
nsCOMPtr<nsISupports> genericItem;
|
||||
inArray->GetElementAt (i, getter_AddRefs(genericItem));
|
||||
nsCOMPtr<nsITransferable> currItem (do_QueryInterface(genericItem));
|
||||
if (currItem)
|
||||
{
|
||||
nsCOMPtr<nsISupportsArray> flavorList;
|
||||
if (NS_SUCCEEDED(currItem->FlavorsTransferableCanExport(getter_AddRefs(flavorList))))
|
||||
{
|
||||
flavorList->Count (&mNumFlavors);
|
||||
for (PRUint32 flavorIndex = 0; flavorIndex < mNumFlavors; ++flavorIndex)
|
||||
{
|
||||
nsCOMPtr<nsISupports> genericWrapper;
|
||||
flavorList->GetElementAt ( flavorIndex, getter_AddRefs(genericWrapper) );
|
||||
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericWrapper) );
|
||||
if ( currentFlavor )
|
||||
{
|
||||
nsXPIDLCString flavorStr;
|
||||
currentFlavor->ToString ( getter_Copies(flavorStr) );
|
||||
|
||||
// register native flavors
|
||||
GdkAtom atom = gdk_atom_intern(flavorStr, PR_TRUE);
|
||||
gtk_target_list_add(targetlist, atom, 1, atom);
|
||||
}
|
||||
|
||||
} // foreach flavor in item
|
||||
} // if valid flavor list
|
||||
} // if item is a transferable
|
||||
} // foreach drag item
|
||||
|
||||
return targetlist;
|
||||
}
|
||||
|
||||
|
||||
/* return PR_TRUE if we have converted or PR_FALSE if we havn't and need to keep being called */
|
||||
PRBool nsDragService::DoConvert(GdkAtom type)
|
||||
{
|
||||
#ifdef DEBUG_DRAG
|
||||
g_print(" nsDragService::DoRealConvert(%li)\n {\n", type);
|
||||
#endif
|
||||
int e = 0;
|
||||
// Set a flag saying that we're blocking waiting for the callback:
|
||||
mBlocking = PR_TRUE;
|
||||
|
||||
//
|
||||
// ask X what kind of data we can get
|
||||
//
|
||||
#ifdef DEBUG_DRAG
|
||||
g_print(" Doing real conversion of atom type '%s'\n", gdk_atom_name(type));
|
||||
#endif
|
||||
gtk_selection_convert(mWidget,
|
||||
GDK_SELECTION_PRIMARY,
|
||||
type,
|
||||
GDK_CURRENT_TIME);
|
||||
|
||||
// Now we need to wait until the callback comes in ...
|
||||
// i is in case we get a runaway (yuck).
|
||||
#ifdef DEBUG_DRAG
|
||||
printf(" Waiting for the callback... mBlocking = %d\n", mBlocking);
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
for (e=0; mBlocking == PR_TRUE && e < 1000; ++e)
|
||||
{
|
||||
gtk_main_iteration_do(PR_TRUE);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DRAG
|
||||
g_print(" }\n");
|
||||
#endif
|
||||
|
||||
if (mSelectionData.length > 0)
|
||||
return PR_TRUE;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/**
|
||||
* Called when the data from a drag comes in (recieved from gdk_selection_convert)
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aSelectionData gtk selection stuff
|
||||
* @param aTime time the selection was requested
|
||||
*/
|
||||
void
|
||||
nsDragService::SelectionReceivedCB (GtkWidget *aWidget,
|
||||
GdkDragContext *aContext,
|
||||
gint aX,
|
||||
gint aY,
|
||||
GtkSelectionData *aSelectionData,
|
||||
guint aInfo,
|
||||
guint aTime)
|
||||
{
|
||||
#ifdef DEBUG_DRAG
|
||||
printf(" nsDragService::SelectionReceivedCB\n {\n");
|
||||
#endif
|
||||
nsDragService *ds =(nsDragSession *)gtk_object_get_data(GTK_OBJECT(aWidget),
|
||||
"ds");
|
||||
if (!cb)
|
||||
{
|
||||
g_print("no dragservice found.. this is bad.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ds->SelectionReceiver(aWidget, aSelectionData);
|
||||
#ifdef DEBUG_DRAG
|
||||
g_print(" }\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* local method (called from nsClipboard::SelectionReceivedCB)
|
||||
*
|
||||
* @param aWidget the widget
|
||||
* @param aSelectionData gtk selection stuff
|
||||
*/
|
||||
void
|
||||
nsDragService::SelectionReceiver (GtkWidget *aWidget,
|
||||
GtkSelectionData *aSD)
|
||||
{
|
||||
gint type;
|
||||
|
||||
mBlocking = PR_FALSE;
|
||||
|
||||
if (aSD->length < 0)
|
||||
{
|
||||
printf(" Error retrieving selection: length was %d\n",
|
||||
aSD->length);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GDK_TARGET_STRING:
|
||||
case TARGET_COMPOUND_TEXT:
|
||||
case TARGET_TEXT_PLAIN:
|
||||
case TARGET_TEXT_XIF:
|
||||
case TARGET_TEXT_UNICODE:
|
||||
case TARGET_TEXT_HTML:
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" Copying mSelectionData pointer -- ");
|
||||
#endif
|
||||
mSelectionData = *aSD;
|
||||
mSelectionData.data = g_new(guchar, aSD->length + 1);
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
g_print(" Data = %s\n Length = %i\n", aSD->data, aSD->length);
|
||||
#endif
|
||||
memcpy(mSelectionData.data,
|
||||
aSD->data,
|
||||
aSD->length);
|
||||
// Null terminate in case anyone cares,
|
||||
// and so we can print the string for debugging:
|
||||
mSelectionData.data[aSD->length] = '\0';
|
||||
mSelectionData.length = aSD->length;
|
||||
return;
|
||||
|
||||
default:
|
||||
mSelectionData = *aSD;
|
||||
mSelectionData.data = g_new(guchar, aSD->length + 1);
|
||||
memcpy(mSelectionData.data,
|
||||
aSD->data,
|
||||
aSD->length);
|
||||
mSelectionData.length = aSD->length;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsDragService::GetNumDropItems (PRUint32 * aNumItems)
|
||||
{
|
||||
*aNumItems = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsDragService::GetData (nsITransferable * aTransferable, PRUint32 anItem)
|
||||
{
|
||||
|
||||
#ifdef DEBUG_DRAG
|
||||
printf("nsClipboard::GetNativeClipboardData()\n");
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
// make sure we have a good transferable
|
||||
if (!aTransferable) {
|
||||
printf(" GetData: Transferable is null!\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// get flavor list that includes all acceptable flavors (including ones obtained through
|
||||
// conversion)
|
||||
nsCOMPtr<nsISupportsArray> flavorList;
|
||||
nsresult errCode = aTransferable->FlavorsTransferableCanImport ( getter_AddRefs(flavorList) );
|
||||
if ( NS_FAILED(errCode) )
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Walk through flavors and see which flavor matches the one being pasted:
|
||||
PRUint32 cnt;
|
||||
flavorList->Count(&cnt);
|
||||
nsCAutoString foundFlavor;
|
||||
for ( PRUint32 i = 0; i < cnt; ++i ) {
|
||||
nsCOMPtr<nsISupports> genericFlavor;
|
||||
flavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) );
|
||||
nsCOMPtr<nsISupportsString> currentFlavor (do_QueryInterface(genericFlavor));
|
||||
if ( currentFlavor ) {
|
||||
nsXPIDLCString flavorStr;
|
||||
currentFlavor->ToString(getter_Copies(flavorStr));
|
||||
if (DoConvert(gdk_atom_intern(flavorStr, 1))) {
|
||||
foundFlavor = flavorStr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CLIPBOARD
|
||||
printf(" Got the callback: '%s', %d\n",
|
||||
mSelectionData.data, mSelectionData.length);
|
||||
#endif /* DEBUG_CLIPBOARD */
|
||||
|
||||
// We're back from the callback, no longer blocking:
|
||||
mBlocking = PR_FALSE;
|
||||
|
||||
//
|
||||
// Now we have data in mSelectionData.data.
|
||||
// We just have to copy it to the transferable.
|
||||
//
|
||||
|
||||
#if 0
|
||||
// pinkerton - we have the flavor already from above, so we don't need
|
||||
// to re-derrive it.
|
||||
nsString *name = new nsString((const char*)gdk_atom_name(mSelectionData.type));
|
||||
int format = GetFormat(*name);
|
||||
df->SetString((const char*)gdk_atom_name(sSelTypes[format]));
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsISupports> genericDataWrapper;
|
||||
nsPrimitiveHelpers::CreatePrimitiveForData ( foundFlavor, mSelectionData.data, mSelectionData.length, getter_AddRefs(genericDataWrapper) );
|
||||
aTransferable->SetTransferData(foundFlavor,
|
||||
genericDataWrapper,
|
||||
mSelectionData.length);
|
||||
|
||||
//delete name;
|
||||
|
||||
// transferable is now copying the data, so we can free it.
|
||||
// g_free(mSelectionData.data);
|
||||
mSelectionData.data = nsnull;
|
||||
mSelectionData.length = 0;
|
||||
|
||||
gtk_drag_source_unset(mWidget);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsDragService::IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsDragService::GetCurrentSession (nsIDragSession **aSession)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void
|
||||
nsDragService::DragLeave (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time)
|
||||
{
|
||||
g_print("leave\n");
|
||||
//gHaveDrag = PR_FALSE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool
|
||||
nsDragService::DragMotion(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
{
|
||||
g_print("drag motion\n");
|
||||
GtkWidget *source_widget;
|
||||
|
||||
#if 0
|
||||
if (!gHaveDrag) {
|
||||
gHaveDrag = PR_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
source_widget = gtk_drag_get_source_widget (context);
|
||||
g_print("motion, source %s\n", source_widget ?
|
||||
gtk_type_name (GTK_OBJECT (source_widget)->klass->type) :
|
||||
"unknown");
|
||||
|
||||
gdk_drag_status (context, context->suggested_action, time);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool
|
||||
nsDragService::DragDrop(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time)
|
||||
{
|
||||
g_print("drop\n");
|
||||
//gHaveDrag = PR_FALSE;
|
||||
|
||||
if (context->targets){
|
||||
gtk_drag_get_data (widget, context,
|
||||
GPOINTER_TO_INT (context->targets->data),
|
||||
time);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void
|
||||
nsDragService::DragDataReceived (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
GtkSelectionData *data,
|
||||
guint info,
|
||||
guint time)
|
||||
{
|
||||
if ((data->length >= 0) && (data->format == 8)) {
|
||||
g_print ("Received \"%s\"\n", (gchar *)data->data);
|
||||
gtk_drag_finish (context, PR_TRUE, PR_FALSE, time);
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_drag_finish (context, PR_FALSE, PR_FALSE, time);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void
|
||||
nsDragService::DragDataGet(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info,
|
||||
guint time,
|
||||
gpointer data)
|
||||
{
|
||||
gtk_selection_data_set (selection_data,
|
||||
selection_data->target,
|
||||
8, (guchar *)"I'm Data!", 9);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void
|
||||
nsDragService::DragDataDelete(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gpointer data)
|
||||
{
|
||||
g_print ("Delete the data!\n");
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsDragService_h__
|
||||
#define nsDragService_h__
|
||||
|
||||
#include "nsBaseDragService.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
||||
/**
|
||||
* Native GTK DragService wrapper
|
||||
*/
|
||||
|
||||
class nsDragService : public nsBaseDragService
|
||||
{
|
||||
|
||||
public:
|
||||
nsDragService();
|
||||
virtual ~nsDragService();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIDragService
|
||||
NS_IMETHOD InvokeDragSession (nsISupportsArray * anArrayTransferables,
|
||||
nsIScriptableRegion * aRegion, PRUint32 aActionType);
|
||||
NS_IMETHOD GetCurrentSession (nsIDragSession ** aSession);
|
||||
|
||||
// nsIDragSession
|
||||
NS_IMETHOD GetData (nsITransferable * aTransferable, PRUint32 anItem);
|
||||
NS_IMETHOD GetNumDropItems (PRUint32 * aNumItems);
|
||||
NS_IMETHOD IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval);
|
||||
|
||||
NS_IMETHOD StartDragSession();
|
||||
NS_IMETHOD EndDragSession();
|
||||
|
||||
|
||||
GtkTargetList *RegisterDragItemsAndFlavors(nsISupportsArray *inArray);
|
||||
|
||||
protected:
|
||||
|
||||
PRBool DoConvert(GdkAtom type);
|
||||
|
||||
static PRBool gHaveDrag;
|
||||
|
||||
static void DragLeave(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time);
|
||||
|
||||
static PRBool DragMotion(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
|
||||
static PRBool DragDrop(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
guint time);
|
||||
|
||||
static void DragDataReceived(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
GtkSelectionData *data,
|
||||
guint info,
|
||||
guint time);
|
||||
|
||||
static void DragDataGet(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info,
|
||||
guint time,
|
||||
gpointer data);
|
||||
|
||||
static void DragDataDelete(GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gpointer data);
|
||||
|
||||
private:
|
||||
GdkDragAction mActionType;
|
||||
PRUint32 mNumFlavors;
|
||||
GtkWidget *mWidget;
|
||||
GdkDragContext *mDragContext;
|
||||
GtkSelectionData mSelectionData;
|
||||
PRBool mBlocking;
|
||||
};
|
||||
|
||||
#endif // nsDragService_h__
|
||||
@@ -1,304 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Mozilla browser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stuart Parmenter <pavlov@netscape.com>
|
||||
*/
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsFilePicker.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsFilePicker, nsIFilePicker)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsFilePicker constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsFilePicker::nsFilePicker()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mWidget = nsnull;
|
||||
mDisplayDirectory = nsnull;
|
||||
mFilterMenu = nsnull;
|
||||
mOptionMenu = nsnull;
|
||||
mNumberOfFilters = 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsFilePicker destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsFilePicker::~nsFilePicker()
|
||||
{
|
||||
if (mFilterMenu)
|
||||
{
|
||||
GtkWidget *menu_item;
|
||||
GList *list = g_list_first(GTK_MENU_SHELL(mFilterMenu)->children);
|
||||
|
||||
for (;list; list = list->next)
|
||||
{
|
||||
menu_item = GTK_WIDGET(list->data);
|
||||
gchar *data = (gchar*)gtk_object_get_data(GTK_OBJECT(menu_item), "filters");
|
||||
|
||||
if (data)
|
||||
nsCRT::free(data);
|
||||
}
|
||||
}
|
||||
|
||||
gtk_widget_destroy(mWidget);
|
||||
}
|
||||
|
||||
|
||||
static void file_ok_clicked(GtkWidget *w, PRBool *ret)
|
||||
{
|
||||
g_print("user hit ok\n");
|
||||
*ret = PR_TRUE;
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
static void file_cancel_clicked(GtkWidget *w, PRBool *ret)
|
||||
{
|
||||
g_print("user hit cancel\n");
|
||||
*ret = PR_FALSE;
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
static void filter_item_activated(GtkWidget *w, gpointer data)
|
||||
{
|
||||
// nsFilePicker *f = (nsFilePicker*)data;
|
||||
gchar *foo = (gchar*)gtk_object_get_data(GTK_OBJECT(w), "filters");
|
||||
g_print("filter_item_activated(): %s\n", foo);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Show - Display the file dialog
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFilePicker::Show(PRInt16 *retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(retval);
|
||||
|
||||
PRBool ret;
|
||||
if (mWidget) {
|
||||
// make things shorter
|
||||
GtkFileSelection *fs = GTK_FILE_SELECTION(mWidget);
|
||||
|
||||
if (mNumberOfFilters != 0)
|
||||
{
|
||||
gtk_option_menu_set_menu(GTK_OPTION_MENU(mOptionMenu), mFilterMenu);
|
||||
}
|
||||
else
|
||||
gtk_widget_hide(mOptionMenu);
|
||||
|
||||
#if 0
|
||||
if (mDisplayDirectory)
|
||||
gtk_file_selection_complete(fs, "/");
|
||||
#endif
|
||||
|
||||
// gtk_window_set_modal(GTK_WINDOW(mWidget), PR_TRUE);
|
||||
gtk_widget_show(mWidget);
|
||||
|
||||
// handle close, destroy, etc on the dialog
|
||||
gtk_signal_connect(GTK_OBJECT(fs->ok_button), "clicked",
|
||||
GTK_SIGNAL_FUNC(file_ok_clicked),
|
||||
&ret);
|
||||
gtk_signal_connect(GTK_OBJECT(fs->cancel_button), "clicked",
|
||||
GTK_SIGNAL_FUNC(file_cancel_clicked),
|
||||
&ret);
|
||||
// start new loop. ret is set in the above callbacks.
|
||||
gtk_main();
|
||||
}
|
||||
else {
|
||||
ret = PR_FALSE;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
*retval = returnOK;
|
||||
else
|
||||
*retval = returnCancel;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set the list of filters
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP nsFilePicker::SetFilterList(PRInt32 aNumberOfFilters,
|
||||
const PRUnichar **aTitles,
|
||||
const PRUnichar **filters)
|
||||
{
|
||||
#if 0
|
||||
GtkWidget *menu_item;
|
||||
|
||||
mNumberOfFilters = aNumberOfFilters;
|
||||
mTitles = aTitles;
|
||||
mFilters = aFilters;
|
||||
|
||||
mFilterMenu = gtk_menu_new();
|
||||
|
||||
for(unsigned int i=0; i < aNumberOfFilters; i++)
|
||||
{
|
||||
// we need *.{htm, html, xul, etc}
|
||||
char *foo = aTitles[i].ToNewCString();
|
||||
char *filters = aFilters[i].ToNewCString();
|
||||
printf("%20s %s\n", foo, filters);
|
||||
|
||||
menu_item = gtk_menu_item_new_with_label(nsAutoCString(aTitles[i]));
|
||||
|
||||
gtk_object_set_data(GTK_OBJECT(menu_item), "filters", filters);
|
||||
|
||||
gtk_signal_connect(GTK_OBJECT(menu_item),
|
||||
"activate",
|
||||
GTK_SIGNAL_FUNC(filter_item_activated),
|
||||
this);
|
||||
|
||||
gtk_menu_append(GTK_MENU(mFilterMenu), menu_item);
|
||||
gtk_widget_show(menu_item);
|
||||
|
||||
nsCRT::free(foo);
|
||||
}
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFilePicker::GetFile(nsIFileSpec **aFile)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(*aFile);
|
||||
if (mWidget) {
|
||||
gchar *fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION(mWidget));
|
||||
|
||||
nsCOMPtr<nsIFileSpec> fileSpec(do_CreateInstance("component://netscape/filespec"));
|
||||
|
||||
NS_ENSURE_TRUE(fileSpec, NS_ERROR_FAILURE);
|
||||
|
||||
fileSpec->SetNativePath(fn);
|
||||
|
||||
*aFile = fileSpec;
|
||||
NS_ADDREF(*aFile);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFilePicker::GetSelectedFilter(PRInt32 *aType)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aType);
|
||||
*aType = mSelectedType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get the file + path
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFilePicker::SetDefaultString(const PRUnichar *aString)
|
||||
{
|
||||
if (mWidget) {
|
||||
gtk_file_selection_set_filename(GTK_FILE_SELECTION(mWidget),
|
||||
(const gchar*)nsAutoCString(aString));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFilePicker::GetDefaultString(PRUnichar **aString)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set the display directory
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFilePicker::SetDisplayDirectory(nsIFileSpec *aDirectory)
|
||||
{
|
||||
mDisplayDirectory = aDirectory;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get the display directory
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFilePicker::GetDisplayDirectory(nsIFileSpec **aDirectory)
|
||||
{
|
||||
*aDirectory = mDisplayDirectory;
|
||||
NS_IF_ADDREF(*aDirectory);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFilePicker::Create(nsIDOMWindow *aParent,
|
||||
const PRUnichar *aTitle,
|
||||
PRInt16 aMode)
|
||||
{
|
||||
return nsBaseFilePicker::Create(aParent, aTitle, aMode);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFilePicker::CreateNative(nsIWidget *aParent,
|
||||
const PRUnichar *aTitle,
|
||||
PRInt16 aMode)
|
||||
{
|
||||
mWidget = gtk_file_selection_new((const gchar *)nsAutoCString(aTitle));
|
||||
gtk_signal_connect(GTK_OBJECT(mWidget),
|
||||
"destroy",
|
||||
GTK_SIGNAL_FUNC(DestroySignal),
|
||||
this);
|
||||
|
||||
gtk_button_box_set_layout(GTK_BUTTON_BOX(GTK_FILE_SELECTION(mWidget)->button_area), GTK_BUTTONBOX_SPREAD);
|
||||
|
||||
mOptionMenu = gtk_option_menu_new();
|
||||
|
||||
gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(mWidget)->main_vbox), mOptionMenu, PR_FALSE, PR_FALSE, 0);
|
||||
gtk_widget_show(mOptionMenu);
|
||||
|
||||
// Hide the file column for the folder case.
|
||||
if (aMode == nsIFilePicker::modeGetFolder) {
|
||||
gtk_widget_hide((GTK_FILE_SELECTION(mWidget)->file_list)->parent);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
gint
|
||||
nsFilePicker::DestroySignal(GtkWidget * aGtkWidget,
|
||||
nsFilePicker* aWidget)
|
||||
{
|
||||
aWidget->OnDestroySignal(aGtkWidget);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nsFilePicker::OnDestroySignal(GtkWidget* aGtkWidget)
|
||||
{
|
||||
if (aGtkWidget == mWidget) {
|
||||
mWidget = nsnull;
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Mozilla browser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stuart Parmenter <pavlov@netscape.com>
|
||||
*/
|
||||
|
||||
#ifndef nsFilePicker_h__
|
||||
#define nsFilePicker_h__
|
||||
|
||||
#include "nsBaseFilePicker.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/**
|
||||
* Native GTK FileSelector wrapper
|
||||
*/
|
||||
|
||||
class nsFilePicker : public nsBaseFilePicker
|
||||
{
|
||||
public:
|
||||
nsFilePicker();
|
||||
virtual ~nsFilePicker();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIFILEPICKER
|
||||
|
||||
protected:
|
||||
/* method from nsBaseFilePicker */
|
||||
NS_IMETHOD CreateNative(nsIWidget *aParent,
|
||||
const PRUnichar *aTitle,
|
||||
PRInt16 aMode);
|
||||
|
||||
static gint DestroySignal(GtkWidget * aGtkWidget,
|
||||
nsFilePicker* aWidget);
|
||||
|
||||
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
|
||||
|
||||
GtkWidget *mWidget;
|
||||
GtkWidget *mOptionMenu;
|
||||
GtkWidget *mFilterMenu;
|
||||
|
||||
|
||||
PRUint32 mNumberOfFilters;
|
||||
const nsString* mTitles;
|
||||
const nsString* mFilters;
|
||||
nsString mDefault;
|
||||
nsIFileSpec *mDisplayDirectory;
|
||||
PRInt16 mSelectedType;
|
||||
};
|
||||
|
||||
#endif // nsFilePicker_h__
|
||||
@@ -1,322 +0,0 @@
|
||||
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsFileWidget.h"
|
||||
#include "nsIToolkit.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsFileWidget, nsIFileWidget)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsFileWidget constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsFileWidget::nsFileWidget() : nsIFileWidget()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mWidget = nsnull;
|
||||
mDisplayDirectory = nsnull;
|
||||
mFilterMenu = nsnull;
|
||||
mOptionMenu = nsnull;
|
||||
mNumberOfFilters = 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsFileWidget destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsFileWidget::~nsFileWidget()
|
||||
{
|
||||
if (mFilterMenu)
|
||||
{
|
||||
GtkWidget *menu_item;
|
||||
GList *list = g_list_first(GTK_MENU_SHELL(mFilterMenu)->children);
|
||||
|
||||
for (;list; list = list->next)
|
||||
{
|
||||
menu_item = GTK_WIDGET(list->data);
|
||||
gchar *data = (gchar*)gtk_object_get_data(GTK_OBJECT(menu_item), "filters");
|
||||
|
||||
if (data)
|
||||
nsCRT::free(data);
|
||||
}
|
||||
}
|
||||
|
||||
gtk_widget_destroy(mWidget);
|
||||
}
|
||||
|
||||
|
||||
static void file_ok_clicked(GtkWidget *w, PRBool *ret)
|
||||
{
|
||||
g_print("user hit ok\n");
|
||||
*ret = PR_TRUE;
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
static void file_cancel_clicked(GtkWidget *w, PRBool *ret)
|
||||
{
|
||||
g_print("user hit cancel\n");
|
||||
*ret = PR_FALSE;
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
static void filter_item_activated(GtkWidget *w, gpointer data)
|
||||
{
|
||||
// nsFileWidget *f = (nsFileWidget*)data;
|
||||
gchar *foo = (gchar*)gtk_object_get_data(GTK_OBJECT(w), "filters");
|
||||
g_print("filter_item_activated(): %s\n", foo);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Show - Display the file dialog
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool nsFileWidget::Show()
|
||||
{
|
||||
PRBool ret;
|
||||
if (mWidget) {
|
||||
// make things shorter
|
||||
GtkFileSelection *fs = GTK_FILE_SELECTION(mWidget);
|
||||
|
||||
if (mNumberOfFilters != 0)
|
||||
{
|
||||
gtk_option_menu_set_menu(GTK_OPTION_MENU(mOptionMenu), mFilterMenu);
|
||||
}
|
||||
else
|
||||
gtk_widget_hide(mOptionMenu);
|
||||
|
||||
#if 0
|
||||
if (mDisplayDirectory)
|
||||
gtk_file_selection_complete(fs, "/");
|
||||
#endif
|
||||
|
||||
// gtk_window_set_modal(GTK_WINDOW(mWidget), PR_TRUE);
|
||||
gtk_widget_show(mWidget);
|
||||
|
||||
// handle close, destroy, etc on the dialog
|
||||
gtk_signal_connect(GTK_OBJECT(fs->ok_button), "clicked",
|
||||
GTK_SIGNAL_FUNC(file_ok_clicked),
|
||||
&ret);
|
||||
gtk_signal_connect(GTK_OBJECT(fs->cancel_button), "clicked",
|
||||
GTK_SIGNAL_FUNC(file_cancel_clicked),
|
||||
&ret);
|
||||
// start new loop. ret is set in the above callbacks.
|
||||
gtk_main();
|
||||
}
|
||||
else {
|
||||
ret = PR_FALSE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set the list of filters
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP nsFileWidget::SetFilterList(PRUint32 aNumberOfFilters,
|
||||
const nsString aTitles[],
|
||||
const nsString aFilters[])
|
||||
{
|
||||
GtkWidget *menu_item;
|
||||
|
||||
mNumberOfFilters = aNumberOfFilters;
|
||||
mTitles = aTitles;
|
||||
mFilters = aFilters;
|
||||
|
||||
mFilterMenu = gtk_menu_new();
|
||||
|
||||
for(unsigned int i=0; i < aNumberOfFilters; i++)
|
||||
{
|
||||
// we need *.{htm, html, xul, etc}
|
||||
char *foo = aTitles[i].ToNewCString();
|
||||
char *filters = aFilters[i].ToNewCString();
|
||||
printf("%20s %s\n", foo, filters);
|
||||
|
||||
menu_item = gtk_menu_item_new_with_label(nsAutoCString(aTitles[i]));
|
||||
|
||||
gtk_object_set_data(GTK_OBJECT(menu_item), "filters", filters);
|
||||
|
||||
gtk_signal_connect(GTK_OBJECT(menu_item),
|
||||
"activate",
|
||||
GTK_SIGNAL_FUNC(filter_item_activated),
|
||||
this);
|
||||
|
||||
gtk_menu_append(GTK_MENU(mFilterMenu), menu_item);
|
||||
gtk_widget_show(menu_item);
|
||||
|
||||
nsCRT::free(foo);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFileWidget::GetFile(nsFileSpec& aFile)
|
||||
{
|
||||
if (mWidget) {
|
||||
gchar *fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION(mWidget));
|
||||
aFile = fn; // Put the filename into the nsFileSpec instance.
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFileWidget::GetSelectedType(PRInt16& theType)
|
||||
{
|
||||
theType = mSelectedType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get the file + path
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFileWidget::SetDefaultString(const nsString& aString)
|
||||
{
|
||||
if (mWidget) {
|
||||
gtk_file_selection_set_filename(GTK_FILE_SELECTION(mWidget),
|
||||
(const gchar*)nsAutoCString(aString));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set the display directory
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFileWidget::SetDisplayDirectory(const nsFileSpec& aDirectory)
|
||||
{
|
||||
mDisplayDirectory = aDirectory;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get the display directory
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFileWidget::GetDisplayDirectory(nsFileSpec& aDirectory)
|
||||
{
|
||||
aDirectory = mDisplayDirectory;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsFileWidget::Create(nsIWidget *aParent,
|
||||
const nsString& aTitle,
|
||||
nsFileDlgMode aMode,
|
||||
nsIDeviceContext *aContext,
|
||||
nsIAppShell *aAppShell,
|
||||
nsIToolkit *aToolkit,
|
||||
void *aInitData)
|
||||
{
|
||||
mMode = aMode;
|
||||
mTitle.SetLength(0);
|
||||
mTitle.Append(aTitle);
|
||||
|
||||
mWidget = gtk_file_selection_new((const gchar *)nsAutoCString(aTitle));
|
||||
gtk_signal_connect(GTK_OBJECT(mWidget),
|
||||
"destroy",
|
||||
GTK_SIGNAL_FUNC(DestroySignal),
|
||||
this);
|
||||
|
||||
gtk_button_box_set_layout(GTK_BUTTON_BOX(GTK_FILE_SELECTION(mWidget)->button_area), GTK_BUTTONBOX_SPREAD);
|
||||
|
||||
mOptionMenu = gtk_option_menu_new();
|
||||
|
||||
gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(mWidget)->main_vbox), mOptionMenu, PR_FALSE, PR_FALSE, 0);
|
||||
gtk_widget_show(mOptionMenu);
|
||||
|
||||
|
||||
// Hide the file column for the folder case.
|
||||
if (aMode == eMode_getfolder) {
|
||||
gtk_widget_hide((GTK_FILE_SELECTION(mWidget)->file_list)->parent);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
gint
|
||||
nsFileWidget::DestroySignal(GtkWidget * aGtkWidget,
|
||||
nsFileWidget* aWidget)
|
||||
{
|
||||
aWidget->OnDestroySignal(aGtkWidget);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nsFileWidget::OnDestroySignal(GtkWidget* aGtkWidget)
|
||||
{
|
||||
if (aGtkWidget == mWidget) {
|
||||
mWidget = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
nsFileDlgResults nsFileWidget::GetFile(nsIWidget *aParent,
|
||||
const nsString &promptString,
|
||||
nsFileSpec &theFileSpec)
|
||||
{
|
||||
Create(aParent, promptString, eMode_load, nsnull, nsnull);
|
||||
if (Show() == PR_TRUE)
|
||||
{
|
||||
GetFile(theFileSpec);
|
||||
return nsFileDlgResults_OK;
|
||||
}
|
||||
|
||||
return nsFileDlgResults_Cancel;
|
||||
}
|
||||
|
||||
nsFileDlgResults nsFileWidget::GetFolder(nsIWidget *aParent,
|
||||
const nsString &promptString,
|
||||
nsFileSpec &theFileSpec)
|
||||
{
|
||||
Create(aParent, promptString, eMode_getfolder, nsnull, nsnull);
|
||||
if (Show() == PR_TRUE)
|
||||
{
|
||||
GetFile(theFileSpec);
|
||||
return nsFileDlgResults_OK;
|
||||
}
|
||||
|
||||
return nsFileDlgResults_Cancel;
|
||||
}
|
||||
|
||||
nsFileDlgResults nsFileWidget::PutFile(nsIWidget *aParent,
|
||||
const nsString &promptString,
|
||||
nsFileSpec &theFileSpec)
|
||||
{
|
||||
Create(aParent, promptString, eMode_save, nsnull, nsnull);
|
||||
if (Show() == PR_TRUE)
|
||||
{
|
||||
GetFile(theFileSpec);
|
||||
return nsFileDlgResults_OK;
|
||||
}
|
||||
return nsFileDlgResults_Cancel;
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsFileWidget_h__
|
||||
#define nsFileWidget_h__
|
||||
|
||||
#include "nsIWidget.h"
|
||||
#include "nsIFileWidget.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
class nsIToolkit;
|
||||
|
||||
/**
|
||||
* Native GTK FileSelector wrapper
|
||||
*/
|
||||
|
||||
class nsFileWidget : public nsIFileWidget
|
||||
{
|
||||
public:
|
||||
nsFileWidget();
|
||||
virtual ~nsFileWidget();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIWidget interface
|
||||
|
||||
NS_IMETHOD Create(nsIWidget *aParent,
|
||||
const nsString& aTitle,
|
||||
nsFileDlgMode aMode,
|
||||
nsIDeviceContext *aContext = nsnull,
|
||||
nsIAppShell *aAppShell = nsnull,
|
||||
nsIToolkit *aToolkit = nsnull,
|
||||
void *aInitData = nsnull);
|
||||
|
||||
// nsIFileWidget part
|
||||
virtual PRBool Show();
|
||||
NS_IMETHOD GetFile(nsFileSpec& aFile);
|
||||
NS_IMETHOD SetDefaultString(const nsString& aFile);
|
||||
NS_IMETHOD SetFilterList(PRUint32 aNumberOfFilters,
|
||||
const nsString aTitles[],
|
||||
const nsString aFilters[]);
|
||||
|
||||
NS_IMETHOD GetDisplayDirectory(nsFileSpec& aDirectory);
|
||||
NS_IMETHOD SetDisplayDirectory(const nsFileSpec& aDirectory);
|
||||
|
||||
virtual nsFileDlgResults GetFile(nsIWidget *aParent,
|
||||
const nsString &promptString,
|
||||
nsFileSpec &theFileSpec);
|
||||
|
||||
virtual nsFileDlgResults GetFolder(nsIWidget *aParent,
|
||||
const nsString &promptString,
|
||||
nsFileSpec &theFileSpec);
|
||||
|
||||
virtual nsFileDlgResults PutFile(nsIWidget *aParent,
|
||||
const nsString &promptString,
|
||||
nsFileSpec &theFileSpec);
|
||||
|
||||
|
||||
NS_IMETHOD GetSelectedType(PRInt16& theType);
|
||||
|
||||
protected:
|
||||
static gint DestroySignal(GtkWidget * aGtkWidget,
|
||||
nsFileWidget* aWidget);
|
||||
|
||||
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
|
||||
|
||||
GtkWidget *mWidget;
|
||||
nsString mTitle;
|
||||
GtkWidget *mOptionMenu;
|
||||
GtkWidget *mFilterMenu;
|
||||
|
||||
|
||||
nsFileDlgMode mMode;
|
||||
PRUint32 mNumberOfFilters;
|
||||
const nsString* mTitles;
|
||||
const nsString* mFilters;
|
||||
nsString mDefault;
|
||||
nsFileSpec mDisplayDirectory;
|
||||
PRInt16 mSelectedType;
|
||||
};
|
||||
|
||||
#endif // nsFileWidget_h__
|
||||
@@ -1,395 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsFontRetrieverService.h"
|
||||
#include "nsIWidget.h"
|
||||
#include <ctype.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include "X11/Xlib.h"
|
||||
#include "X11/Xutil.h"
|
||||
|
||||
#include "nsFont.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsFontSizeIterator.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsFontRetrieverService, nsIFontRetrieverService, nsIFontNameIterator)
|
||||
|
||||
//----------------------------------------------------------
|
||||
nsFontRetrieverService::nsFontRetrieverService()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
mFontList = nsnull;
|
||||
mSizeIter = nsnull;
|
||||
mNameIterInx = 0;
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
nsFontRetrieverService::~nsFontRetrieverService()
|
||||
{
|
||||
if (nsnull != mFontList) {
|
||||
for (PRInt32 i=0;i<mFontList->Count();i++) {
|
||||
FontInfo * font = (FontInfo *)mFontList->ElementAt(i);
|
||||
if (font->mSizes) {
|
||||
delete font->mSizes;
|
||||
}
|
||||
delete font;
|
||||
}
|
||||
delete mFontList;
|
||||
}
|
||||
NS_IF_RELEASE(mSizeIter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------
|
||||
//-- nsIFontRetrieverService
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontRetrieverService::CreateFontNameIterator( nsIFontNameIterator** aIterator )
|
||||
{
|
||||
if (nsnull == aIterator) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (nsnull == mFontList) {
|
||||
LoadFontList();
|
||||
}
|
||||
*aIterator = this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontRetrieverService::CreateFontSizeIterator( const nsString & aFontName,
|
||||
nsIFontSizeIterator** aIterator )
|
||||
{
|
||||
// save value in case someone externally is using it
|
||||
PRInt32 saveIterInx = mNameIterInx;
|
||||
|
||||
PRBool found = PR_FALSE;
|
||||
Reset();
|
||||
do {
|
||||
nsAutoString name;
|
||||
Get(&name);
|
||||
if (name.Equals(aFontName)) {
|
||||
found = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
} while (Advance() == NS_OK);
|
||||
|
||||
if (found) {
|
||||
if (nsnull == mSizeIter) {
|
||||
mSizeIter = new nsFontSizeIterator();
|
||||
}
|
||||
NS_ASSERTION( nsnull != mSizeIter, "nsFontSizeIterator instance pointer is null");
|
||||
|
||||
*aIterator = (nsIFontSizeIterator *)mSizeIter;
|
||||
NS_ADDREF(mSizeIter);
|
||||
|
||||
FontInfo * fontInfo = (FontInfo *)mFontList->ElementAt(mNameIterInx);
|
||||
mSizeIter->SetFontInfo(fontInfo);
|
||||
mNameIterInx = saveIterInx;
|
||||
return NS_OK;
|
||||
}
|
||||
mNameIterInx = saveIterInx;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//-- nsIFontNameIterator
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontRetrieverService::Reset()
|
||||
{
|
||||
mNameIterInx = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontRetrieverService::Get( nsString* aFontName )
|
||||
{
|
||||
if (mNameIterInx < mFontList->Count()) {
|
||||
FontInfo * fontInfo = (FontInfo *)mFontList->ElementAt(mNameIterInx);
|
||||
*aFontName = fontInfo->mName;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontRetrieverService::Advance()
|
||||
{
|
||||
if (mNameIterInx < mFontList->Count()-1) {
|
||||
mNameIterInx++;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//------------------------------
|
||||
static FontInfo * GetFontInfo(nsVoidArray * aFontList, char * aName)
|
||||
{
|
||||
nsAutoString name(aName);
|
||||
PRInt32 i;
|
||||
PRInt32 cnt = aFontList->Count();
|
||||
for (i=0;i<cnt;i++) {
|
||||
FontInfo * fontInfo = (FontInfo *)aFontList->ElementAt(i);
|
||||
if (fontInfo->mName.Equals(name)) {
|
||||
return fontInfo;
|
||||
}
|
||||
}
|
||||
|
||||
FontInfo * fontInfo = new FontInfo();
|
||||
fontInfo->mName = aName;
|
||||
//printf("Adding [%s]\n", aName);fflush(stdout);
|
||||
fontInfo->mIsScalable = PR_FALSE; // X fonts aren't scalable right??
|
||||
fontInfo->mSizes = nsnull;
|
||||
aFontList->AppendElement(fontInfo);
|
||||
return fontInfo;
|
||||
}
|
||||
|
||||
//------------------------------
|
||||
static void AddSizeToFontInfo(FontInfo * aFontInfo, PRInt32 aSize)
|
||||
{
|
||||
nsVoidArray * sizes;
|
||||
if (nsnull == aFontInfo->mSizes) {
|
||||
sizes = new nsVoidArray();
|
||||
aFontInfo->mSizes = sizes;
|
||||
} else {
|
||||
sizes = aFontInfo->mSizes;
|
||||
}
|
||||
PRInt32 i;
|
||||
PRInt32 cnt = sizes->Count();
|
||||
for (i=0;i<cnt;i++) {
|
||||
PRInt32 size = (int)sizes->ElementAt(i);
|
||||
if (size == aSize) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
sizes->AppendElement((void *)aSize);
|
||||
}
|
||||
|
||||
//---------------------------------------------------
|
||||
// XXX - Hack - Parts of this will need to be reworked
|
||||
//
|
||||
// This method does brute force parcing for 4 different formats:
|
||||
//
|
||||
// 1) The format -*-*-*-*-*-* etc.
|
||||
// -misc-fixed-medium-r-normal--13-120-75-75-c-80-iso8859-8
|
||||
//
|
||||
// 2) Name-size format
|
||||
// lucidasans-10
|
||||
//
|
||||
// 3) Name-style-size
|
||||
// lucidasans-bold-10
|
||||
//
|
||||
// 4) Name only (implicit size)
|
||||
// 6x13
|
||||
//
|
||||
//--------------------------------------------------
|
||||
NS_IMETHODIMP nsFontRetrieverService::LoadFontList()
|
||||
{
|
||||
char * pattern = "*";
|
||||
int nnames = 1024;
|
||||
|
||||
int available = nnames+1;
|
||||
int i;
|
||||
char **fonts;
|
||||
XFontStruct *info;
|
||||
|
||||
if (nsnull == mFontList) {
|
||||
mFontList = new nsVoidArray();
|
||||
if (nsnull == mFontList) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get list of fonts matching pattern */
|
||||
for (;;) {
|
||||
// the following line is VERY slow to return
|
||||
fonts = XListFontsWithInfo(GDK_DISPLAY(), pattern, nnames,
|
||||
&available, &info);
|
||||
if (fonts == NULL || available < nnames)
|
||||
break;
|
||||
|
||||
XFreeFontInfo(fonts, info, available);
|
||||
nnames = available * 2;
|
||||
}
|
||||
|
||||
if (fonts == NULL) {
|
||||
fprintf(stderr, "pattern \"%s\" unmatched\n", pattern);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
#if 0 // debug
|
||||
// print out all the retrieved fonts
|
||||
printf("-----------------------------\n");
|
||||
for (i=0; i<available; i++) {
|
||||
printf("[%s]i\n", fonts[i]);
|
||||
}
|
||||
printf("-----------------------------\n");
|
||||
#endif
|
||||
|
||||
// this code assumes all like fonts are grouped together
|
||||
// currentName is the current name of the font we are gathering
|
||||
// sizes for, when the name changes we create a new FontInfo object
|
||||
// but it also takes into account fonts of similar names when it
|
||||
// goes to add then and disregards duplicates
|
||||
char buffer[1024];
|
||||
char currentName[1024];
|
||||
FontInfo * font = nsnull;
|
||||
|
||||
currentName[0] = 0;
|
||||
for (i=0; i<available; i++) {
|
||||
|
||||
// This is kind of lame, but it will have to do for now
|
||||
strcpy(buffer, fonts[i]);
|
||||
|
||||
// Start by checking to see if the name begins with a dash
|
||||
char * ptr = buffer;
|
||||
if (buffer[0] == '-') { //Format #1
|
||||
|
||||
PRInt32 cnt = 0;
|
||||
// skip first two '-'
|
||||
do {
|
||||
if (*ptr == '-') cnt++;
|
||||
ptr++;
|
||||
} while (cnt < 2);
|
||||
|
||||
// find the dash at the end of the name
|
||||
char * end = strchr(ptr, '-');
|
||||
if (end) {
|
||||
*end = 0;
|
||||
|
||||
// Check to see if we need to create a new FontInfo obj
|
||||
// and set the currentName var to this guys font name
|
||||
if (strcmp(currentName, ptr) || NULL == font) {
|
||||
font = GetFontInfo(mFontList, ptr);
|
||||
strcpy(currentName, ptr);
|
||||
}
|
||||
if (nsnull == font->mSizes) {
|
||||
font->mSizes = new nsVoidArray();
|
||||
}
|
||||
ptr = end+1; // skip past the dash that was set to zero
|
||||
|
||||
cnt = 0;
|
||||
// now skip ahead 4 dashes
|
||||
do {
|
||||
if (*ptr == '-') cnt++;
|
||||
ptr++;
|
||||
} while (cnt < 4);
|
||||
|
||||
// find the dash after the size
|
||||
end = strchr(ptr, '-');
|
||||
|
||||
if (end) {
|
||||
*end = 0;
|
||||
PRInt32 size;
|
||||
sscanf(ptr, "%d", &size);
|
||||
AddSizeToFontInfo(font, size);
|
||||
}
|
||||
}
|
||||
} else { // formats 2,3,4
|
||||
|
||||
// no leading dash means the start of the
|
||||
// buffer is the start of the name
|
||||
// this checks for a dash at the end of the font name
|
||||
// which means there is a size at the end
|
||||
char * end = strchr(buffer, '-');
|
||||
if (end) { // Format 2,3
|
||||
*end = 0;
|
||||
// Check to see if we need to create a new FontInfo obj
|
||||
// and set the currentName var to this guys font name
|
||||
if (strcmp(currentName, buffer) || NULL == font) {
|
||||
font = GetFontInfo(mFontList, buffer);
|
||||
strcpy(currentName, buffer);
|
||||
}
|
||||
end++; // advance past the dash
|
||||
// check to see if we have a number
|
||||
ptr = end;
|
||||
if (isalpha(*ptr)) { // Format 3
|
||||
// skip until next dash
|
||||
end = strchr(ptr, '-');
|
||||
if (end) {
|
||||
*end = 0;
|
||||
ptr = end+1;
|
||||
}
|
||||
}
|
||||
PRInt32 size;
|
||||
// yes, it has a dash at the end so it must have the size
|
||||
// check to see if the size is terminated by a dash
|
||||
// it shouldn't be
|
||||
char * end2 = strchr(ptr, '-');
|
||||
if (end2) *end2 = 0; // put terminator at the dash
|
||||
sscanf(end, "%d", &size);
|
||||
AddSizeToFontInfo(font, size);
|
||||
|
||||
} else { // Format #4
|
||||
// The font has an implicit size,
|
||||
// so there is nothing to parse for size
|
||||
// so we can't really do much here
|
||||
// Check to see if we need to create a new FontInfo obj
|
||||
// and set the currentName var to this guys font name
|
||||
if (strcmp(currentName, buffer) || NULL == font) {
|
||||
font = GetFontInfo(mFontList, buffer);
|
||||
strcpy(currentName, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
XFreeFontInfo(fonts, info, available);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontRetrieverService::IsFontScalable(const nsString & aFontName,
|
||||
PRBool* aResult )
|
||||
{
|
||||
// save value in case someone externally is using it
|
||||
PRInt32 saveIterInx = mNameIterInx;
|
||||
|
||||
PRBool found = PR_FALSE;
|
||||
Reset();
|
||||
do {
|
||||
nsAutoString name;
|
||||
Get(&name);
|
||||
if (name.Equals(aFontName)) {
|
||||
found = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
} while (Advance() == NS_OK);
|
||||
|
||||
if (found) {
|
||||
FontInfo * fontInfo = (FontInfo *)mFontList->ElementAt(mNameIterInx);
|
||||
*aResult = fontInfo->mIsScalable;
|
||||
mNameIterInx = saveIterInx;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mNameIterInx = saveIterInx;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef __nsFontRetrieverService
|
||||
#define __nsFontRetrieverService
|
||||
|
||||
#include "nsIFontRetrieverService.h"
|
||||
#include "nsIFontNameIterator.h"
|
||||
|
||||
class nsVoidArray;
|
||||
class nsFontSizeIterator;
|
||||
|
||||
class nsFontRetrieverService: public nsIFontRetrieverService,
|
||||
public nsIFontNameIterator
|
||||
{
|
||||
public:
|
||||
nsFontRetrieverService();
|
||||
virtual ~nsFontRetrieverService();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIFontRetrieverService
|
||||
NS_IMETHOD CreateFontNameIterator( nsIFontNameIterator** aIterator );
|
||||
|
||||
NS_IMETHOD CreateFontSizeIterator( const nsString & aFontName, nsIFontSizeIterator** aIterator );
|
||||
NS_IMETHOD IsFontScalable( const nsString & aFontName, PRBool* aResult );
|
||||
|
||||
// nsIFontNameIterator
|
||||
|
||||
NS_IMETHOD Reset();
|
||||
NS_IMETHOD Get( nsString* aFontName );
|
||||
NS_IMETHOD Advance();
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
NS_IMETHOD LoadFontList();
|
||||
|
||||
nsVoidArray * mFontList;
|
||||
|
||||
PRInt32 mNameIterInx;
|
||||
|
||||
nsFontSizeIterator * mSizeIter;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,88 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsFontSizeIterator.h"
|
||||
|
||||
#include "nsFont.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
|
||||
NS_IMPL_ADDREF(nsFontSizeIterator)
|
||||
NS_IMPL_RELEASE(nsFontSizeIterator)
|
||||
NS_IMPL_QUERY_INTERFACE(nsFontSizeIterator, nsIFontSizeIterator::GetIID())
|
||||
|
||||
//----------------------------------------------------------
|
||||
nsFontSizeIterator::nsFontSizeIterator()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mFontInfo = nsnull;
|
||||
mSizeIterInx = 0;
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
nsFontSizeIterator::~nsFontSizeIterator()
|
||||
{
|
||||
}
|
||||
|
||||
///----------------------------------------------------------
|
||||
//-- nsIFontNameIterator
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontSizeIterator::Reset()
|
||||
{
|
||||
mSizeIterInx = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontSizeIterator::Get( double* aFontSize )
|
||||
{
|
||||
if (nsnull != mFontInfo->mSizes &&
|
||||
mFontInfo->mSizes->Count() > 0 &&
|
||||
mSizeIterInx < mFontInfo->mSizes->Count()) {
|
||||
PRUint32 size = (PRUint32)mFontInfo->mSizes->ElementAt(mSizeIterInx);
|
||||
*aFontSize = (double)size;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontSizeIterator::Advance()
|
||||
{
|
||||
if (nsnull != mFontInfo->mSizes &&
|
||||
mFontInfo->mSizes->Count() > 0 &&
|
||||
mSizeIterInx < mFontInfo->mSizes->Count()-2) {
|
||||
mSizeIterInx++;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
NS_IMETHODIMP nsFontSizeIterator::SetFontInfo( FontInfo * aFontInfo )
|
||||
{
|
||||
mFontInfo = aFontInfo;
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef __nsFontSizeIterator
|
||||
#define __nsFontSizeIterator
|
||||
|
||||
#include "nsIFontSizeIterator.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsVoidArray;
|
||||
|
||||
typedef struct {
|
||||
nsString mName;
|
||||
PRBool mIsScalable;
|
||||
nsVoidArray * mSizes;
|
||||
} FontInfo;
|
||||
|
||||
|
||||
class nsFontSizeIterator: public nsIFontSizeIterator {
|
||||
public:
|
||||
nsFontSizeIterator();
|
||||
virtual ~nsFontSizeIterator();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIFontSizeIterator
|
||||
NS_IMETHOD Reset();
|
||||
NS_IMETHOD Get( double* aFontSize );
|
||||
NS_IMETHOD Advance();
|
||||
|
||||
// Native impl
|
||||
NS_IMETHOD SetFontInfo( FontInfo * aFontInfo );
|
||||
|
||||
protected:
|
||||
|
||||
FontInfo * mFontInfo;
|
||||
PRInt32 mSizeIterInx; // current index of iter
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,967 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsWidget.h"
|
||||
#include "nsWindow.h"
|
||||
|
||||
#include "nsScrollbar.h"
|
||||
#include "nsIFileWidget.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsIMenu.h"
|
||||
#include "nsIMenuItem.h"
|
||||
#include "nsIMenuListener.h"
|
||||
|
||||
#include "nsTextWidget.h"
|
||||
|
||||
#include "nsICharsetConverterManager.h"
|
||||
#include "nsIPlatformCharset.h"
|
||||
#include "nsIServiceManager.h"
|
||||
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
|
||||
|
||||
#include "stdio.h"
|
||||
#include "ctype.h"
|
||||
|
||||
#include "gtk/gtk.h"
|
||||
#include "nsGtkEventHandler.h"
|
||||
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#ifdef DEBUG_pavlov
|
||||
//#define DEBUG_EVENTS 1
|
||||
#endif
|
||||
|
||||
struct EventInfo {
|
||||
nsWidget *widget; // the widget
|
||||
nsRect *rect; // the rect
|
||||
};
|
||||
|
||||
//==============================================================
|
||||
void InitAllocationEvent(GtkAllocation *aAlloc,
|
||||
gpointer p,
|
||||
nsSizeEvent &anEvent,
|
||||
PRUint32 aEventType)
|
||||
{
|
||||
anEvent.message = aEventType;
|
||||
anEvent.widget = (nsWidget *) p;
|
||||
|
||||
anEvent.eventStructType = NS_SIZE_EVENT;
|
||||
|
||||
if (aAlloc != nsnull) {
|
||||
// HACK
|
||||
// nsRect *foo = new nsRect(aAlloc->x, aAlloc->y, aAlloc->width, aAlloc->height);
|
||||
nsRect *foo = new nsRect(0, 0, aAlloc->width, aAlloc->height);
|
||||
anEvent.windowSize = foo;
|
||||
// anEvent.point.x = aAlloc->x;
|
||||
// anEvent.point.y = aAlloc->y;
|
||||
// HACK
|
||||
anEvent.point.x = 0;
|
||||
anEvent.point.y = 0;
|
||||
anEvent.mWinWidth = aAlloc->width;
|
||||
anEvent.mWinHeight = aAlloc->height;
|
||||
}
|
||||
|
||||
anEvent.time = PR_IntervalNow();
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
void InitConfigureEvent(GdkEventConfigure *aConf,
|
||||
gpointer p,
|
||||
nsSizeEvent &anEvent,
|
||||
PRUint32 aEventType)
|
||||
{
|
||||
anEvent.message = aEventType;
|
||||
anEvent.widget = (nsWidget *) p;
|
||||
|
||||
anEvent.eventStructType = NS_SIZE_EVENT;
|
||||
|
||||
if (aConf != nsnull) {
|
||||
/* do we accually need to alloc a new rect, or can we just set the
|
||||
current one */
|
||||
nsRect *foo = new nsRect(aConf->x, aConf->y, aConf->width, aConf->height);
|
||||
anEvent.windowSize = foo;
|
||||
anEvent.point.x = aConf->x;
|
||||
anEvent.point.y = aConf->y;
|
||||
anEvent.mWinWidth = aConf->width;
|
||||
anEvent.mWinHeight = aConf->height;
|
||||
}
|
||||
// this usually returns 0
|
||||
anEvent.time = 0;
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
void InitExposeEvent(GdkEventExpose *aGEE,
|
||||
gpointer p,
|
||||
nsPaintEvent &anEvent,
|
||||
PRUint32 aEventType)
|
||||
{
|
||||
anEvent.message = aEventType;
|
||||
anEvent.widget = (nsWidget *) p;
|
||||
|
||||
anEvent.eventStructType = NS_PAINT_EVENT;
|
||||
|
||||
if (aGEE != nsnull)
|
||||
{
|
||||
#ifdef DEBUG_EVENTS
|
||||
g_print("expose event: x = %i , y = %i , w = %i , h = %i\n",
|
||||
aGEE->area.x, aGEE->area.y,
|
||||
aGEE->area.width, aGEE->area.height);
|
||||
#endif
|
||||
anEvent.point.x = aGEE->area.x;
|
||||
anEvent.point.y = aGEE->area.y;
|
||||
|
||||
nsRect *rect = new nsRect(aGEE->area.x, aGEE->area.y,
|
||||
aGEE->area.width, aGEE->area.height);
|
||||
anEvent.rect = rect;
|
||||
anEvent.time = gdk_event_get_time((GdkEvent*)aGEE);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================
|
||||
void UninitExposeEvent(GdkEventExpose *aGEE,
|
||||
gpointer p,
|
||||
nsPaintEvent &anEvent,
|
||||
PRUint32 aEventType)
|
||||
{
|
||||
if (aGEE != nsnull) {
|
||||
delete anEvent.rect;
|
||||
}
|
||||
}
|
||||
|
||||
struct nsKeyConverter {
|
||||
int vkCode; // Platform independent key code
|
||||
int keysym; // GDK keysym key code
|
||||
};
|
||||
|
||||
//
|
||||
// Netscape keycodes are defined in widget/public/nsGUIEvent.h
|
||||
// GTK keycodes are defined in <gdk/gdkkeysyms.h>
|
||||
//
|
||||
struct nsKeyConverter nsKeycodes[] = {
|
||||
{ NS_VK_CANCEL, GDK_Cancel },
|
||||
{ NS_VK_BACK, GDK_BackSpace },
|
||||
{ NS_VK_TAB, GDK_Tab },
|
||||
{ NS_VK_TAB, GDK_ISO_Left_Tab },
|
||||
{ NS_VK_CLEAR, GDK_Clear },
|
||||
{ NS_VK_RETURN, GDK_Return },
|
||||
{ NS_VK_SHIFT, GDK_Shift_L },
|
||||
{ NS_VK_SHIFT, GDK_Shift_R },
|
||||
{ NS_VK_CONTROL, GDK_Control_L },
|
||||
{ NS_VK_CONTROL, GDK_Control_R },
|
||||
{ NS_VK_ALT, GDK_Alt_L },
|
||||
{ NS_VK_ALT, GDK_Alt_R },
|
||||
{ NS_VK_PAUSE, GDK_Pause },
|
||||
{ NS_VK_CAPS_LOCK, GDK_Caps_Lock },
|
||||
{ NS_VK_ESCAPE, GDK_Escape },
|
||||
{ NS_VK_SPACE, GDK_space },
|
||||
{ NS_VK_PAGE_UP, GDK_Page_Up },
|
||||
{ NS_VK_PAGE_DOWN, GDK_Page_Down },
|
||||
{ NS_VK_END, GDK_End },
|
||||
{ NS_VK_HOME, GDK_Home },
|
||||
{ NS_VK_LEFT, GDK_Left },
|
||||
{ NS_VK_UP, GDK_Up },
|
||||
{ NS_VK_RIGHT, GDK_Right },
|
||||
{ NS_VK_DOWN, GDK_Down },
|
||||
{ NS_VK_PRINTSCREEN, GDK_Print },
|
||||
{ NS_VK_INSERT, GDK_Insert },
|
||||
{ NS_VK_DELETE, GDK_Delete },
|
||||
|
||||
{ NS_VK_MULTIPLY, GDK_KP_Multiply },
|
||||
{ NS_VK_ADD, GDK_KP_Add },
|
||||
{ NS_VK_SEPARATOR, GDK_KP_Separator },
|
||||
{ NS_VK_SUBTRACT, GDK_KP_Subtract },
|
||||
{ NS_VK_DECIMAL, GDK_KP_Decimal },
|
||||
{ NS_VK_DIVIDE, GDK_KP_Divide },
|
||||
{ NS_VK_RETURN, GDK_KP_Enter },
|
||||
|
||||
// NS doesn't have dash or equals distinct from the numeric keypad ones,
|
||||
// so we'll use those for now. See bug 17008:
|
||||
{ NS_VK_SUBTRACT, GDK_minus },
|
||||
{ NS_VK_EQUALS, GDK_equal },
|
||||
// and we don't have a single-quote symbol either:
|
||||
{ NS_VK_QUOTE, GDK_apostrophe },
|
||||
|
||||
{ NS_VK_COMMA, GDK_comma },
|
||||
{ NS_VK_PERIOD, GDK_period },
|
||||
{ NS_VK_SLASH, GDK_slash },
|
||||
{ NS_VK_BACK_SLASH, GDK_backslash },
|
||||
{ NS_VK_BACK_QUOTE, GDK_grave },
|
||||
{ NS_VK_OPEN_BRACKET, GDK_bracketleft },
|
||||
{ NS_VK_CLOSE_BRACKET, GDK_bracketright },
|
||||
{ NS_VK_QUOTE, GDK_quotedbl },
|
||||
|
||||
// Some shifted keys, see bug 15463.
|
||||
// These should be subject to different keyboard mappings;
|
||||
// how do we do that in gtk?
|
||||
{ NS_VK_SEMICOLON, GDK_colon },
|
||||
{ NS_VK_BACK_QUOTE, GDK_asciitilde },
|
||||
{ NS_VK_COMMA, GDK_less },
|
||||
{ NS_VK_PERIOD, GDK_greater },
|
||||
{ NS_VK_SLASH, GDK_question },
|
||||
{ NS_VK_1, GDK_exclam },
|
||||
{ NS_VK_2, GDK_at },
|
||||
{ NS_VK_3, GDK_numbersign },
|
||||
{ NS_VK_4, GDK_dollar },
|
||||
{ NS_VK_5, GDK_percent },
|
||||
{ NS_VK_6, GDK_asciicircum },
|
||||
{ NS_VK_7, GDK_ampersand },
|
||||
{ NS_VK_8, GDK_asterisk },
|
||||
{ NS_VK_9, GDK_parenleft },
|
||||
{ NS_VK_0, GDK_parenright },
|
||||
{ NS_VK_SUBTRACT, GDK_underscore },
|
||||
{ NS_VK_EQUALS, GDK_plus }
|
||||
};
|
||||
|
||||
void nsGtkWidget_InitNSKeyEvent(int aEventType, nsKeyEvent& aKeyEvent,
|
||||
GtkWidget *w, gpointer p, GdkEventKey * event);
|
||||
|
||||
//==============================================================
|
||||
|
||||
// Input keysym is in gtk format; output is in NS_VK format
|
||||
int nsPlatformToDOMKeyCode(GdkEventKey *aGEK)
|
||||
{
|
||||
int i;
|
||||
int length = sizeof(nsKeycodes) / sizeof(struct nsKeyConverter);
|
||||
|
||||
int keysym = aGEK->keyval;
|
||||
|
||||
// First, try to handle alphanumeric input, not listed in nsKeycodes:
|
||||
// most likely, more letters will be getting typed in than things in
|
||||
// the key list, so we will look through these first.
|
||||
|
||||
// since X has different key symbols for upper and lowercase letters and
|
||||
// mozilla does not, convert gdk's to mozilla's
|
||||
if (keysym >= GDK_a && keysym <= GDK_z)
|
||||
return keysym - GDK_a + NS_VK_A;
|
||||
if (keysym >= GDK_A && keysym <= GDK_Z)
|
||||
return keysym - GDK_A + NS_VK_A;
|
||||
|
||||
// numbers
|
||||
if (keysym >= GDK_0 && keysym <= GDK_9)
|
||||
return keysym - GDK_0 + NS_VK_0;
|
||||
|
||||
// keypad numbers
|
||||
if (keysym >= GDK_KP_0 && keysym <= GDK_KP_9)
|
||||
return keysym - GDK_KP_0 + NS_VK_NUMPAD0;
|
||||
|
||||
// misc other things
|
||||
for (i = 0; i < length; i++) {
|
||||
if (nsKeycodes[i].keysym == keysym)
|
||||
return(nsKeycodes[i].vkCode);
|
||||
}
|
||||
|
||||
// function keys
|
||||
if (keysym >= GDK_F1 && keysym <= GDK_F24)
|
||||
return keysym - GDK_F1 + NS_VK_F1;
|
||||
|
||||
#if defined(DEBUG_akkana) || defined(DEBUG_ftang)
|
||||
printf("No match in nsPlatformToDOMKeyCode: keysym is 0x%x, string is %s\n", keysym, aGEK->string);
|
||||
#endif
|
||||
|
||||
return((int)0);
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
|
||||
PRUint32 nsConvertCharCodeToUnicode(GdkEventKey* aGEK)
|
||||
{
|
||||
// For control chars, GDK sets string to be the actual ascii value.
|
||||
// Map that to what nsKeyEvent wants, which currently --
|
||||
// TEMPORARILY (the spec has changed and will be switched over
|
||||
// when the tree opens for M11) --
|
||||
// is the ascii for the actual event (e.g. 1 for control-a).
|
||||
// This is only true for control chars; for alt chars, send the
|
||||
// ascii for the key, i.e. a for alt-a.
|
||||
if (aGEK->state & GDK_CONTROL_MASK)
|
||||
{
|
||||
if (aGEK->state & GDK_SHIFT_MASK)
|
||||
return aGEK->string[0] + 'A' - 1;
|
||||
else
|
||||
return aGEK->string[0] + 'a' - 1;
|
||||
}
|
||||
|
||||
// For now (obviously this will need to change for IME),
|
||||
// only set a char code if the result is printable:
|
||||
if (!isprint(aGEK->string[0]))
|
||||
return 0;
|
||||
|
||||
// ALT keys in gdk give the upper case character in string,
|
||||
// but we want the lower case char in char code
|
||||
// unless shift was also pressed.
|
||||
if (((aGEK->state & GDK_MOD1_MASK))
|
||||
&& !(aGEK->state & GDK_SHIFT_MASK)
|
||||
&& isupper(aGEK->string[0]))
|
||||
return tolower(aGEK->string[0]);
|
||||
|
||||
//
|
||||
// placeholder for something a little more interesting and correct
|
||||
//
|
||||
return aGEK->string[0];
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
void InitKeyEvent(GdkEventKey *aGEK,
|
||||
gpointer p,
|
||||
nsKeyEvent &anEvent,
|
||||
PRUint32 aEventType)
|
||||
{
|
||||
anEvent.message = aEventType;
|
||||
anEvent.widget = (nsWidget *) p;
|
||||
|
||||
anEvent.eventStructType = NS_KEY_EVENT;
|
||||
|
||||
if (aGEK != nsnull) {
|
||||
anEvent.keyCode = nsPlatformToDOMKeyCode(aGEK);
|
||||
anEvent.charCode = 0;
|
||||
anEvent.time = aGEK->time;
|
||||
anEvent.isShift = (aGEK->state & GDK_SHIFT_MASK) ? PR_TRUE : PR_FALSE;
|
||||
anEvent.isControl = (aGEK->state & GDK_CONTROL_MASK) ? PR_TRUE : PR_FALSE;
|
||||
anEvent.isAlt = (aGEK->state & GDK_MOD1_MASK) ? PR_TRUE : PR_FALSE;
|
||||
// XXX
|
||||
anEvent.isMeta = PR_FALSE; //(aGEK->state & GDK_MOD2_MASK) ? PR_TRUE : PR_FALSE;
|
||||
anEvent.point.x = 0;
|
||||
anEvent.point.y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void InitKeyPressEvent(GdkEventKey *aGEK,
|
||||
gpointer p,
|
||||
nsKeyEvent &anEvent)
|
||||
{
|
||||
//
|
||||
// init the basic event fields
|
||||
//
|
||||
anEvent.eventStructType = NS_KEY_EVENT;
|
||||
anEvent.message = NS_KEY_PRESS;
|
||||
anEvent.widget = (nsWidget*)p;
|
||||
|
||||
if (aGEK!=nsnull)
|
||||
{
|
||||
anEvent.isShift = (aGEK->state & GDK_SHIFT_MASK) ? PR_TRUE : PR_FALSE;
|
||||
anEvent.isControl = (aGEK->state & GDK_CONTROL_MASK) ? PR_TRUE : PR_FALSE;
|
||||
anEvent.isAlt = (aGEK->state & GDK_MOD1_MASK) ? PR_TRUE : PR_FALSE;
|
||||
// XXX
|
||||
anEvent.isMeta = PR_FALSE; //(aGEK->state & GDK_MOD2_MASK) ? PR_TRUE : PR_FALSE;
|
||||
|
||||
if(aGEK->length)
|
||||
anEvent.charCode = nsConvertCharCodeToUnicode(aGEK);
|
||||
else
|
||||
anEvent.charCode = 0;
|
||||
|
||||
if (anEvent.charCode) {
|
||||
anEvent.keyCode = 0;
|
||||
anEvent.isShift = PR_FALSE;
|
||||
} else
|
||||
anEvent.keyCode = nsPlatformToDOMKeyCode(aGEK);
|
||||
|
||||
#if defined(DEBUG_akkana) || defined(DEBUG_pavlov) || defined (DEBUG_ftang)
|
||||
printf("Key Press event: keyCode = 0x%x, char code = '%c'",
|
||||
anEvent.keyCode, anEvent.charCode);
|
||||
if (anEvent.isShift)
|
||||
printf(" [shift]");
|
||||
if (anEvent.isControl)
|
||||
printf(" [ctrl]");
|
||||
if (anEvent.isAlt)
|
||||
printf(" [alt]");
|
||||
if (anEvent.isMeta)
|
||||
printf(" [meta]");
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
anEvent.time = aGEK->time;
|
||||
anEvent.point.x = 0;
|
||||
anEvent.point.y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================
|
||||
void UninitKeyEvent(GdkEventKey *aGEK,
|
||||
gpointer p,
|
||||
nsKeyEvent &anEvent,
|
||||
PRUint32 aEventType)
|
||||
{
|
||||
}
|
||||
|
||||
/*==============================================================
|
||||
==============================================================
|
||||
=============================================================
|
||||
==============================================================*/
|
||||
|
||||
void handle_size_allocate(GtkWidget *w, GtkAllocation *alloc, gpointer p)
|
||||
{
|
||||
nsWindow *widget = (nsWindow *)p;
|
||||
nsSizeEvent event;
|
||||
|
||||
InitAllocationEvent(alloc, p, event, NS_SIZE);
|
||||
NS_ADDREF(widget);
|
||||
widget->OnResize(event);
|
||||
NS_RELEASE(widget);
|
||||
|
||||
delete event.windowSize;
|
||||
}
|
||||
|
||||
gint handle_expose_event(GtkWidget *w, GdkEventExpose *event, gpointer p)
|
||||
{
|
||||
if (event->type == GDK_NO_EXPOSE)
|
||||
return PR_FALSE;
|
||||
|
||||
nsPaintEvent pevent;
|
||||
InitExposeEvent(event, p, pevent, NS_PAINT);
|
||||
|
||||
nsWindow *win = (nsWindow *)p;
|
||||
win->AddRef();
|
||||
win->OnExpose(pevent);
|
||||
win->Release();
|
||||
|
||||
UninitExposeEvent(event, p, pevent, NS_PAINT);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
void menu_item_activate_handler(GtkWidget *w, gpointer p)
|
||||
{
|
||||
// g_print("menu_item_activate_handler\n");
|
||||
|
||||
nsIMenuListener *menuListener = nsnull;
|
||||
nsIMenuItem *menuItem = (nsIMenuItem *)p;
|
||||
if (menuItem != nsnull) {
|
||||
nsMenuEvent mevent;
|
||||
mevent.message = NS_MENU_SELECTED;
|
||||
mevent.eventStructType = NS_MENU_EVENT;
|
||||
mevent.point.x = 0;
|
||||
mevent.point.y = 0;
|
||||
// mevent.widget = menuItem;
|
||||
mevent.widget = nsnull;
|
||||
menuItem->GetCommand(mevent.mCommand);
|
||||
|
||||
mevent.mMenuItem = menuItem;
|
||||
mevent.time = PR_IntervalNow();
|
||||
|
||||
// FIXME - THIS SHOULD WORK. FIX EVENTS FOR XP CODE!!!!! (pav)
|
||||
// nsEventStatus status;
|
||||
// mevent.widget->DispatchEvent((nsGUIEvent *)&mevent, status);
|
||||
|
||||
menuItem->QueryInterface(nsIMenuListener::GetIID(), (void**)&menuListener);
|
||||
if(menuListener) {
|
||||
menuListener->MenuItemSelected(mevent);
|
||||
NS_IF_RELEASE(menuListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
void menu_map_handler(GtkWidget *w, gpointer p)
|
||||
{
|
||||
nsIMenuListener *menuListener = nsnull;
|
||||
nsIMenu *menu = (nsIMenu *)p;
|
||||
if (menu != nsnull) {
|
||||
nsMenuEvent mevent;
|
||||
mevent.message = NS_MENU_SELECTED;
|
||||
mevent.eventStructType = NS_MENU_EVENT;
|
||||
mevent.point.x = 0;
|
||||
mevent.point.y = 0;
|
||||
mevent.widget = nsnull;
|
||||
|
||||
mevent.time = PR_IntervalNow();
|
||||
|
||||
menu->QueryInterface(nsIMenuListener::GetIID(), (void**)&menuListener);
|
||||
|
||||
if(menuListener) {
|
||||
menuListener->MenuConstruct(
|
||||
mevent,
|
||||
nsnull, //parent window
|
||||
nsnull, //menuNode
|
||||
nsnull ); // webshell
|
||||
NS_IF_RELEASE(menuListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
void menu_unmap_handler(GtkWidget *w, gpointer p)
|
||||
{
|
||||
nsIMenuListener *menuListener = nsnull;
|
||||
nsIMenu *menu = (nsIMenu *)p;
|
||||
if (menu != nsnull) {
|
||||
nsMenuEvent mevent;
|
||||
mevent.message = NS_MENU_SELECTED;
|
||||
mevent.eventStructType = NS_MENU_EVENT;
|
||||
mevent.point.x = 0;
|
||||
mevent.point.y = 0;
|
||||
mevent.widget = nsnull;
|
||||
|
||||
mevent.time = PR_IntervalNow();
|
||||
|
||||
menu->QueryInterface(nsIMenuListener::GetIID(), (void**)&menuListener);
|
||||
if(menuListener) {
|
||||
menuListener->MenuDestruct(mevent);
|
||||
NS_IF_RELEASE(menuListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==============================================================
|
||||
void handle_scrollbar_value_changed(GtkAdjustment *adj, gpointer p)
|
||||
{
|
||||
nsScrollbar *widget = (nsScrollbar*) p;
|
||||
nsScrollbarEvent sevent;
|
||||
|
||||
sevent.message = NS_SCROLLBAR_POS;
|
||||
sevent.widget = (nsWidget *) p;
|
||||
sevent.eventStructType = NS_SCROLLBAR_EVENT;
|
||||
|
||||
GdkWindow *win = (GdkWindow *)widget->GetNativeData(NS_NATIVE_WINDOW);
|
||||
gdk_window_get_pointer(win, &sevent.point.x, &sevent.point.y, nsnull);
|
||||
|
||||
widget->AddRef();
|
||||
widget->OnScroll(sevent, adj->value);
|
||||
widget->Release();
|
||||
|
||||
/* FIXME we need to set point.* from the event stuff. */
|
||||
#if 0
|
||||
nsWindow * widgetWindow = (nsWindow *) p ;
|
||||
XmScrollBarCallbackStruct * cbs = (XmScrollBarCallbackStruct*) call_data;
|
||||
sevent.widget = (nsWindow *) p;
|
||||
if (cbs->event != nsnull) {
|
||||
sevent.point.x = cbs->event->xbutton.x;
|
||||
sevent.point.y = cbs->event->xbutton.y;
|
||||
} else {
|
||||
sevent.point.x = 0;
|
||||
sevent.point.y = 0;
|
||||
}
|
||||
sevent.time = 0; //XXX Implement this
|
||||
|
||||
switch (cbs->reason) {
|
||||
|
||||
case XmCR_INCREMENT:
|
||||
sevent.message = NS_SCROLLBAR_LINE_NEXT;
|
||||
break;
|
||||
|
||||
case XmCR_DECREMENT:
|
||||
sevent.message = NS_SCROLLBAR_LINE_PREV;
|
||||
break;
|
||||
|
||||
case XmCR_PAGE_INCREMENT:
|
||||
sevent.message = NS_SCROLLBAR_PAGE_NEXT;
|
||||
break;
|
||||
|
||||
case XmCR_PAGE_DECREMENT:
|
||||
sevent.message = NS_SCROLLBAR_PAGE_PREV;
|
||||
break;
|
||||
|
||||
case XmCR_DRAG:
|
||||
sevent.message = NS_SCROLLBAR_POS;
|
||||
break;
|
||||
|
||||
case XmCR_VALUE_CHANGED:
|
||||
sevent.message = NS_SCROLLBAR_POS;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static gint composition_start(GdkEventKey *aEvent, nsWindow *aWin,
|
||||
nsEventStatus *aStatus) {
|
||||
nsCompositionEvent compEvent;
|
||||
|
||||
compEvent.widget = (nsWidget*)aWin;
|
||||
compEvent.point.x = 0;
|
||||
compEvent.point.y = 0;
|
||||
compEvent.time = aEvent->time;
|
||||
compEvent.message = NS_COMPOSITION_START;
|
||||
compEvent.eventStructType = NS_COMPOSITION_START;
|
||||
compEvent.compositionMessage = NS_COMPOSITION_START;
|
||||
aWin->DispatchEvent(&compEvent, *aStatus);
|
||||
|
||||
// set SpotLocation
|
||||
aWin->SetXICSpotLocation(compEvent.theReply.mCursorPosition);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static gint composition_draw(GdkEventKey *aEvent, nsWindow *aWin,
|
||||
nsIUnicodeDecoder *aDecoder,
|
||||
nsEventStatus *aStatus) {
|
||||
if (!aWin->mIMECompositionUniString) {
|
||||
aWin->mIMECompositionUniStringSize = 128;
|
||||
aWin->mIMECompositionUniString =
|
||||
new PRUnichar[aWin->mIMECompositionUniStringSize];
|
||||
}
|
||||
PRUnichar *uniChar;
|
||||
PRInt32 uniCharSize;
|
||||
PRInt32 srcLen = aEvent->length;
|
||||
for (;;) {
|
||||
uniChar = aWin->mIMECompositionUniString;
|
||||
uniCharSize = aWin->mIMECompositionUniStringSize - 1;
|
||||
aDecoder->Convert((char*)aEvent->string, &srcLen, uniChar, &uniCharSize);
|
||||
if (srcLen == aEvent->length &&
|
||||
uniCharSize < aWin->mIMECompositionUniStringSize - 1) {
|
||||
break;
|
||||
}
|
||||
aWin->mIMECompositionUniStringSize += 32;
|
||||
aWin->mIMECompositionUniString =
|
||||
new PRUnichar[aWin->mIMECompositionUniStringSize];
|
||||
}
|
||||
aWin->mIMECompositionUniString[uniCharSize] = 0;
|
||||
|
||||
nsTextEvent textEvent;
|
||||
textEvent.message = NS_TEXT_EVENT;
|
||||
textEvent.widget = (nsWidget*)aWin;
|
||||
textEvent.time = aEvent->time;
|
||||
textEvent.point.x = 0;
|
||||
textEvent.point.y = 0;
|
||||
textEvent.theText = aWin->mIMECompositionUniString;
|
||||
textEvent.rangeCount = 0;
|
||||
textEvent.rangeArray = nsnull;
|
||||
textEvent.isShift = (aEvent->state & GDK_SHIFT_MASK) ? PR_TRUE : PR_FALSE;
|
||||
textEvent.isControl = (aEvent->state & GDK_CONTROL_MASK) ? PR_TRUE : PR_FALSE;
|
||||
textEvent.isAlt = (aEvent->state & GDK_MOD1_MASK) ? PR_TRUE : PR_FALSE;
|
||||
// XXX
|
||||
textEvent.isMeta = PR_FALSE; //(aEvent->state & GDK_MOD2_MASK) ? PR_TRUE : PR_FALSE;
|
||||
textEvent.eventStructType = NS_TEXT_EVENT;
|
||||
aWin->DispatchEvent(&textEvent, *aStatus);
|
||||
|
||||
aWin->SetXICSpotLocation(textEvent.theReply.mCursorPosition);
|
||||
return True;
|
||||
}
|
||||
|
||||
static gint composition_end(GdkEventKey *aEvent, nsWindow *aWin,
|
||||
nsEventStatus *aStatus) {
|
||||
nsCompositionEvent compEvent;
|
||||
|
||||
compEvent.widget = (nsWidget*)aWin;
|
||||
compEvent.point.x = 0;
|
||||
compEvent.point.y = 0;
|
||||
compEvent.time = aEvent->time;
|
||||
compEvent.message = NS_COMPOSITION_END;
|
||||
compEvent.eventStructType = NS_COMPOSITION_END;
|
||||
compEvent.compositionMessage = NS_COMPOSITION_END;
|
||||
aWin->DispatchEvent(&compEvent, *aStatus);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static nsIUnicodeDecoder*
|
||||
open_unicode_decoder(void) {
|
||||
nsresult result = NS_ERROR_FAILURE;
|
||||
nsIUnicodeDecoder *decoder = nsnull;
|
||||
NS_WITH_SERVICE(nsIPlatformCharset, platform, NS_PLATFORMCHARSET_PROGID,
|
||||
&result);
|
||||
if (platform && NS_SUCCEEDED(result)) {
|
||||
nsAutoString charset("");
|
||||
result = platform->GetCharset(kPlatformCharsetSel_Menu, charset);
|
||||
if (NS_FAILED(result) || (charset.Length() == 0)) {
|
||||
charset = "ISO-8859-1"; // default
|
||||
}
|
||||
nsICharsetConverterManager* manager = nsnull;
|
||||
nsresult res = nsServiceManager::
|
||||
GetService(kCharsetConverterManagerCID,
|
||||
nsCOMTypeInfo<nsICharsetConverterManager>::GetIID(),
|
||||
(nsISupports**)&manager);
|
||||
if (manager && NS_SUCCEEDED(res)) {
|
||||
manager->GetUnicodeDecoder(&charset, &decoder);
|
||||
nsServiceManager::ReleaseService(kCharsetConverterManagerCID, manager);
|
||||
}
|
||||
}
|
||||
return decoder;
|
||||
}
|
||||
|
||||
// GTK's text widget already does XIM, so we don't want to do this again
|
||||
gint handle_key_press_event_for_text(GtkObject *w, GdkEventKey* event,
|
||||
gpointer p)
|
||||
{
|
||||
nsKeyEvent kevent;
|
||||
nsTextWidget* win = (nsTextWidget*)p;
|
||||
|
||||
// work around for annoying things.
|
||||
if (event->keyval == GDK_Tab)
|
||||
if (event->state & GDK_CONTROL_MASK)
|
||||
if (event->state & GDK_MOD1_MASK)
|
||||
return PR_FALSE;
|
||||
|
||||
// Don't pass shift, control and alt as key press events
|
||||
if (event->keyval == GDK_Shift_L
|
||||
|| event->keyval == GDK_Shift_R
|
||||
|| event->keyval == GDK_Control_L
|
||||
|| event->keyval == GDK_Control_R)
|
||||
return PR_TRUE;
|
||||
|
||||
win->AddRef();
|
||||
InitKeyEvent(event, p, kevent, NS_KEY_DOWN);
|
||||
win->OnKey(kevent);
|
||||
|
||||
//
|
||||
// Second, dispatch the Key event as a key press event w/ a Unicode
|
||||
// character code. Note we have to check for modifier keys, since
|
||||
// gtk returns a character value for them
|
||||
//
|
||||
InitKeyPressEvent(event,p, kevent);
|
||||
win->OnKey(kevent);
|
||||
|
||||
win->Release();
|
||||
if (w)
|
||||
{
|
||||
gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_press_event");
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// GTK's text widget already does XIM, so we don't want to do this again
|
||||
gint handle_key_release_event_for_text(GtkObject *w, GdkEventKey* event,
|
||||
gpointer p)
|
||||
{
|
||||
nsKeyEvent kevent;
|
||||
nsTextWidget* win = (nsTextWidget*)p;
|
||||
|
||||
// Don't pass shift, control and alt as key release events
|
||||
if (event->keyval == GDK_Shift_L
|
||||
|| event->keyval == GDK_Shift_R
|
||||
|| event->keyval == GDK_Control_L
|
||||
|| event->keyval == GDK_Control_R)
|
||||
return PR_TRUE;
|
||||
|
||||
InitKeyEvent(event, p, kevent, NS_KEY_UP);
|
||||
win->AddRef();
|
||||
win->OnKey(kevent);
|
||||
win->Release();
|
||||
|
||||
if (w)
|
||||
{
|
||||
gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_release_event");
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================
|
||||
gint handle_key_press_event(GtkObject *w, GdkEventKey* event, gpointer p)
|
||||
{
|
||||
nsKeyEvent kevent;
|
||||
nsWindow* win = (nsWindow*)p;
|
||||
|
||||
// work around for annoying things.
|
||||
if (event->keyval == GDK_Tab)
|
||||
if (event->state & GDK_CONTROL_MASK)
|
||||
if (event->state & GDK_MOD1_MASK)
|
||||
return PR_FALSE;
|
||||
|
||||
// Don't pass shift, control and alt as key press events
|
||||
if (event->keyval == GDK_Shift_L
|
||||
|| event->keyval == GDK_Shift_R
|
||||
|| event->keyval == GDK_Control_L
|
||||
|| event->keyval == GDK_Control_R)
|
||||
return PR_TRUE;
|
||||
|
||||
win->AddRef();
|
||||
//
|
||||
// First, dispatch the Key event as a virtual key down event
|
||||
//
|
||||
InitKeyEvent(event, p, kevent, NS_KEY_DOWN);
|
||||
win->OnKey(kevent);
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Second, dispatch the Key event as a key press event w/ a Unicode
|
||||
// character code. Note we have to check for modifier keys, since
|
||||
// gtk returns a character value for them
|
||||
//
|
||||
if (event->length) {
|
||||
static nsIUnicodeDecoder *decoder = nsnull;
|
||||
if (!decoder) {
|
||||
decoder = open_unicode_decoder();
|
||||
}
|
||||
if (decoder && (!kevent.keyCode)) {
|
||||
nsEventStatus status;
|
||||
composition_start(event, win, &status);
|
||||
composition_draw(event, win, decoder, &status);
|
||||
composition_end(event, win, &status);
|
||||
} else {
|
||||
InitKeyPressEvent(event,p, kevent);
|
||||
win->OnKey(kevent);
|
||||
nsEventStatus status;
|
||||
composition_start(event, win, &status);
|
||||
composition_end(event, win, &status);
|
||||
}
|
||||
} else { // for Home/End/Up/Down/Left/Right/PageUp/PageDown key
|
||||
InitKeyPressEvent(event,p, kevent);
|
||||
win->OnKey(kevent);
|
||||
}
|
||||
|
||||
win->Release();
|
||||
if (w)
|
||||
{
|
||||
gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_press_event");
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
gint handle_key_release_event(GtkObject *w, GdkEventKey* event, gpointer p)
|
||||
{
|
||||
// Don't pass shift, control and alt as key release events
|
||||
if (event->keyval == GDK_Shift_L
|
||||
|| event->keyval == GDK_Shift_R
|
||||
|| event->keyval == GDK_Control_L
|
||||
|| event->keyval == GDK_Control_R)
|
||||
return PR_TRUE;
|
||||
|
||||
nsKeyEvent kevent;
|
||||
InitKeyEvent(event, p, kevent, NS_KEY_UP);
|
||||
|
||||
nsWindow * win = (nsWindow *) p;
|
||||
win->AddRef();
|
||||
win->OnKey(kevent);
|
||||
win->Release();
|
||||
|
||||
if (w)
|
||||
{
|
||||
gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_release_event");
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
void
|
||||
handle_gdk_event (GdkEvent *event, gpointer data)
|
||||
{
|
||||
GtkObject *object = nsnull;
|
||||
|
||||
if (event->any.window)
|
||||
gdk_window_get_user_data (event->any.window, (void **)&object);
|
||||
|
||||
if (object != nsnull &&
|
||||
GDK_IS_SUPERWIN (object))
|
||||
{
|
||||
// It was an event on one of our superwindows
|
||||
|
||||
nsWindow *window = (nsWindow *)gtk_object_get_data (object, "nsWindow");
|
||||
|
||||
if (gtk_grab_get_current () != nsnull)
|
||||
{
|
||||
// A GTK+ grab is in effect. Rewrite the event to point to
|
||||
// our toplevel, and pass it through.
|
||||
// XXX: We should actually translate the coordinates
|
||||
|
||||
gdk_window_unref (event->any.window);
|
||||
event->any.window = GTK_WIDGET (window->GetMozArea())->window;
|
||||
gdk_window_ref (event->any.window);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle it ourselves.
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case GDK_KEY_PRESS:
|
||||
handle_key_press_event (NULL, &event->key, window);
|
||||
break;
|
||||
case GDK_KEY_RELEASE:
|
||||
handle_key_release_event (NULL, &event->key, window);
|
||||
break;
|
||||
default:
|
||||
window->HandleEvent (event);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_main_do_event (event);
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
void
|
||||
handle_xlib_shell_event(GdkSuperWin *superwin, XEvent *event, gpointer p)
|
||||
{
|
||||
nsWindow *window = (nsWindow *)p;
|
||||
switch(event->xany.type) {
|
||||
case ConfigureNotify:
|
||||
window->HandleXlibConfigureNotifyEvent(event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
void
|
||||
handle_xlib_bin_event(GdkSuperWin *superwin, XEvent *event, gpointer p)
|
||||
{
|
||||
nsWindow *window = (nsWindow *)p;
|
||||
|
||||
switch(event->xany.type) {
|
||||
case Expose:
|
||||
window->HandleXlibExposeEvent(event);
|
||||
break;
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
window->HandleXlibButtonEvent((XButtonEvent *)event);
|
||||
break;
|
||||
case MotionNotify:
|
||||
window->HandleXlibMotionNotifyEvent((XMotionEvent *) event);
|
||||
break;
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
window->HandleXlibCrossingEvent((XCrossingEvent *) event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
gint nsGtkWidget_FSBCancel_Callback(GtkWidget *w, gpointer p)
|
||||
{
|
||||
#if 0
|
||||
nsWindow *widgetWindow = (nsWindow*)gtk_object_get_user_data(GTK_OBJECT(w));
|
||||
nsFileWidget * widgetWindow = (nsFileWidget *) p ;
|
||||
if (p != nsnull) {
|
||||
widgetWindow->OnCancel();
|
||||
}
|
||||
#endif
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
gint nsGtkWidget_FSBOk_Callback(GtkWidget *w, gpointer p)
|
||||
{
|
||||
#if 0
|
||||
nsWindow *widgetWindow = (nsWindow*)gtk_object_get_user_data(GTK_OBJECT(w));
|
||||
nsFileWidget * widgetWindow = (nsFileWidget *) p;
|
||||
if (p != nsnull) {
|
||||
widgetWindow->OnOk();
|
||||
}
|
||||
#endif
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef __nsGtkEventHandler_h
|
||||
#define __nsGtkEventHandler_h
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include "gdksuperwin.h"
|
||||
|
||||
class nsIWidget;
|
||||
class nsIMenuItem;
|
||||
class nsIMenu;
|
||||
|
||||
gint handle_configure_event(GtkWidget *w, GdkEventConfigure *conf, gpointer p);
|
||||
void handle_size_allocate(GtkWidget *w, GtkAllocation *alloc, gpointer p);
|
||||
gint handle_expose_event(GtkWidget *w, GdkEventExpose *event, gpointer p);
|
||||
|
||||
|
||||
gint handle_key_release_event_for_text(GtkObject *w, GdkEventKey* event, gpointer p);
|
||||
gint handle_key_press_event_for_text(GtkObject *w, GdkEventKey* event, gpointer p);
|
||||
|
||||
gint handle_key_release_event(GtkObject *w, GdkEventKey* event, gpointer p);
|
||||
gint handle_key_press_event(GtkObject *w, GdkEventKey* event, gpointer p);
|
||||
|
||||
void handle_scrollbar_value_changed(GtkAdjustment *adjustment, gpointer p);
|
||||
|
||||
void menu_item_activate_handler(GtkWidget *w, gpointer p);
|
||||
|
||||
void menu_map_handler(GtkWidget *w, gpointer p);
|
||||
void menu_unmap_handler(GtkWidget *w, gpointer p);
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
gint nsGtkWidget_FSBCancel_Callback(GtkWidget *w, gpointer p);
|
||||
gint nsGtkWidget_FSBOk_Callback(GtkWidget *w, gpointer p);
|
||||
|
||||
//----------------------------------------------------
|
||||
gint CheckButton_Toggle_Callback(GtkWidget *w, gpointer p);
|
||||
|
||||
gint nsGtkWidget_RadioButton_ArmCallback(GtkWidget *w, gpointer p);
|
||||
gint nsGtkWidget_RadioButton_DisArmCallback(GtkWidget *w, gpointer p);
|
||||
|
||||
gint nsGtkWidget_Text_Callback(GtkWidget *w, GdkEventKey* event, gpointer p);
|
||||
gint nsGtkWidget_Expose_Callback(GtkWidget *w, gpointer p);
|
||||
|
||||
gint nsGtkWidget_Refresh_Callback(gpointer call_data);
|
||||
|
||||
void handle_xlib_shell_event(GdkSuperWin *superwin, XEvent *event, gpointer p);
|
||||
void handle_xlib_bin_event(GdkSuperWin *superwin, XEvent *event, gpointer p);
|
||||
void handle_gdk_event (GdkEvent *event, gpointer data);
|
||||
|
||||
#endif // __nsGtkEventHandler.h
|
||||
@@ -1,213 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nsGtkUtils.h"
|
||||
|
||||
#include <gdk/gdkx.h>
|
||||
#include <gdk/gdkprivate.h>
|
||||
|
||||
#if defined(__osf__) && !defined(_XOPEN_SOURCE_EXTENDED)
|
||||
/*
|
||||
** DEC's compiler requires _XOPEN_SOURCE_EXTENDED to be defined in
|
||||
** order for it to see the prototype for usleep in unistd.h, but if
|
||||
** we define that the build breaks long before getting here. So
|
||||
** put the prototype here explicitly.
|
||||
*/
|
||||
int usleep(useconds_t);
|
||||
#endif
|
||||
#if defined(__QNX__)
|
||||
#define usleep(s) sleep(s)
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
#if 0
|
||||
/* staitc */ gint
|
||||
nsGtkUtils::gdk_query_pointer(GdkWindow * window,
|
||||
gint * x_out,
|
||||
gint * y_out)
|
||||
{
|
||||
g_return_val_if_fail(NULL != window, FALSE);
|
||||
g_return_val_if_fail(NULL != x_out, FALSE);
|
||||
g_return_val_if_fail(NULL != y_out, FALSE);
|
||||
|
||||
Window root;
|
||||
Window child;
|
||||
int rootx, rooty;
|
||||
int winx = 0;
|
||||
int winy = 0;
|
||||
unsigned int xmask = 0;
|
||||
gint result = FALSE;
|
||||
|
||||
*x_out = -1;
|
||||
*y_out = -1;
|
||||
|
||||
result = XQueryPointer(GDK_WINDOW_XDISPLAY(window),
|
||||
GDK_WINDOW_XWINDOW(window),
|
||||
&root,
|
||||
&child,
|
||||
&rootx,
|
||||
&rooty,
|
||||
&winx,
|
||||
&winy,
|
||||
&xmask);
|
||||
|
||||
if (result)
|
||||
{
|
||||
*x_out = rootx;
|
||||
*y_out = rooty;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
//////////////////////////////////////////////////////////////////
|
||||
/* static */ void
|
||||
nsGtkUtils::gtk_widget_set_color(GtkWidget * widget,
|
||||
GtkRcFlags flags,
|
||||
GtkStateType state,
|
||||
GdkColor * color)
|
||||
{
|
||||
GtkRcStyle * rc_style;
|
||||
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (color != NULL);
|
||||
g_return_if_fail (flags == 0);
|
||||
|
||||
rc_style = (GtkRcStyle *) gtk_object_get_data (GTK_OBJECT (widget),
|
||||
"modify-style");
|
||||
|
||||
if (!rc_style)
|
||||
{
|
||||
rc_style = gtk_rc_style_new ();
|
||||
|
||||
gtk_widget_modify_style (widget, rc_style);
|
||||
|
||||
gtk_object_set_data (GTK_OBJECT (widget), "modify-style", rc_style);
|
||||
}
|
||||
|
||||
if (flags & GTK_RC_FG)
|
||||
{
|
||||
rc_style->color_flags[state] = GtkRcFlags(rc_style->color_flags[state] | GTK_RC_FG);
|
||||
rc_style->fg[state] = *color;
|
||||
}
|
||||
|
||||
if (flags & GTK_RC_BG)
|
||||
{
|
||||
rc_style->color_flags[state] = GtkRcFlags(rc_style->color_flags[state] | GTK_RC_BG);
|
||||
rc_style->bg[state] = *color;
|
||||
}
|
||||
|
||||
if (flags & GTK_RC_TEXT)
|
||||
{
|
||||
rc_style->color_flags[state] = GtkRcFlags(rc_style->color_flags[state] | GTK_RC_TEXT);
|
||||
rc_style->text[state] = *color;
|
||||
}
|
||||
|
||||
if (flags & GTK_RC_BASE)
|
||||
{
|
||||
rc_style->color_flags[state] = GtkRcFlags(rc_style->color_flags[state] | GTK_RC_BASE);
|
||||
rc_style->base[state] = *color;
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////
|
||||
/* static */ GdkModifierType
|
||||
nsGtkUtils::gdk_keyboard_get_modifiers()
|
||||
{
|
||||
GdkModifierType m = (GdkModifierType) 0;
|
||||
|
||||
gdk_window_get_pointer(NULL,NULL,NULL,&m);
|
||||
|
||||
return m;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////
|
||||
/* static */ void
|
||||
nsGtkUtils::gdk_window_flash(GdkWindow * aGdkWindow,
|
||||
unsigned int aTimes,
|
||||
unsigned long aInterval,
|
||||
GdkRectangle * aArea)
|
||||
{
|
||||
gint x;
|
||||
gint y;
|
||||
gint width;
|
||||
gint height;
|
||||
guint i;
|
||||
GdkGC * gc = 0;
|
||||
GdkColor white;
|
||||
|
||||
gdk_window_get_geometry(aGdkWindow,
|
||||
NULL,
|
||||
NULL,
|
||||
&width,
|
||||
&height,
|
||||
NULL);
|
||||
|
||||
gdk_window_get_origin (aGdkWindow,
|
||||
&x,
|
||||
&y);
|
||||
|
||||
gc = gdk_gc_new(GDK_ROOT_PARENT());
|
||||
|
||||
white.pixel = WhitePixel(gdk_display,DefaultScreen(gdk_display));
|
||||
|
||||
gdk_gc_set_foreground(gc,&white);
|
||||
gdk_gc_set_function(gc,GDK_XOR);
|
||||
gdk_gc_set_subwindow(gc,GDK_INCLUDE_INFERIORS);
|
||||
|
||||
/*
|
||||
* If an area is given, use that. Notice how out of whack coordinates
|
||||
* and dimentsions are not checked!!!
|
||||
*/
|
||||
if (aArea)
|
||||
{
|
||||
x += aArea->x;
|
||||
y += aArea->y;
|
||||
|
||||
width = aArea->width;
|
||||
height = aArea->height;
|
||||
}
|
||||
|
||||
/*
|
||||
* Need to do this twice so that the XOR effect can replace
|
||||
* the original window contents.
|
||||
*/
|
||||
for (i = 0; i < aTimes * 2; i++)
|
||||
{
|
||||
gdk_draw_rectangle(GDK_ROOT_PARENT(),
|
||||
gc,
|
||||
TRUE,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height);
|
||||
|
||||
gdk_flush();
|
||||
|
||||
usleep(aInterval);
|
||||
}
|
||||
|
||||
gdk_gc_destroy(gc);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////
|
||||
@@ -1,85 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef __nsGtkUtils_h
|
||||
#define __nsGtkUtils_h
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
struct nsGtkUtils
|
||||
{
|
||||
//
|
||||
// Wrapper for XQueryPointer
|
||||
//
|
||||
#if 0
|
||||
static gint gdk_query_pointer(GdkWindow * window,
|
||||
gint * x_out,
|
||||
gint * y_out);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Change a widget's background
|
||||
//
|
||||
// flags isa bit mask of the following bits:
|
||||
//
|
||||
// GTK_RC_FG
|
||||
// GTK_RC_BG
|
||||
// GTK_RC_TEXT
|
||||
// GTK_RC_BASE
|
||||
//
|
||||
// state is an enum:
|
||||
//
|
||||
// GTK_STATE_NORMAL,
|
||||
// GTK_STATE_ACTIVE,
|
||||
// GTK_STATE_PRELIGHT,
|
||||
// GTK_STATE_SELECTED,
|
||||
// GTK_STATE_INSENSITIVE
|
||||
//
|
||||
static void gtk_widget_set_color(GtkWidget * widget,
|
||||
GtkRcFlags flags,
|
||||
GtkStateType state,
|
||||
GdkColor * color);
|
||||
|
||||
/**
|
||||
* Return the current keyboard modifier state.
|
||||
*
|
||||
* @return the current keyboard modifier state.
|
||||
*
|
||||
*/
|
||||
static GdkModifierType gdk_keyboard_get_modifiers();
|
||||
|
||||
/**
|
||||
* Flash an area within a GDK window (or the whole window)
|
||||
*
|
||||
* @param aGdkWindow The GDK window to flash.
|
||||
* @param aTimes Number of times to flash the area.
|
||||
* @param aInterval Interval between flashes in milliseconds.
|
||||
* @param aArea The area to flash. The whole window if NULL.
|
||||
*
|
||||
*/
|
||||
static void gdk_window_flash(GdkWindow * aGdkWindow,
|
||||
unsigned int aTimes,
|
||||
unsigned long aInterval,
|
||||
GdkRectangle * aArea);
|
||||
};
|
||||
|
||||
#endif // __nsGtkEventHandler.h
|
||||
@@ -1,141 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "nsLabel.h"
|
||||
#include "nsString.h"
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsLabel, nsWidget)
|
||||
NS_IMPL_RELEASE_INHERITED(nsLabel, nsWidget)
|
||||
NS_IMPL_QUERY_INTERFACE2(nsLabel, nsILabel, nsIWidget)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsLabel constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsLabel::nsLabel() : nsWidget(), nsILabel()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mAlignment = eAlign_Left;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsLabel destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsLabel::~nsLabel()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the nativeLabel widget
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsLabel::CreateNative(GtkObject *parentWindow)
|
||||
{
|
||||
unsigned char alignment = GetNativeAlignment();
|
||||
|
||||
mWidget = gtk_label_new("");
|
||||
gtk_widget_set_name(mWidget, "nsLabel");
|
||||
gtk_misc_set_alignment(GTK_MISC(mWidget), 0.0, alignment);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsLabel::PreCreateWidget(nsWidgetInitData *aInitData)
|
||||
{
|
||||
if (nsnull != aInitData) {
|
||||
nsLabelInitData* data = (nsLabelInitData *) aInitData;
|
||||
mAlignment = data->mAlignment;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set alignment
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsLabel::SetAlignment(nsLabelAlignment aAlignment)
|
||||
{
|
||||
GtkJustification align;
|
||||
|
||||
mAlignment = aAlignment;
|
||||
|
||||
align = GetNativeAlignment();
|
||||
gtk_misc_set_alignment(GTK_MISC(mWidget), 0.0, align);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
GtkJustification nsLabel::GetNativeAlignment()
|
||||
{
|
||||
switch (mAlignment) {
|
||||
case eAlign_Right : return GTK_JUSTIFY_RIGHT;
|
||||
case eAlign_Left : return GTK_JUSTIFY_LEFT;
|
||||
case eAlign_Center: return GTK_JUSTIFY_CENTER;
|
||||
default :
|
||||
return GTK_JUSTIFY_LEFT;
|
||||
}
|
||||
return GTK_JUSTIFY_LEFT;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set this button label
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsLabel::SetLabel(const nsString& aText)
|
||||
{
|
||||
NS_ALLOC_STR_BUF(label, aText, 256);
|
||||
gtk_label_set(GTK_LABEL(mWidget), label);
|
||||
NS_FREE_STR_BUF(label);
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Get this button label
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsLabel::GetLabel(nsString& aBuffer)
|
||||
{
|
||||
char * text;
|
||||
gtk_label_get(GTK_LABEL(mWidget), &text);
|
||||
aBuffer.SetLength(0);
|
||||
aBuffer.Append(text);
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsLabel_h__
|
||||
#define nsLabel_h__
|
||||
|
||||
#include "nsWidget.h"
|
||||
#include "nsILabel.h"
|
||||
|
||||
/**
|
||||
* Native GTK+ Label wrapper
|
||||
*/
|
||||
class nsLabel : public nsWidget,
|
||||
public nsILabel
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
nsLabel();
|
||||
virtual ~nsLabel();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsILabel part
|
||||
NS_IMETHOD SetLabel(const nsString &aText);
|
||||
NS_IMETHOD GetLabel(nsString &aBuffer);
|
||||
NS_IMETHOD SetAlignment(nsLabelAlignment aAlignment);
|
||||
|
||||
NS_IMETHOD PreCreateWidget(nsWidgetInitData *aInitData);
|
||||
|
||||
virtual PRBool OnMove(PRInt32 aX, PRInt32 aY) { return PR_FALSE; }
|
||||
virtual PRBool OnResize(nsRect &aRect) { return PR_FALSE; }
|
||||
|
||||
|
||||
protected:
|
||||
NS_METHOD CreateNative(GtkObject *parentWindow);
|
||||
GtkJustification GetNativeAlignment();
|
||||
|
||||
nsLabelAlignment mAlignment;
|
||||
|
||||
};
|
||||
|
||||
#endif // nsLabel_h__
|
||||
@@ -1,394 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "nsListBox.h"
|
||||
#include "nsString.h"
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsListBox, nsWidget)
|
||||
NS_IMPL_RELEASE_INHERITED(nsListBox, nsWidget)
|
||||
NS_IMPL_QUERY_INTERFACE3(nsListBox, nsIListBox, nsIListWidget, nsIWidget)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsListBox constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsListBox::nsListBox() : nsWidget(), nsIListWidget(), nsIListBox()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mMultiSelect = PR_FALSE;
|
||||
mCList = nsnull;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsListBox:: destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsListBox::~nsListBox()
|
||||
{
|
||||
}
|
||||
|
||||
void nsListBox::InitCallbacks(char * aName)
|
||||
{
|
||||
InstallButtonPressSignal(mCList);
|
||||
InstallButtonReleaseSignal(mCList);
|
||||
|
||||
InstallEnterNotifySignal(mCList);
|
||||
InstallLeaveNotifySignal(mCList);
|
||||
|
||||
// These are needed so that the events will go to us and not our parent.
|
||||
AddToEventMask(mCList,
|
||||
GDK_BUTTON_PRESS_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_ENTER_NOTIFY_MASK |
|
||||
GDK_EXPOSURE_MASK |
|
||||
GDK_FOCUS_CHANGE_MASK |
|
||||
GDK_KEY_PRESS_MASK |
|
||||
GDK_KEY_RELEASE_MASK |
|
||||
GDK_LEAVE_NOTIFY_MASK |
|
||||
GDK_POINTER_MOTION_MASK);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// initializer
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP nsListBox::SetMultipleSelection(PRBool aMultipleSelections)
|
||||
{
|
||||
mMultiSelect = aMultipleSelections;
|
||||
if (mCList) {
|
||||
if (mMultiSelect)
|
||||
gtk_clist_set_selection_mode(GTK_CLIST(mCList), GTK_SELECTION_MULTIPLE);
|
||||
else
|
||||
gtk_clist_set_selection_mode(GTK_CLIST(mCList), GTK_SELECTION_BROWSE);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// AddItemAt
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP nsListBox::AddItemAt(nsString &aItem, PRInt32 aPosition)
|
||||
{
|
||||
if (mCList) {
|
||||
gchar *text[2];
|
||||
const nsAutoCString tempStr(aItem);
|
||||
text[0] = (gchar*)(const char *)tempStr;
|
||||
text[1] = (gchar*)NULL;
|
||||
gtk_clist_insert(GTK_CLIST(mCList), (int)aPosition, text);
|
||||
|
||||
// XXX Im not sure using the string address is the right thing to
|
||||
// store in the row data.
|
||||
gtk_clist_set_row_data(GTK_CLIST(mCList), aPosition, (gpointer)&aItem);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Finds an item at a postion
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRInt32 nsListBox::FindItem(nsString &aItem, PRInt32 aStartPos)
|
||||
{
|
||||
int i = -1;
|
||||
if (mCList) {
|
||||
i = gtk_clist_find_row_from_data(GTK_CLIST(mCList), (gpointer)&aItem);
|
||||
if (i < aStartPos) {
|
||||
i = -1;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// CountItems - Get Item Count
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRInt32 nsListBox::GetItemCount()
|
||||
{
|
||||
if (mCList) {
|
||||
return GTK_CLIST(mCList)->rows;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Removes an Item at a specified location
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool nsListBox::RemoveItemAt(PRInt32 aPosition)
|
||||
{
|
||||
if (mCList) {
|
||||
gtk_clist_remove(GTK_CLIST(mCList), aPosition);
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool nsListBox::GetItemAt(nsString& anItem, PRInt32 aPosition)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
anItem.Truncate();
|
||||
if (mCList) {
|
||||
char *text = nsnull;
|
||||
gtk_clist_get_text(GTK_CLIST(mCList),aPosition,0,&text);
|
||||
if (text) {
|
||||
anItem.Append(text);
|
||||
result = PR_TRUE;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Gets the selected of selected item
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsListBox::GetSelectedItem(nsString& aItem)
|
||||
{
|
||||
aItem.Truncate();
|
||||
if (mCList) {
|
||||
PRInt32 i=0, idx=-1;
|
||||
GtkCList *clist = GTK_CLIST(mCList);
|
||||
GList *list = clist->row_list;
|
||||
|
||||
for (i=0; i < clist->rows && idx == -1; i++, list = list->next) {
|
||||
if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED) {
|
||||
char *text = nsnull;
|
||||
gtk_clist_get_text(GTK_CLIST(mCList),i,0,&text);
|
||||
if (text) {
|
||||
aItem.Append(text);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Gets the list of selected otems
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRInt32 nsListBox::GetSelectedIndex()
|
||||
{
|
||||
PRInt32 i=0, idx=-1;
|
||||
if (mCList) {
|
||||
if (!mMultiSelect) {
|
||||
GtkCList *clist = GTK_CLIST(mCList);
|
||||
GList *list = clist->row_list;
|
||||
|
||||
for (i=0; i < clist->rows && idx == -1; i++, list = list->next) {
|
||||
if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED) {
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
NS_ASSERTION(PR_FALSE, "Multi selection list box does not support GetSelectedIndex()");
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// SelectItem
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsListBox::SelectItem(PRInt32 aPosition)
|
||||
{
|
||||
if (mCList) {
|
||||
gtk_clist_select_row(GTK_CLIST(mCList), aPosition, 0);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// GetSelectedCount
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
PRInt32 nsListBox::GetSelectedCount()
|
||||
{
|
||||
if (mCList) {
|
||||
if (!GTK_CLIST(mCList)->selection)
|
||||
return 0;
|
||||
else
|
||||
return (PRInt32)g_list_length(GTK_CLIST(mCList)->selection);
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// GetSelectedIndices
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsListBox::GetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize)
|
||||
{
|
||||
if (mCList) {
|
||||
PRInt32 i=0, num = 0;
|
||||
GtkCList *clist = GTK_CLIST(mCList);
|
||||
GList *list = clist->row_list;
|
||||
|
||||
for (i=0; i < clist->rows && num < aSize; i++, list = list->next) {
|
||||
if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED) {
|
||||
aIndices[num] = i;
|
||||
num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
PRInt32 i = 0;
|
||||
for (i = 0; i < aSize; i++) aIndices[i] = 0;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// SetSelectedIndices
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsListBox::SetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize)
|
||||
{
|
||||
if (mCList) {
|
||||
gtk_clist_unselect_all(GTK_CLIST(mCList));
|
||||
int i;
|
||||
for (i=0;i<aSize;i++) {
|
||||
SelectItem(aIndices[i]);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Deselect
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsListBox::Deselect()
|
||||
{
|
||||
if (mCList) {
|
||||
gtk_clist_unselect_all(GTK_CLIST(mCList));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Set initial parameters
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsListBox::PreCreateWidget(nsWidgetInitData *aInitData)
|
||||
{
|
||||
if (nsnull != aInitData) {
|
||||
nsListBoxInitData* data = (nsListBoxInitData *) aInitData;
|
||||
mMultiSelect = data->mMultiSelect;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the native widget
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsListBox::CreateNative(GtkObject *parentWindow)
|
||||
{
|
||||
// to handle scrolling
|
||||
mWidget = gtk_scrolled_window_new (nsnull, nsnull);
|
||||
gtk_widget_set_name(mWidget, "nsListBox");
|
||||
gtk_container_set_border_width(GTK_CONTAINER(mWidget), 0);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (mWidget),
|
||||
GTK_POLICY_NEVER,
|
||||
GTK_POLICY_AUTOMATIC);
|
||||
|
||||
mCList = ::gtk_clist_new(1);
|
||||
gtk_clist_column_titles_hide(GTK_CLIST(mCList));
|
||||
// Default (it may be changed)
|
||||
gtk_clist_set_selection_mode(GTK_CLIST(mCList), GTK_SELECTION_BROWSE);
|
||||
SetMultipleSelection(mMultiSelect);
|
||||
gtk_widget_show(mCList);
|
||||
gtk_signal_connect(GTK_OBJECT(mCList),
|
||||
"destroy",
|
||||
GTK_SIGNAL_FUNC(DestroySignal),
|
||||
this);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (mWidget), mCList);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsListBox::OnDestroySignal(GtkWidget* aGtkWidget)
|
||||
{
|
||||
if (aGtkWidget == mCList) {
|
||||
mCList = nsnull;
|
||||
}
|
||||
else {
|
||||
nsWidget::OnDestroySignal(aGtkWidget);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// set font for listbox
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
/*virtual*/
|
||||
void nsListBox::SetFontNative(GdkFont *aFont)
|
||||
{
|
||||
GtkStyle *style = gtk_style_copy(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0))->style);
|
||||
// gtk_style_copy ups the ref count of the font
|
||||
gdk_font_unref (style->font);
|
||||
|
||||
style->font = aFont;
|
||||
gdk_font_ref(style->font);
|
||||
|
||||
gtk_widget_set_style(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0)), style);
|
||||
|
||||
gtk_style_unref(style);
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsListBox_h__
|
||||
#define nsListBox_h__
|
||||
|
||||
#include "nsWidget.h"
|
||||
#include "nsIListBox.h"
|
||||
|
||||
/**
|
||||
* Native GTK+ Listbox wrapper
|
||||
*/
|
||||
class nsListBox : public nsWidget,
|
||||
public nsIListWidget,
|
||||
public nsIListBox
|
||||
{
|
||||
|
||||
public:
|
||||
nsListBox();
|
||||
virtual ~nsListBox();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIListBox interface
|
||||
NS_IMETHOD PreCreateWidget(nsWidgetInitData *aInitData);
|
||||
NS_IMETHOD SetMultipleSelection(PRBool aMultipleSelections);
|
||||
NS_IMETHOD AddItemAt(nsString &aItem, PRInt32 aPosition);
|
||||
PRInt32 FindItem(nsString &aItem, PRInt32 aStartPos);
|
||||
PRInt32 GetItemCount();
|
||||
PRBool RemoveItemAt(PRInt32 aPosition);
|
||||
PRBool GetItemAt(nsString& anItem, PRInt32 aPosition);
|
||||
NS_IMETHOD GetSelectedItem(nsString& aItem);
|
||||
PRInt32 GetSelectedIndex();
|
||||
PRInt32 GetSelectedCount();
|
||||
NS_IMETHOD GetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize);
|
||||
NS_IMETHOD SetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize);
|
||||
NS_IMETHOD SelectItem(PRInt32 aPosition);
|
||||
NS_IMETHOD Deselect() ;
|
||||
|
||||
virtual void SetFontNative(GdkFont *aFont);
|
||||
|
||||
protected:
|
||||
NS_IMETHOD CreateNative(GtkObject *parentWindow);
|
||||
virtual void InitCallbacks(char * aName = nsnull);
|
||||
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
|
||||
|
||||
GtkWidget *mCList;
|
||||
PRBool mMultiSelect;
|
||||
};
|
||||
|
||||
#endif // nsListBox_h__
|
||||
@@ -1,316 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsLookAndFeel.h"
|
||||
#include <gtk/gtkinvisible.h>
|
||||
|
||||
#define GDK_COLOR_TO_NS_RGB(c) \
|
||||
((nscolor) NS_RGB(c.red, c.green, c.blue))
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsLookAndFeel, nsILookAndFeel)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Query interface implementation
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsLookAndFeel::nsLookAndFeel()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mWidget = gtk_invisible_new();
|
||||
gtk_widget_ensure_style(mWidget);
|
||||
mStyle = gtk_widget_get_style(mWidget);
|
||||
}
|
||||
|
||||
nsLookAndFeel::~nsLookAndFeel()
|
||||
{
|
||||
gtk_widget_destroy(mWidget);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLookAndFeel::GetColor(const nsColorID aID, nscolor &aColor)
|
||||
{
|
||||
nsresult res = NS_OK;
|
||||
aColor = 0; // default color black
|
||||
|
||||
switch (aID) {
|
||||
case eColor_WindowBackground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_WindowForeground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_WidgetBackground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_WidgetForeground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_WidgetSelectBackground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_SELECTED]);
|
||||
break;
|
||||
case eColor_WidgetSelectForeground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_SELECTED]);
|
||||
break;
|
||||
case eColor_Widget3DHighlight:
|
||||
aColor = NS_RGB(0xa0,0xa0,0xa0);
|
||||
break;
|
||||
case eColor_Widget3DShadow:
|
||||
aColor = NS_RGB(0x40,0x40,0x40);
|
||||
break;
|
||||
case eColor_TextBackground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_TextForeground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_TextSelectBackground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_SELECTED]);
|
||||
break;
|
||||
case eColor_TextSelectForeground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->text[GTK_STATE_SELECTED]);
|
||||
break;
|
||||
|
||||
// css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
|
||||
case eColor_activeborder:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_activecaption:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_appworkspace:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_background:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
|
||||
case eColor_captiontext:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_graytext:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_INSENSITIVE]);
|
||||
break;
|
||||
case eColor_highlight:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_SELECTED]);
|
||||
break;
|
||||
case eColor_highlighttext:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_SELECTED]);
|
||||
break;
|
||||
case eColor_inactiveborder:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_inactivecaption:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_INSENSITIVE]);
|
||||
break;
|
||||
case eColor_inactivecaptiontext:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_INSENSITIVE]);
|
||||
break;
|
||||
case eColor_infobackground:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_infotext:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_menu:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_menutext:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
case eColor_scrollbar:
|
||||
break;
|
||||
|
||||
case eColor_threedface:
|
||||
case eColor_buttonface:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
|
||||
case eColor_buttonhighlight: // ?
|
||||
case eColor_threedhighlight:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_ACTIVE]);
|
||||
break;
|
||||
|
||||
case eColor_buttontext:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
|
||||
case eColor_buttonshadow:
|
||||
case eColor_threeddarkshadow:
|
||||
case eColor_threedshadow: // i think these should be the same
|
||||
aColor = NS_DarkenColor(NS_DarkenColor(NS_DarkenColor(NS_DarkenColor(NS_DarkenColor(GDK_COLOR_TO_NS_RGB(mStyle->light[GTK_STATE_NORMAL]))))));
|
||||
// aColor = GDK_COLOR_TO_NS_RGB(mStyle->dark[GTK_STATE_NORMAL]); // dark style gives me bright green?!
|
||||
break;
|
||||
|
||||
case eColor_threedlightshadow:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->light[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
|
||||
case eColor_window:
|
||||
case eColor_windowframe:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
|
||||
case eColor_windowtext:
|
||||
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* default color is BLACK */
|
||||
aColor = 0;
|
||||
res = NS_ERROR_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
// printf("%i, %i, %i\n", NS_GET_R(aColor), NS_GET_B(aColor), NS_GET_G(aColor));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
|
||||
{
|
||||
nsresult res = NS_OK;
|
||||
switch (aID) {
|
||||
case eMetric_WindowTitleHeight:
|
||||
aMetric = 0;
|
||||
break;
|
||||
case eMetric_WindowBorderWidth:
|
||||
// aMetric = mStyle->klass->xthickness;
|
||||
break;
|
||||
case eMetric_WindowBorderHeight:
|
||||
// aMetric = mStyle->klass->ythickness;
|
||||
break;
|
||||
case eMetric_Widget3DBorder:
|
||||
// aMetric = 4;
|
||||
break;
|
||||
case eMetric_TextFieldHeight:
|
||||
{
|
||||
GtkRequisition req;
|
||||
GtkWidget *text = gtk_entry_new();
|
||||
// needed to avoid memory leak
|
||||
gtk_widget_ref(text);
|
||||
gtk_object_sink(GTK_OBJECT(text));
|
||||
gtk_widget_size_request(text,&req);
|
||||
aMetric = req.height;
|
||||
gtk_widget_destroy(text);
|
||||
gtk_widget_unref(text);
|
||||
}
|
||||
break;
|
||||
case eMetric_TextFieldBorder:
|
||||
aMetric = 2;
|
||||
break;
|
||||
case eMetric_TextVerticalInsidePadding:
|
||||
aMetric = 0;
|
||||
break;
|
||||
case eMetric_TextShouldUseVerticalInsidePadding:
|
||||
aMetric = 0;
|
||||
break;
|
||||
case eMetric_TextHorizontalInsideMinimumPadding:
|
||||
aMetric = 15;
|
||||
break;
|
||||
case eMetric_TextShouldUseHorizontalInsideMinimumPadding:
|
||||
aMetric = 1;
|
||||
break;
|
||||
case eMetric_ButtonHorizontalInsidePaddingNavQuirks:
|
||||
aMetric = 10;
|
||||
break;
|
||||
case eMetric_ButtonHorizontalInsidePaddingOffsetNavQuirks:
|
||||
aMetric = 8;
|
||||
break;
|
||||
case eMetric_CheckboxSize:
|
||||
aMetric = 15;
|
||||
break;
|
||||
case eMetric_RadioboxSize:
|
||||
aMetric = 15;
|
||||
break;
|
||||
case eMetric_ListShouldUseHorizontalInsideMinimumPadding:
|
||||
aMetric = 15;
|
||||
break;
|
||||
case eMetric_ListHorizontalInsideMinimumPadding:
|
||||
aMetric = 15;
|
||||
break;
|
||||
case eMetric_ListShouldUseVerticalInsidePadding:
|
||||
aMetric = 1;
|
||||
break;
|
||||
case eMetric_ListVerticalInsidePadding:
|
||||
aMetric = 1;
|
||||
break;
|
||||
case eMetric_CaretBlinkTime:
|
||||
aMetric = 500;
|
||||
break;
|
||||
case eMetric_CaretWidthTwips:
|
||||
aMetric = 20;
|
||||
break;
|
||||
default:
|
||||
aMetric = 0;
|
||||
res = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricFloatID aID, float & aMetric)
|
||||
{
|
||||
nsresult res = NS_OK;
|
||||
switch (aID) {
|
||||
case eMetricFloat_TextFieldVerticalInsidePadding:
|
||||
aMetric = 0.25f;
|
||||
break;
|
||||
case eMetricFloat_TextFieldHorizontalInsidePadding:
|
||||
aMetric = 0.95f; // large number on purpose so minimum padding is used
|
||||
break;
|
||||
case eMetricFloat_TextAreaVerticalInsidePadding:
|
||||
aMetric = 0.40f;
|
||||
break;
|
||||
case eMetricFloat_TextAreaHorizontalInsidePadding:
|
||||
aMetric = 0.40f; // large number on purpose so minimum padding is used
|
||||
break;
|
||||
case eMetricFloat_ListVerticalInsidePadding:
|
||||
aMetric = 0.10f;
|
||||
break;
|
||||
case eMetricFloat_ListHorizontalInsidePadding:
|
||||
aMetric = 0.40f;
|
||||
break;
|
||||
case eMetricFloat_ButtonVerticalInsidePadding:
|
||||
aMetric = 0.25f;
|
||||
break;
|
||||
case eMetricFloat_ButtonHorizontalInsidePadding:
|
||||
aMetric = 0.25f;
|
||||
break;
|
||||
default:
|
||||
aMetric = -1.0;
|
||||
res = NS_ERROR_FAILURE;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
NS_IMETHODIMP nsLookAndFeel::GetNavSize(const nsMetricNavWidgetID aWidgetID,
|
||||
const nsMetricNavFontID aFontID,
|
||||
const PRInt32 aFontSize,
|
||||
nsSize &aSize)
|
||||
{
|
||||
aSize.width = 0;
|
||||
aSize.height = 0;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
#endif
|
||||
@@ -1,55 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef __nsLookAndFeel
|
||||
#define __nsLookAndFeel
|
||||
#include "nsILookAndFeel.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
class nsLookAndFeel: public nsILookAndFeel {
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
public:
|
||||
nsLookAndFeel();
|
||||
virtual ~nsLookAndFeel();
|
||||
|
||||
NS_IMETHOD GetColor(const nsColorID aID, nscolor &aColor);
|
||||
NS_IMETHOD GetMetric(const nsMetricID aID, PRInt32 & aMetric);
|
||||
NS_IMETHOD GetMetric(const nsMetricFloatID aID, float & aMetric);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
// This method returns the actual (or nearest estimate)
|
||||
// of the Navigator size for a given form control for a given font
|
||||
// and font size. This is used in NavQuirks mode to see how closely
|
||||
// we match its size
|
||||
NS_IMETHOD GetNavSize(const nsMetricNavWidgetID aWidgetID,
|
||||
const nsMetricNavFontID aFontID,
|
||||
const PRInt32 aFontSize,
|
||||
nsSize &aSize);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
GtkStyle *mStyle;
|
||||
GtkWidget *mWidget;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,792 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "nsMenu.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIMenuBar.h"
|
||||
#include "nsIMenuItem.h"
|
||||
#include "nsIMenuListener.h"
|
||||
#include "nsString.h"
|
||||
#include "nsGtkEventHandler.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
|
||||
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
|
||||
static NS_DEFINE_CID(kMenuItemCID, NS_MENUITEM_CID);
|
||||
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
|
||||
nsresult nsMenu::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
*aInstancePtr = NULL;
|
||||
|
||||
if (aIID.Equals(nsIMenu::GetIID())) {
|
||||
*aInstancePtr = (void*)(nsIMenu*) this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kISupportsIID)) {
|
||||
*aInstancePtr = (void*)(nsISupports*)(nsIMenu*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(nsIMenuListener::GetIID())) {
|
||||
*aInstancePtr = (void*)(nsIMenuListener*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(nsMenu)
|
||||
NS_IMPL_RELEASE(nsMenu)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsMenu constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsMenu::nsMenu() : nsIMenu()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mNumMenuItems = 0;
|
||||
mMenu = nsnull;
|
||||
mMenuParent = nsnull;
|
||||
mMenuBarParent = nsnull;
|
||||
mListener = nsnull;
|
||||
mConstructCalled = PR_FALSE;
|
||||
|
||||
mDOMNode = nsnull;
|
||||
mWebShell = nsnull;
|
||||
mDOMElement = nsnull;
|
||||
mAccessKey = "_";
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsMenu destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsMenu::~nsMenu()
|
||||
{
|
||||
//g_print("nsMenu::~nsMenu() called\n");
|
||||
NS_IF_RELEASE(mListener);
|
||||
// Free our menu items
|
||||
RemoveAll();
|
||||
gtk_widget_destroy(mMenu);
|
||||
mMenu = nsnull;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the proper widget
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::Create(nsISupports *aParent, const nsString &aLabel)
|
||||
{
|
||||
if(aParent)
|
||||
{
|
||||
nsIMenuBar * menubar = nsnull;
|
||||
aParent->QueryInterface(nsIMenuBar::GetIID(), (void**) &menubar);
|
||||
if(menubar)
|
||||
{
|
||||
mMenuBarParent = menubar;
|
||||
NS_RELEASE(menubar);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsIMenu * menu = nsnull;
|
||||
aParent->QueryInterface(nsIMenu::GetIID(), (void**) &menu);
|
||||
if(menu)
|
||||
{
|
||||
mMenuParent = menu;
|
||||
NS_RELEASE(menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mLabel = aLabel;
|
||||
mMenu = gtk_menu_new();
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (mMenu), "map",
|
||||
GTK_SIGNAL_FUNC(menu_map_handler),
|
||||
this);
|
||||
gtk_signal_connect (GTK_OBJECT (mMenu), "unmap",
|
||||
GTK_SIGNAL_FUNC(menu_unmap_handler),
|
||||
this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::GetParent(nsISupports*& aParent)
|
||||
{
|
||||
aParent = nsnull;
|
||||
if (nsnull != mMenuParent) {
|
||||
return mMenuParent->QueryInterface(kISupportsIID,
|
||||
(void**)&aParent);
|
||||
} else if (nsnull != mMenuBarParent) {
|
||||
return mMenuBarParent->QueryInterface(kISupportsIID,
|
||||
(void**)&aParent);
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::GetLabel(nsString &aText)
|
||||
{
|
||||
aText = mLabel;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::SetLabel(const nsString &aText)
|
||||
{
|
||||
/* we Do GetLabel() when we are adding the menu...
|
||||
* but we might want to redo this.
|
||||
*/
|
||||
mLabel = aText;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::GetAccessKey(nsString &aText)
|
||||
{
|
||||
aText = mAccessKey;
|
||||
char *foo = mAccessKey.ToNewCString();
|
||||
|
||||
#ifdef DEBUG_pavlov
|
||||
g_print("GetAccessKey returns \"%s\"\n", foo);
|
||||
#endif
|
||||
|
||||
nsCRT::free(foo);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::SetAccessKey(const nsString &aText)
|
||||
{
|
||||
mAccessKey = aText;
|
||||
char *foo = mAccessKey.ToNewCString();
|
||||
|
||||
#ifdef DEBUG_pavlov
|
||||
g_print("SetAccessKey setting to \"%s\"\n", foo);
|
||||
#endif
|
||||
|
||||
nsCRT::free(foo);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/**
|
||||
* Set enabled state
|
||||
*
|
||||
*/
|
||||
NS_METHOD nsMenu::SetEnabled(PRBool aIsEnabled)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/**
|
||||
* Get enabled state
|
||||
*
|
||||
*/
|
||||
NS_METHOD nsMenu::GetEnabled(PRBool* aIsEnabled)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/**
|
||||
* Query if this is the help menu
|
||||
*
|
||||
*/
|
||||
NS_METHOD nsMenu::IsHelpMenu(PRBool* aIsHelpMenu)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::AddItem(nsISupports * aItem)
|
||||
{
|
||||
if(aItem)
|
||||
{
|
||||
nsIMenuItem * menuitem = nsnull;
|
||||
aItem->QueryInterface(nsIMenuItem::GetIID(),
|
||||
(void**)&menuitem);
|
||||
if(menuitem)
|
||||
{
|
||||
AddMenuItem(menuitem); // nsMenu now owns this
|
||||
NS_RELEASE(menuitem);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsIMenu * menu = nsnull;
|
||||
aItem->QueryInterface(nsIMenu::GetIID(),
|
||||
(void**)&menu);
|
||||
if(menu)
|
||||
{
|
||||
AddMenu(menu); // nsMenu now owns this
|
||||
NS_RELEASE(menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// local method used by nsMenu::AddItem
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::AddMenuItem(nsIMenuItem * aMenuItem)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
void *voidData;
|
||||
|
||||
aMenuItem->GetNativeData(voidData);
|
||||
widget = GTK_WIDGET(voidData);
|
||||
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
|
||||
|
||||
// XXX add aMenuItem to internal data structor list
|
||||
// Need to be adding an nsISupports *, not nsIMenuItem *
|
||||
nsISupports * supports = nsnull;
|
||||
aMenuItem->QueryInterface(kISupportsIID,
|
||||
(void**)&supports);
|
||||
{
|
||||
mMenuItemVoidArray.AppendElement(supports);
|
||||
mNumMenuItems++;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// local method used by nsMenu::AddItem
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::AddMenu(nsIMenu * aMenu)
|
||||
{
|
||||
nsString Label;
|
||||
GtkWidget *newmenu=nsnull;
|
||||
void *voidData=NULL;
|
||||
|
||||
aMenu->GetLabel(Label);
|
||||
|
||||
// Create nsMenuItem
|
||||
nsIMenuItem * pnsMenuItem = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(kMenuItemCID,
|
||||
nsnull,
|
||||
nsIMenuItem::GetIID(),
|
||||
(void**)&pnsMenuItem);
|
||||
if (NS_OK == rv) {
|
||||
nsISupports * supports = nsnull;
|
||||
QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pnsMenuItem->Create(supports, Label, PR_FALSE); //PR_TRUE);
|
||||
NS_RELEASE(supports);
|
||||
|
||||
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
AddItem(supports); // Parent should now own menu item
|
||||
NS_RELEASE(supports);
|
||||
|
||||
void * menuitem = nsnull;
|
||||
pnsMenuItem->GetNativeData(menuitem);
|
||||
|
||||
voidData = NULL;
|
||||
aMenu->GetNativeData(&voidData);
|
||||
newmenu = GTK_WIDGET(voidData);
|
||||
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), newmenu);
|
||||
|
||||
NS_RELEASE(pnsMenuItem);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::AddSeparator()
|
||||
{
|
||||
// Create nsMenuItem
|
||||
nsIMenuItem * pnsMenuItem = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(
|
||||
kMenuItemCID, nsnull, nsIMenuItem::GetIID(), (void**)&pnsMenuItem);
|
||||
if (NS_OK == rv) {
|
||||
nsString tmp = "menuseparator";
|
||||
nsISupports * supports = nsnull;
|
||||
QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pnsMenuItem->Create(supports, tmp, PR_TRUE);
|
||||
NS_RELEASE(supports);
|
||||
|
||||
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
AddItem(supports); // Parent should now own menu item
|
||||
NS_RELEASE(supports);
|
||||
|
||||
NS_RELEASE(pnsMenuItem);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::GetItemCount(PRUint32 &aCount)
|
||||
{
|
||||
// this should be right.. does it need to be +1 ?
|
||||
aCount = g_list_length(GTK_MENU_SHELL(mMenu)->children);
|
||||
//g_print("nsMenu::GetItemCount = %i\n", aCount);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::GetItemAt(const PRUint32 aPos,
|
||||
nsISupports *&aMenuItem)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::InsertItemAt(const PRUint32 aPos,
|
||||
nsISupports *aMenuItem)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::RemoveItem(const PRUint32 aPos)
|
||||
{
|
||||
#if 0
|
||||
// this may work here better than Removeall(), but i'm not sure how to test this one
|
||||
nsISupports *item = mMenuItemVoidArray[aPos];
|
||||
delete item;
|
||||
mMenuItemVoidArray.RemoveElementAt(aPos);
|
||||
#endif
|
||||
/*
|
||||
gtk_menu_shell_remove (GTK_MENU_SHELL (mMenu), item);
|
||||
|
||||
nsCRT::free(labelStr);
|
||||
|
||||
voidData = NULL;
|
||||
|
||||
aMenu->GetNativeData(&voidData);
|
||||
newmenu = GTK_WIDGET(voidData);
|
||||
|
||||
gtk_menu_item_remove_submenu (GTK_MENU_ITEM (item));
|
||||
*/
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::RemoveAll()
|
||||
{
|
||||
//g_print("nsMenu::RemoveAll()\n");
|
||||
#if 0
|
||||
// this doesn't work quite right, but this is about all that should really be needed
|
||||
int i=0;
|
||||
nsIMenu *menu = nsnull;
|
||||
nsIMenuItem *menuitem = nsnull;
|
||||
nsISupports *item = nsnull;
|
||||
|
||||
for (i=mMenuItemVoidArray.Count(); i>0; i--)
|
||||
{
|
||||
item = (nsISupports*)mMenuItemVoidArray[i-1];
|
||||
|
||||
if(nsnull != item)
|
||||
{
|
||||
if (NS_OK == item->QueryInterface(nsIMenuItem::GetIID(), (void**)&menuitem)) {
|
||||
// we do this twice because we have to do it once for QueryInterface,
|
||||
// then we want to get rid of it.
|
||||
// g_print("remove nsMenuItem\n");
|
||||
NS_RELEASE(menuitem);
|
||||
NS_RELEASE(item);
|
||||
menuitem = nsnull;
|
||||
} else if (NS_OK == item->QueryInterface(nsIMenu::GetIID(), (void**)&menu)) {
|
||||
// g_print("remove nsMenu\n");
|
||||
NS_RELEASE(menu);
|
||||
NS_RELEASE(item);
|
||||
menu = nsnull;
|
||||
}
|
||||
// mMenuItemVoidArray.RemoveElementAt(i-1);
|
||||
}
|
||||
}
|
||||
mMenuItemVoidArray.Clear();
|
||||
#else
|
||||
for (int i = mMenuItemVoidArray.Count(); i > 0; i--) {
|
||||
if(nsnull != mMenuItemVoidArray[i-1]) {
|
||||
nsIMenuItem * menuitem = nsnull;
|
||||
((nsISupports*)mMenuItemVoidArray[i-1])->QueryInterface(nsIMenuItem::GetIID(),
|
||||
(void**)&menuitem);
|
||||
if(menuitem) {
|
||||
void *gtkmenuitem = nsnull;
|
||||
menuitem->GetNativeData(gtkmenuitem);
|
||||
if (gtkmenuitem) {
|
||||
// gtk_widget_ref(GTK_WIDGET(gtkmenuitem));
|
||||
//gtk_widget_destroy(GTK_WIDGET(gtkmenuitem));
|
||||
gtk_container_remove (GTK_CONTAINER (mMenu), GTK_WIDGET(gtkmenuitem));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
nsIMenu * menu= nsnull;
|
||||
((nsISupports*)mMenuItemVoidArray[i-1])->QueryInterface(nsIMenu::GetIID(),
|
||||
(void**)&menu);
|
||||
if(menu)
|
||||
{
|
||||
void * gtkmenu = nsnull;
|
||||
menu->GetNativeData(>kmenu);
|
||||
|
||||
if(gtkmenu){
|
||||
//g_print("gtkmenu removed");
|
||||
|
||||
//gtk_menu_item_remove_submenu (GTK_MENU_ITEM (item));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//g_print("end RemoveAll\n");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::GetNativeData(void ** aData)
|
||||
{
|
||||
*aData = (void *)mMenu;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::SetNativeData(void * aData)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
GtkWidget *nsMenu::GetNativeParent()
|
||||
{
|
||||
void * voidData;
|
||||
if (nsnull != mMenuParent) {
|
||||
mMenuParent->GetNativeData(&voidData);
|
||||
} else if (nsnull != mMenuBarParent) {
|
||||
mMenuBarParent->GetNativeData(voidData);
|
||||
} else {
|
||||
return nsnull;
|
||||
}
|
||||
return GTK_WIDGET(voidData);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::AddMenuListener(nsIMenuListener * aMenuListener)
|
||||
{
|
||||
mListener = aMenuListener;
|
||||
NS_ADDREF(mListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenu::RemoveMenuListener(nsIMenuListener * aMenuListener)
|
||||
{
|
||||
if (aMenuListener == mListener) {
|
||||
NS_IF_RELEASE(mListener);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// nsIMenuListener interface
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenu::MenuItemSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
if (nsnull != mListener) {
|
||||
mListener->MenuSelected(aMenuEvent);
|
||||
}
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
nsEventStatus nsMenu::MenuSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
if (nsnull != mListener) {
|
||||
mListener->MenuSelected(aMenuEvent);
|
||||
}
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenu::MenuDeselected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
if (nsnull != mListener) {
|
||||
mListener->MenuDeselected(aMenuEvent);
|
||||
}
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenu::MenuConstruct(const nsMenuEvent & aMenuEvent,
|
||||
nsIWidget * aParentWindow,
|
||||
void * menuNode,
|
||||
void * aWebShell)
|
||||
{
|
||||
//g_print("nsMenu::MenuConstruct called \n");
|
||||
if(menuNode){
|
||||
SetDOMNode((nsIDOMNode*)menuNode);
|
||||
}
|
||||
|
||||
if(!aWebShell){
|
||||
aWebShell = mWebShell;
|
||||
}
|
||||
|
||||
// First open the menu.
|
||||
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
|
||||
if (domElement)
|
||||
domElement->SetAttribute("open", "true");
|
||||
|
||||
/// Now get the kids. Retrieve our menupopup child.
|
||||
nsCOMPtr<nsIDOMNode> menuPopupNode;
|
||||
mDOMNode->GetFirstChild(getter_AddRefs(menuPopupNode));
|
||||
while (menuPopupNode) {
|
||||
nsCOMPtr<nsIDOMElement> menuPopupElement(do_QueryInterface(menuPopupNode));
|
||||
if (menuPopupElement) {
|
||||
nsString menuPopupNodeType;
|
||||
menuPopupElement->GetNodeName(menuPopupNodeType);
|
||||
if (menuPopupNodeType.Equals("menupopup"))
|
||||
break;
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> oldMenuPopupNode(menuPopupNode);
|
||||
oldMenuPopupNode->GetNextSibling(getter_AddRefs(menuPopupNode));
|
||||
}
|
||||
|
||||
if (!menuPopupNode)
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> menuitemNode;
|
||||
menuPopupNode->GetFirstChild(getter_AddRefs(menuitemNode));
|
||||
|
||||
unsigned short menuIndex = 0;
|
||||
|
||||
while (menuitemNode) {
|
||||
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
|
||||
if (menuitemElement) {
|
||||
nsString menuitemNodeType;
|
||||
nsString menuitemName;
|
||||
menuitemElement->GetNodeName(menuitemNodeType);
|
||||
if (menuitemNodeType.Equals("menuitem")) {
|
||||
// LoadMenuItem
|
||||
LoadMenuItem(this,
|
||||
menuitemElement,
|
||||
menuitemNode,
|
||||
menuIndex,
|
||||
(nsIWebShell*)aWebShell);
|
||||
} else if (menuitemNodeType.Equals("menuseparator")) {
|
||||
AddSeparator();
|
||||
} else if (menuitemNodeType.Equals("menu")) {
|
||||
// Load a submenu
|
||||
LoadSubMenu(this, menuitemElement, menuitemNode);
|
||||
}
|
||||
}
|
||||
|
||||
++menuIndex;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
|
||||
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
|
||||
} // end menu item innner loop
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenu::MenuDestruct(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
// Close the node.
|
||||
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
|
||||
if (domElement)
|
||||
domElement->RemoveAttribute("open");
|
||||
|
||||
//g_print("nsMenu::MenuDestruct called \n");
|
||||
mConstructCalled = PR_FALSE;
|
||||
RemoveAll();
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/**
|
||||
* Set DOMNode
|
||||
*
|
||||
*/
|
||||
NS_METHOD nsMenu::SetDOMNode(nsIDOMNode * aMenuNode)
|
||||
{
|
||||
mDOMNode = aMenuNode;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/**
|
||||
* Set DOMElement
|
||||
*
|
||||
*/
|
||||
NS_METHOD nsMenu::SetDOMElement(nsIDOMElement * aMenuElement)
|
||||
{
|
||||
mDOMElement = aMenuElement;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/**
|
||||
* Set WebShell
|
||||
*
|
||||
*/
|
||||
NS_METHOD nsMenu::SetWebShell(nsIWebShell * aWebShell)
|
||||
{
|
||||
mWebShell = aWebShell;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
void nsMenu::LoadMenuItem(nsIMenu * pParentMenu,
|
||||
nsIDOMElement * menuitemElement,
|
||||
nsIDOMNode * menuitemNode,
|
||||
unsigned short menuitemIndex,
|
||||
nsIWebShell * aWebShell)
|
||||
{
|
||||
static const char* NS_STRING_TRUE = "true";
|
||||
nsString disabled;
|
||||
nsString menuitemName;
|
||||
nsString menuitemCmd;
|
||||
|
||||
menuitemElement->GetAttribute(nsAutoString("disabled"), disabled);
|
||||
menuitemElement->GetAttribute(nsAutoString("value"), menuitemName);
|
||||
menuitemElement->GetAttribute(nsAutoString("cmd"), menuitemCmd);
|
||||
|
||||
// Create nsMenuItem
|
||||
nsIMenuItem * pnsMenuItem = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(kMenuItemCID,
|
||||
nsnull,
|
||||
nsIMenuItem::GetIID(),
|
||||
(void**)&pnsMenuItem);
|
||||
if (NS_OK == rv) {
|
||||
pnsMenuItem->Create(pParentMenu, menuitemName, PR_FALSE);
|
||||
|
||||
nsISupports * supports = nsnull;
|
||||
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pParentMenu->AddItem(supports); // Parent should now own menu item
|
||||
NS_RELEASE(supports);
|
||||
|
||||
if(disabled == NS_STRING_TRUE ) {
|
||||
pnsMenuItem->SetEnabled(PR_FALSE);
|
||||
}
|
||||
|
||||
// Create MenuDelegate - this is the intermediator inbetween
|
||||
// the DOM node and the nsIMenuItem
|
||||
// The nsWebShellWindow wacthes for Document changes and then notifies the
|
||||
// the appropriate nsMenuDelegate object
|
||||
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(menuitemNode));
|
||||
if (!domElement) {
|
||||
//return NS_ERROR_FAILURE;
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString cmdAtom("oncommand");
|
||||
nsString cmdName;
|
||||
|
||||
domElement->GetAttribute(cmdAtom, cmdName);
|
||||
|
||||
pnsMenuItem->SetCommand(cmdName);
|
||||
// DO NOT use passed in webshell because of messed up windows dynamic loading
|
||||
// code.
|
||||
pnsMenuItem->SetWebShell(mWebShell);
|
||||
pnsMenuItem->SetDOMElement(domElement);
|
||||
|
||||
NS_RELEASE(pnsMenuItem);
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
void nsMenu::LoadSubMenu(nsIMenu * pParentMenu,
|
||||
nsIDOMElement * menuElement,
|
||||
nsIDOMNode * menuNode)
|
||||
{
|
||||
nsString menuName;
|
||||
menuElement->GetAttribute(nsAutoString("value"), menuName);
|
||||
//printf("Creating Menu [%s] \n", menuName.ToNewCString()); // this leaks
|
||||
|
||||
// Create nsMenu
|
||||
nsIMenu * pnsMenu = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(kMenuCID,
|
||||
nsnull,
|
||||
nsIMenu::GetIID(),
|
||||
(void**)&pnsMenu);
|
||||
if (NS_OK == rv) {
|
||||
// Call Create
|
||||
nsISupports * supports = nsnull;
|
||||
pParentMenu->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pnsMenu->Create(supports, menuName);
|
||||
NS_RELEASE(supports); // Balance QI
|
||||
|
||||
// Set nsMenu Name
|
||||
pnsMenu->SetLabel(menuName);
|
||||
|
||||
supports = nsnull;
|
||||
pnsMenu->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pParentMenu->AddItem(supports); // parent takes ownership
|
||||
NS_RELEASE(supports);
|
||||
|
||||
pnsMenu->SetWebShell(mWebShell);
|
||||
pnsMenu->SetDOMNode(menuNode);
|
||||
|
||||
/*
|
||||
// Begin menuitem inner loop
|
||||
unsigned short menuIndex = 0;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> menuitemNode;
|
||||
menuNode->GetFirstChild(getter_AddRefs(menuitemNode));
|
||||
while (menuitemNode) {
|
||||
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
|
||||
if (menuitemElement) {
|
||||
nsString menuitemNodeType;
|
||||
menuitemElement->GetNodeName(menuitemNodeType);
|
||||
|
||||
#ifdef DEBUG_saari
|
||||
printf("Type [%s] %d\n", menuitemNodeType.ToNewCString(), menuitemNodeType.Equals("menuseparator"));
|
||||
#endif
|
||||
|
||||
if (menuitemNodeType.Equals("menuitem")) {
|
||||
// Load a menuitem
|
||||
LoadMenuItem(pnsMenu, menuitemElement, menuitemNode, menuIndex, mWebShell);
|
||||
} else if (menuitemNodeType.Equals("menuseparator")) {
|
||||
pnsMenu->AddSeparator();
|
||||
} else if (menuitemNodeType.Equals("menu")) {
|
||||
// Add a submenu
|
||||
LoadSubMenu(pnsMenu, menuitemElement, menuitemNode);
|
||||
}
|
||||
}
|
||||
++menuIndex;
|
||||
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
|
||||
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
|
||||
} // end menu item innner loop
|
||||
*/
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsMenu_h__
|
||||
#define nsMenu_h__
|
||||
|
||||
#include "nsIMenu.h"
|
||||
#include "nsIMenuListener.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
class nsIDOMElement;
|
||||
class nsIDOMNode;
|
||||
class nsIMenuBar;
|
||||
class nsIWebShell;
|
||||
|
||||
/**
|
||||
* Native GTK+ Menu wrapper
|
||||
*/
|
||||
|
||||
class nsMenu : public nsIMenu, public nsIMenuListener
|
||||
{
|
||||
|
||||
public:
|
||||
nsMenu();
|
||||
virtual ~nsMenu();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIMenuListener methods
|
||||
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuConstruct(
|
||||
const nsMenuEvent & aMenuEvent,
|
||||
nsIWidget * aParentWindow,
|
||||
void * menuNode,
|
||||
void * aWebShell);
|
||||
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
|
||||
|
||||
NS_IMETHOD Create(nsISupports * aParent, const nsString &aLabel);
|
||||
|
||||
// nsIMenu Methods
|
||||
NS_IMETHOD GetParent(nsISupports *&aParent);
|
||||
NS_IMETHOD GetLabel(nsString &aText);
|
||||
NS_IMETHOD SetLabel(const nsString &aText);
|
||||
NS_IMETHOD GetAccessKey(nsString &aText);
|
||||
NS_IMETHOD SetAccessKey(const nsString &aText);
|
||||
NS_IMETHOD AddItem(nsISupports * aItem);
|
||||
NS_IMETHOD AddMenuItem(nsIMenuItem * aMenuItem);
|
||||
NS_IMETHOD AddMenu(nsIMenu * aMenu);
|
||||
NS_IMETHOD AddSeparator();
|
||||
NS_IMETHOD GetItemCount(PRUint32 &aCount);
|
||||
NS_IMETHOD GetItemAt(const PRUint32 aPos, nsISupports *& aMenuItem);
|
||||
NS_IMETHOD InsertItemAt(const PRUint32 aPos, nsISupports * aMenuItem);
|
||||
NS_IMETHOD RemoveItem(const PRUint32 aPos);
|
||||
NS_IMETHOD RemoveAll();
|
||||
NS_IMETHOD GetNativeData(void** aData);
|
||||
NS_IMETHOD SetNativeData(void* aData);
|
||||
NS_IMETHOD AddMenuListener(nsIMenuListener * aMenuListener);
|
||||
NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener);
|
||||
NS_IMETHOD SetEnabled(PRBool aIsEnabled);
|
||||
NS_IMETHOD GetEnabled(PRBool* aIsEnabled);
|
||||
NS_IMETHOD IsHelpMenu(PRBool* aIsHelp);
|
||||
|
||||
NS_IMETHOD SetDOMNode(nsIDOMNode * aMenuNode);
|
||||
NS_IMETHOD SetDOMElement(nsIDOMElement * aMenuElement);
|
||||
NS_IMETHOD SetWebShell(nsIWebShell * aWebShell);
|
||||
|
||||
protected:
|
||||
void LoadMenuItem(
|
||||
nsIMenu * pParentMenu,
|
||||
nsIDOMElement * menuitemElement,
|
||||
nsIDOMNode * menuitemNode,
|
||||
unsigned short menuitemIndex,
|
||||
nsIWebShell * aWebShell);
|
||||
|
||||
void LoadSubMenu(
|
||||
nsIMenu * pParentMenu,
|
||||
nsIDOMElement * menuElement,
|
||||
nsIDOMNode * menuNode);
|
||||
|
||||
GtkWidget *GetNativeParent();
|
||||
|
||||
nsString mLabel;
|
||||
nsString mAccessKey;
|
||||
PRUint32 mNumMenuItems;
|
||||
GtkWidget *mMenu;
|
||||
|
||||
nsVoidArray mMenuItemVoidArray;
|
||||
|
||||
nsIMenu *mMenuParent;
|
||||
nsIMenuBar *mMenuBarParent;
|
||||
nsIMenuListener * mListener;
|
||||
|
||||
PRBool mConstructCalled;
|
||||
nsIDOMNode * mDOMNode;
|
||||
nsIWebShell * mWebShell;
|
||||
nsIDOMElement * mDOMElement;
|
||||
};
|
||||
|
||||
#endif // nsMenu_h__
|
||||
@@ -1,354 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "nsMenuBar.h"
|
||||
#include "nsMenuItem.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIMenu.h"
|
||||
#include "nsIWebShell.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
#include "nsGtkEventHandler.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
|
||||
static NS_DEFINE_CID(kMenuBarCID, NS_MENUBAR_CID);
|
||||
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
|
||||
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
|
||||
nsresult nsMenuBar::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
*aInstancePtr = NULL;
|
||||
|
||||
if (aIID.Equals(nsIMenuBar::GetIID())) {
|
||||
*aInstancePtr = (void*) ((nsIMenuBar*) this);
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aIID.Equals(kISupportsIID)) {
|
||||
*aInstancePtr = (void*) ((nsISupports*)(nsIMenuBar*) this);
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aIID.Equals(nsIMenuListener::GetIID())) {
|
||||
*aInstancePtr = (void*) ((nsIMenuListener*)this);
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(nsMenuBar)
|
||||
NS_IMPL_RELEASE(nsMenuBar)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsMenuBar constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsMenuBar::nsMenuBar() : nsIMenuBar(), nsIMenuListener()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mNumMenus = 0;
|
||||
mMenuBar = nsnull;
|
||||
mParent = nsnull;
|
||||
mIsMenuBarAdded = PR_FALSE;
|
||||
mWebShell = nsnull;
|
||||
mDOMNode = nsnull;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsMenuBar destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsMenuBar::~nsMenuBar()
|
||||
{
|
||||
// Release the menus
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the proper widget
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::Create(nsIWidget *aParent)
|
||||
{
|
||||
SetParent(aParent);
|
||||
mMenuBar = gtk_menu_bar_new();
|
||||
|
||||
gtk_widget_show(mMenuBar);
|
||||
mParent->SetMenuBar(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::GetParent(nsIWidget *&aParent)
|
||||
{
|
||||
aParent = mParent;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::SetParent(nsIWidget *aParent)
|
||||
{
|
||||
mParent = aParent;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::AddMenu(nsIMenu * aMenu)
|
||||
{
|
||||
nsString Label;
|
||||
GtkWidget *widget, *nmenu;
|
||||
void *voidData;
|
||||
|
||||
nsISupports * supports = nsnull;
|
||||
aMenu->QueryInterface(kISupportsIID, (void**)&supports);
|
||||
if (supports) {
|
||||
mMenusVoidArray.AppendElement(aMenu);
|
||||
mNumMenus++;
|
||||
}
|
||||
|
||||
aMenu->GetLabel(Label);
|
||||
|
||||
// get access key
|
||||
nsString accessKey = " ";
|
||||
aMenu->GetAccessKey(accessKey);
|
||||
if(accessKey != " ")
|
||||
{
|
||||
// munge acess key into name
|
||||
PRInt32 offset = Label.Find(accessKey);
|
||||
if(offset != -1)
|
||||
Label.Insert("_", offset);
|
||||
}
|
||||
|
||||
char *foo = Label.ToNewCString();
|
||||
g_print("%s\n", foo);
|
||||
nsCRT::free(foo);
|
||||
|
||||
widget = nsMenuItem::CreateLocalized(Label);
|
||||
gtk_widget_show(widget);
|
||||
gtk_menu_bar_append (GTK_MENU_BAR (mMenuBar), widget);
|
||||
|
||||
aMenu->GetNativeData(&voidData);
|
||||
nmenu = GTK_WIDGET(voidData);
|
||||
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), nmenu);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::GetMenuCount(PRUint32 &aCount)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::GetMenuAt(const PRUint32 aCount, nsIMenu *& aMenu)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::InsertMenuAt(const PRUint32 aCount, nsIMenu *& aMenu)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::RemoveMenu(const PRUint32 aCount)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::RemoveAll()
|
||||
{
|
||||
for (int i = mMenusVoidArray.Count(); i > 0; i--) {
|
||||
if(nsnull != mMenusVoidArray[i-1]) {
|
||||
nsIMenu * menu = nsnull;
|
||||
((nsISupports*)mMenusVoidArray[i-1])->QueryInterface(nsIMenu::GetIID(), (void**)&menu);
|
||||
if(menu) {
|
||||
//void * gtkmenu= nsnull;
|
||||
//menu->GetNativeData(>kmenu);
|
||||
//if(gtkmenu){
|
||||
// gtk_container_remove (GTK_CONTAINER (mMenuBar), GTK_WIDGET(gtkmenu) );
|
||||
//}
|
||||
NS_RELEASE(menu);
|
||||
|
||||
g_print("menu release \n");
|
||||
int num =((nsISupports*)mMenusVoidArray[i-1])->Release();
|
||||
while(num) {
|
||||
g_print("menu release again!\n");
|
||||
num = ((nsISupports*)mMenusVoidArray[i-1])->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::GetNativeData(void *& aData)
|
||||
{
|
||||
aData = (void *)mMenuBar;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::SetNativeData(void * aData)
|
||||
{
|
||||
// Temporary hack for MacOS. Will go away when nsMenuBar handles it's own
|
||||
// construction
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::Paint()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsMenuListener interface
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenuBar::MenuItemSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
nsEventStatus nsMenuBar::MenuSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
nsEventStatus nsMenuBar::MenuDeselected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
nsEventStatus nsMenuBar::MenuConstruct(
|
||||
const nsMenuEvent & aMenuEvent,
|
||||
nsIWidget * aParentWindow,
|
||||
void * menubarNode,
|
||||
void * aWebShell)
|
||||
{
|
||||
mWebShell = (nsIWebShell*) aWebShell;
|
||||
mDOMNode = (nsIDOMNode*)menubarNode;
|
||||
|
||||
nsIMenuBar * pnsMenuBar = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(kMenuBarCID,
|
||||
nsnull,
|
||||
nsIMenuBar::GetIID(),
|
||||
(void**)&pnsMenuBar);
|
||||
if (NS_OK == rv) {
|
||||
if (nsnull != pnsMenuBar) {
|
||||
pnsMenuBar->Create(aParentWindow);
|
||||
|
||||
// set pnsMenuBar as a nsMenuListener on aParentWindow
|
||||
nsCOMPtr<nsIMenuListener> menuListener;
|
||||
pnsMenuBar->QueryInterface(nsIMenuListener::GetIID(), getter_AddRefs(menuListener));
|
||||
aParentWindow->AddMenuListener(menuListener);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> menuNode;
|
||||
((nsIDOMNode*)menubarNode)->GetFirstChild(getter_AddRefs(menuNode));
|
||||
while (menuNode) {
|
||||
nsCOMPtr<nsIDOMElement> menuElement(do_QueryInterface(menuNode));
|
||||
if (menuElement) {
|
||||
nsString menuNodeType;
|
||||
nsString menuName;
|
||||
nsString menuAccessKey = " ";
|
||||
menuElement->GetNodeName(menuNodeType);
|
||||
if (menuNodeType.Equals("menu")) {
|
||||
menuElement->GetAttribute(nsAutoString("value"), menuName);
|
||||
menuElement->GetAttribute(nsAutoString("accesskey"), menuAccessKey);
|
||||
// Don't create the menu yet, just add in the top level names
|
||||
|
||||
// Create nsMenu
|
||||
nsIMenu * pnsMenu = nsnull;
|
||||
rv = nsComponentManager::CreateInstance(kMenuCID, nsnull, nsIMenu::GetIID(), (void**)&pnsMenu);
|
||||
if (NS_OK == rv) {
|
||||
// Call Create
|
||||
nsISupports * supports = nsnull;
|
||||
pnsMenuBar->QueryInterface(kISupportsIID, (void**) &supports);
|
||||
pnsMenu->Create(supports, menuName);
|
||||
NS_RELEASE(supports);
|
||||
|
||||
pnsMenu->SetLabel(menuName);
|
||||
pnsMenu->SetAccessKey(menuAccessKey);
|
||||
pnsMenu->SetDOMNode(menuNode);
|
||||
pnsMenu->SetDOMElement(menuElement);
|
||||
pnsMenu->SetWebShell(mWebShell);
|
||||
|
||||
// Make nsMenu a child of nsMenuBar
|
||||
// nsMenuBar takes ownership of the nsMenu
|
||||
pnsMenuBar->AddMenu(pnsMenu);
|
||||
|
||||
// Release the menu now that the menubar owns it
|
||||
NS_RELEASE(pnsMenu);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> oldmenuNode(menuNode);
|
||||
oldmenuNode->GetNextSibling(getter_AddRefs(menuNode));
|
||||
} // end while (nsnull != menuNode)
|
||||
|
||||
// Give the aParentWindow this nsMenuBar to hold onto.
|
||||
// The parent window should take ownership at this point
|
||||
aParentWindow->SetMenuBar(pnsMenuBar);
|
||||
|
||||
// HACK: force a paint for now
|
||||
pnsMenuBar->Paint();
|
||||
|
||||
NS_RELEASE(pnsMenuBar);
|
||||
} // end if ( nsnull != pnsMenuBar )
|
||||
}
|
||||
|
||||
return nsEventStatus_eIgnore;
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
nsEventStatus nsMenuBar::MenuDestruct(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsMenuBar_h__
|
||||
#define nsMenuBar_h__
|
||||
|
||||
#include "nsIMenuBar.h"
|
||||
#include "nsIMenuListener.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
class nsIDOMNode;
|
||||
class nsIWebShell;
|
||||
class nsIWidget;
|
||||
|
||||
/**
|
||||
* Native GTK+ MenuBar wrapper
|
||||
*/
|
||||
|
||||
class nsMenuBar : public nsIMenuBar, public nsIMenuListener
|
||||
{
|
||||
|
||||
public:
|
||||
nsMenuBar();
|
||||
virtual ~nsMenuBar();
|
||||
|
||||
// nsIMenuListener interface
|
||||
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuConstruct(
|
||||
const nsMenuEvent & aMenuEvent,
|
||||
nsIWidget * aParentWindow,
|
||||
void * menuNode,
|
||||
void * aWebShell);
|
||||
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
|
||||
NS_IMETHOD Create(nsIWidget * aParent);
|
||||
|
||||
// nsIMenuBar Methods
|
||||
NS_IMETHOD GetParent(nsIWidget *&aParent);
|
||||
NS_IMETHOD SetParent(nsIWidget * aParent);
|
||||
NS_IMETHOD AddMenu(nsIMenu * aMenu);
|
||||
NS_IMETHOD GetMenuCount(PRUint32 &aCount);
|
||||
NS_IMETHOD GetMenuAt(const PRUint32 aCount, nsIMenu *& aMenu);
|
||||
NS_IMETHOD InsertMenuAt(const PRUint32 aCount, nsIMenu *& aMenu);
|
||||
NS_IMETHOD RemoveMenu(const PRUint32 aCount);
|
||||
NS_IMETHOD RemoveAll();
|
||||
NS_IMETHOD GetNativeData(void*& aData);
|
||||
NS_IMETHOD Paint();
|
||||
NS_IMETHOD SetNativeData(void* aData);
|
||||
protected:
|
||||
GtkWidget * mMenuBar;
|
||||
nsIWidget * mParent;
|
||||
PRBool mIsMenuBarAdded;
|
||||
|
||||
nsIWebShell * mWebShell;
|
||||
nsIDOMNode * mDOMNode;
|
||||
|
||||
nsVoidArray mMenusVoidArray;
|
||||
PRUint32 mNumMenus;
|
||||
};
|
||||
|
||||
#endif // nsMenuBar_h__
|
||||
@@ -1,539 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "nsMenuItem.h"
|
||||
#include "nsIMenu.h"
|
||||
#include "nsIMenuBar.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
#include "nsGtkEventHandler.h"
|
||||
|
||||
#include "nsIPopUpMenu.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDocumentViewer.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsIWebShell.h"
|
||||
#include "nsICharsetConverterManager.h"
|
||||
#include "nsIPlatformCharset.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
|
||||
nsresult nsMenuItem::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
*aInstancePtr = NULL;
|
||||
|
||||
if (aIID.Equals(nsIMenuItem::GetIID())) {
|
||||
*aInstancePtr = (void*)(nsIMenuItem*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kISupportsIID)) {
|
||||
*aInstancePtr = (void*)(nsISupports*)(nsIMenuItem*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(nsIMenuListener::GetIID())) {
|
||||
*aInstancePtr = (void*)(nsIMenuListener*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(nsMenuItem)
|
||||
NS_IMPL_RELEASE(nsMenuItem)
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsMenuItem constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsMenuItem::nsMenuItem() : nsIMenuItem()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mMenuItem = nsnull;
|
||||
mMenuParent = nsnull;
|
||||
mPopUpParent = nsnull;
|
||||
mTarget = nsnull;
|
||||
mXULCommandListener = nsnull;
|
||||
mIsSeparator = PR_FALSE;
|
||||
mWebShell = nsnull;
|
||||
mDOMElement = nsnull;
|
||||
mIsSubMenu = PR_FALSE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsMenuItem destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsMenuItem::~nsMenuItem()
|
||||
{
|
||||
//g_print("nsMenuItem::~nsMenuItem called\n");
|
||||
//NS_IF_RELEASE(mTarget);
|
||||
gtk_widget_destroy(mMenuItem);
|
||||
mMenuItem = nsnull;
|
||||
//g_print("end nsMenuItem::~nsMenuItem\n");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
GtkWidget *nsMenuItem::GetNativeParent()
|
||||
{
|
||||
void * voidData;
|
||||
if (nsnull != mMenuParent) {
|
||||
mMenuParent->GetNativeData(&voidData);
|
||||
} else if (nsnull != mPopUpParent) {
|
||||
mPopUpParent->GetNativeData(voidData);
|
||||
} else {
|
||||
return nsnull;
|
||||
}
|
||||
return GTK_WIDGET(voidData);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsIWidget * nsMenuItem::GetMenuBarParent(nsISupports * aParent)
|
||||
{
|
||||
nsIWidget * widget = nsnull; // MenuBar's Parent
|
||||
nsIMenu * menu = nsnull;
|
||||
nsIMenuBar * menuBar = nsnull;
|
||||
nsIPopUpMenu * popup = nsnull;
|
||||
nsISupports * parent = aParent;
|
||||
|
||||
while(1) {
|
||||
if (NS_OK == parent->QueryInterface(nsIMenu::GetIID(),(void**)&menu)) {
|
||||
NS_RELEASE(parent);
|
||||
if (NS_OK != menu->GetParent(parent)) {
|
||||
NS_RELEASE(menu);
|
||||
return nsnull;
|
||||
}
|
||||
NS_RELEASE(menu);
|
||||
|
||||
} else if (NS_OK == parent->QueryInterface(nsIPopUpMenu::GetIID(),(void**)&popup)) {
|
||||
if (NS_OK != popup->GetParent(widget)) {
|
||||
widget = nsnull;
|
||||
}
|
||||
NS_RELEASE(popup);
|
||||
NS_RELEASE(parent);
|
||||
return widget;
|
||||
|
||||
} else if (NS_OK == parent->QueryInterface(nsIMenuBar::GetIID(),(void**)&menuBar)) {
|
||||
if (NS_OK != menuBar->GetParent(widget)) {
|
||||
widget = nsnull;
|
||||
}
|
||||
NS_RELEASE(menuBar);
|
||||
NS_RELEASE(parent);
|
||||
return widget;
|
||||
} else {
|
||||
NS_RELEASE(parent);
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
nsMenuItem::CreateLocalized(const nsString& aLabel)
|
||||
{
|
||||
nsresult result;
|
||||
static nsIUnicodeEncoder* converter = nsnull;
|
||||
static int isLatin1 = 0;
|
||||
static int initialized = 0;
|
||||
if (!initialized) {
|
||||
initialized = 1;
|
||||
result = NS_ERROR_FAILURE;
|
||||
NS_WITH_SERVICE(nsIPlatformCharset, platform, NS_PLATFORMCHARSET_PROGID,
|
||||
&result);
|
||||
if (platform && NS_SUCCEEDED(result)) {
|
||||
nsAutoString charset("");
|
||||
result = platform->GetCharset(kPlatformCharsetSel_Menu, charset);
|
||||
if (NS_SUCCEEDED(result) && (charset.Length() > 0)) {
|
||||
if (!charset.Compare("iso-8859-1", PR_TRUE)) {
|
||||
isLatin1 = 1;
|
||||
}
|
||||
NS_WITH_SERVICE(nsICharsetConverterManager, manager,
|
||||
NS_CHARSETCONVERTERMANAGER_PROGID, &result);
|
||||
if (manager && NS_SUCCEEDED(result)) {
|
||||
result = manager->GetUnicodeEncoder(&charset, &converter);
|
||||
if (NS_FAILED(result) && converter) {
|
||||
NS_RELEASE(converter);
|
||||
converter = nsnull;
|
||||
}
|
||||
else if (converter) {
|
||||
result = converter->SetOutputErrorBehavior(
|
||||
nsIUnicodeEncoder::kOnError_Replace, nsnull, '?');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget* menuItem = nsnull;
|
||||
|
||||
if (converter) {
|
||||
char labelStr[128];
|
||||
labelStr[0] = 0;
|
||||
PRInt32 srcLen = aLabel.Length() + 1;
|
||||
PRInt32 destLen = sizeof(labelStr);
|
||||
result = converter->Convert(aLabel.GetUnicode(), &srcLen, labelStr,
|
||||
&destLen);
|
||||
if (labelStr[0] && NS_SUCCEEDED(result)) {
|
||||
menuItem = gtk_menu_item_new_with_label(labelStr);
|
||||
if (menuItem && (!isLatin1)) {
|
||||
GtkWidget* label = GTK_BIN(menuItem)->child;
|
||||
gtk_widget_ensure_style(label);
|
||||
GtkStyle* style = gtk_style_copy(label->style);
|
||||
gdk_font_unref(style->font);
|
||||
style->font = gdk_fontset_load("*");
|
||||
gtk_widget_set_style(label, style);
|
||||
gtk_style_unref(style);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
char labelStr[128];
|
||||
aLabel.ToCString(labelStr, sizeof(labelStr));
|
||||
menuItem = gtk_menu_item_new_with_label(labelStr);
|
||||
}
|
||||
|
||||
return menuItem;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::Create(nsISupports *aParent,
|
||||
const nsString &aLabel,
|
||||
PRBool aIsSeparator)
|
||||
|
||||
{
|
||||
if (nsnull == aParent) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if(aParent) {
|
||||
nsIMenu * menu;
|
||||
aParent->QueryInterface(nsIMenu::GetIID(), (void**) &menu);
|
||||
mMenuParent = menu;
|
||||
NS_RELEASE(menu);
|
||||
}
|
||||
|
||||
nsIWidget *widget = nsnull; // MenuBar's Parent
|
||||
nsISupports *sups;
|
||||
if (NS_OK == aParent->QueryInterface(kISupportsIID,(void**)&sups)) {
|
||||
widget = GetMenuBarParent(sups);
|
||||
// GetMenuBarParent will call release for us
|
||||
// NS_RELEASE(sups);
|
||||
mTarget = widget;
|
||||
}
|
||||
|
||||
mIsSeparator = aIsSeparator;
|
||||
mLabel = aLabel;
|
||||
|
||||
// create the native menu item
|
||||
|
||||
if(mIsSeparator) {
|
||||
mMenuItem = gtk_menu_item_new();
|
||||
} else {
|
||||
mMenuItem = CreateLocalized(aLabel);
|
||||
}
|
||||
|
||||
gtk_widget_show(mMenuItem);
|
||||
|
||||
gtk_signal_connect(GTK_OBJECT(mMenuItem), "activate",
|
||||
GTK_SIGNAL_FUNC(menu_item_activate_handler),
|
||||
this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetLabel(nsString &aText)
|
||||
{
|
||||
aText = mLabel;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::SetLabel(nsString &aText)
|
||||
{
|
||||
mLabel = aText;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::SetEnabled(PRBool aIsEnabled)
|
||||
{
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(mMenuItem), aIsEnabled);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetEnabled(PRBool *aIsEnabled)
|
||||
{
|
||||
*aIsEnabled = GTK_WIDGET_IS_SENSITIVE(mMenuItem);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::SetChecked(PRBool aIsEnabled)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetChecked(PRBool *aIsEnabled)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::SetCheckboxType(PRBool aIsCheckbox)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetCheckboxType(PRBool *aIsCheckbox)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetCommand(PRUint32 & aCommand)
|
||||
{
|
||||
aCommand = mCommand;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetTarget(nsIWidget *& aTarget)
|
||||
{
|
||||
aTarget = mTarget;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetNativeData(void *& aData)
|
||||
{
|
||||
aData = (void *)mMenuItem;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::AddMenuListener(nsIMenuListener * aMenuListener)
|
||||
{
|
||||
|
||||
NS_IF_RELEASE(mXULCommandListener);
|
||||
NS_IF_ADDREF(aMenuListener);
|
||||
mXULCommandListener = aMenuListener;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::RemoveMenuListener(nsIMenuListener * aMenuListener)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::IsSeparator(PRBool & aIsSep)
|
||||
{
|
||||
aIsSep = mIsSeparator;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// nsIMenuListener interface
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenuItem::MenuItemSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
if(!mIsSeparator) {
|
||||
//g_print("nsMenuItem::MenuItemSelected\n");
|
||||
DoCommand();
|
||||
}else{
|
||||
//g_print("nsMenuItem::MenuItemSelected is separator\n");
|
||||
}
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenuItem::MenuSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
if(mXULCommandListener)
|
||||
return mXULCommandListener->MenuSelected(aMenuEvent);
|
||||
|
||||
//g_print("nsMenuItem::MenuSelected\n");
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenuItem::MenuDeselected(const nsMenuEvent &aMenuEvent)
|
||||
{
|
||||
//g_print("nsMenuItem::MenuDeselected\n");
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenuItem::MenuConstruct(const nsMenuEvent &aMenuEvent,
|
||||
nsIWidget *aParentWindow,
|
||||
void *menuNode,
|
||||
void *aWebShell)
|
||||
{
|
||||
//g_print("nsMenuItem::MenuConstruct\n");
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenuItem::MenuDestruct(const nsMenuEvent &aMenuEvent)
|
||||
{
|
||||
//g_print("nsMenuItem::MenuDestruct\n");
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/**
|
||||
* Sets the JavaScript Command to be invoked when a "gui" event
|
||||
* occurs on a source widget
|
||||
* @param aStrCmd the JS command to be cached for later execution
|
||||
* @return NS_OK
|
||||
*/
|
||||
NS_METHOD nsMenuItem::SetCommand(const nsString &aStrCmd)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/**
|
||||
* Executes the "cached" JavaScript Command
|
||||
* @return NS_OK if the command was executed properly, otherwise an error code
|
||||
*/
|
||||
NS_METHOD nsMenuItem::DoCommand()
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
if(!mWebShell || !mDOMElement)
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIContentViewer> contentViewer;
|
||||
NS_ENSURE_SUCCESS(mWebShell->GetContentViewer(getter_AddRefs(contentViewer)),
|
||||
NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDocumentViewer> docViewer;
|
||||
docViewer = do_QueryInterface(contentViewer);
|
||||
if (!docViewer) {
|
||||
NS_ERROR("Document viewer interface not supported by the content viewer.");
|
||||
//g_print("Document viewer interface not supported by the content viewer.");
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPresContext> presContext;
|
||||
if (NS_FAILED(rv = docViewer->GetPresContext(*getter_AddRefs(presContext)))) {
|
||||
NS_ERROR("Unable to retrieve the doc viewer's presentation context.");
|
||||
//g_print("Unable to retrieve the doc viewer's presentation context.");
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsMouseEvent event;
|
||||
event.eventStructType = NS_MOUSE_EVENT;
|
||||
event.message = NS_MENU_ACTION;
|
||||
|
||||
nsCOMPtr<nsIContent> contentNode;
|
||||
contentNode = do_QueryInterface(mDOMElement);
|
||||
if (!contentNode) {
|
||||
NS_ERROR("DOM Node doesn't support the nsIContent interface required to handle DOM events.");
|
||||
//g_print("DOM Node doesn't support the nsIContent interface required to handle DOM events.");
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = contentNode->HandleDOMEvent(*presContext, &event, nsnull, NS_EVENT_FLAG_INIT, status);
|
||||
//g_print("HandleDOMEvent called");
|
||||
return rv;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::SetDOMNode(nsIDOMNode * aDOMNode)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetDOMNode(nsIDOMNode ** aDOMNode)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::SetDOMElement(nsIDOMElement * aDOMElement)
|
||||
{
|
||||
mDOMElement = aDOMElement;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetDOMElement(nsIDOMElement ** aDOMElement)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::SetWebShell(nsIWebShell * aWebShell)
|
||||
{
|
||||
mWebShell = aWebShell;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsMenuItem::SetShortcutChar(const nsString &aText)
|
||||
{
|
||||
mKeyEquivalent = aText;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsMenuItem::GetShortcutChar(nsString &aText)
|
||||
{
|
||||
aText = mKeyEquivalent;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsMenuItem::SetModifiers(PRUint8 aModifiers)
|
||||
{
|
||||
mModifiers = aModifiers;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsMenuItem::GetModifiers(PRUint8 * aModifiers)
|
||||
{
|
||||
*aModifiers = mModifiers;
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsMenuItem_h__
|
||||
#define nsMenuItem_h__
|
||||
|
||||
#include "nsIMenuItem.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIMenuListener.h"
|
||||
|
||||
class nsIDOMNode;
|
||||
class nsIDOMElement;
|
||||
class nsIMenu;
|
||||
class nsIPopUpMenu;
|
||||
class nsIWebShell;
|
||||
class nsIWidget;
|
||||
|
||||
/**
|
||||
* Native GTK+ MenuItem wrapper
|
||||
*/
|
||||
|
||||
class nsMenuItem : public nsIMenuItem, public nsIMenuListener
|
||||
{
|
||||
|
||||
public:
|
||||
nsMenuItem();
|
||||
virtual ~nsMenuItem();
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIMenuItem Methods
|
||||
NS_IMETHOD Create(nsISupports *aParent,
|
||||
const nsString &aLabel,
|
||||
PRBool aIsSeparator);
|
||||
NS_IMETHOD GetLabel(nsString &aText);
|
||||
NS_IMETHOD SetLabel(nsString &aText);
|
||||
NS_IMETHOD SetEnabled(PRBool aIsEnabled);
|
||||
NS_IMETHOD GetEnabled(PRBool *aIsEnabled);
|
||||
NS_IMETHOD SetChecked(PRBool aIsEnabled);
|
||||
NS_IMETHOD GetChecked(PRBool *aIsEnabled);
|
||||
NS_IMETHOD SetCheckboxType(PRBool aIsCheckbox);
|
||||
NS_IMETHOD GetCheckboxType(PRBool *aIsCheckbox);
|
||||
NS_IMETHOD GetCommand(PRUint32 & aCommand);
|
||||
NS_IMETHOD GetTarget(nsIWidget *& aTarget);
|
||||
NS_IMETHOD GetNativeData(void*& aData);
|
||||
NS_IMETHOD AddMenuListener(nsIMenuListener * aMenuListener);
|
||||
NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener);
|
||||
NS_IMETHOD IsSeparator(PRBool & aIsSep);
|
||||
|
||||
NS_IMETHOD SetCommand(const nsString & aStrCmd);
|
||||
NS_IMETHOD DoCommand();
|
||||
NS_IMETHOD SetDOMNode(nsIDOMNode * aDOMNode);
|
||||
NS_IMETHOD GetDOMNode(nsIDOMNode ** aDOMNode);
|
||||
NS_IMETHOD SetDOMElement(nsIDOMElement * aDOMElement);
|
||||
NS_IMETHOD GetDOMElement(nsIDOMElement ** aDOMElement);
|
||||
NS_IMETHOD SetWebShell(nsIWebShell * aWebShell);
|
||||
|
||||
NS_IMETHOD SetShortcutChar(const nsString &aText);
|
||||
NS_IMETHOD GetShortcutChar(nsString &aText);
|
||||
NS_IMETHOD SetModifiers(PRUint8 aModifiers);
|
||||
NS_IMETHOD GetModifiers(PRUint8 * aModifiers);
|
||||
|
||||
// nsIMenuListener interface
|
||||
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
|
||||
nsEventStatus MenuConstruct(const nsMenuEvent & aMenuEvent,
|
||||
nsIWidget * aParentWindow,
|
||||
void * menuNode,
|
||||
void * aWebShell);
|
||||
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
|
||||
|
||||
static GtkWidget* CreateLocalized(const nsString& aLabel);
|
||||
|
||||
protected:
|
||||
nsIWidget *GetMenuBarParent(nsISupports * aParentSupports);
|
||||
GtkWidget *GetNativeParent();
|
||||
|
||||
nsIMenuListener *mXULCommandListener;
|
||||
nsString mLabel;
|
||||
nsString mKeyEquivalent;
|
||||
PRUint8 mModifiers;
|
||||
PRUint32 mCommand;
|
||||
nsIMenu *mMenuParent;
|
||||
nsIPopUpMenu *mPopUpParent;
|
||||
nsIWidget *mTarget;
|
||||
|
||||
GtkWidget *mMenuItem; // native cascade widget
|
||||
PRBool mIsSeparator;
|
||||
PRBool mIsSubMenu;
|
||||
|
||||
nsIWebShell * mWebShell;
|
||||
nsIDOMElement * mDOMElement;
|
||||
};
|
||||
|
||||
#endif // nsMenuItem_h__
|
||||
@@ -1,214 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
#include "nsPopUpMenu.h"
|
||||
#include "nsIMenu.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsFileSpec.h" // XXX: For nsAutoCString
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsPopUpMenu, nsIPopUpMenu::GetIID())
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsPopUpMenu constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsPopUpMenu::nsPopUpMenu() : nsIPopUpMenu()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mNumMenuItems = 0;
|
||||
mParent = nsnull;
|
||||
mMenu = nsnull;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsPopUpMenu destructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsPopUpMenu::~nsPopUpMenu()
|
||||
{
|
||||
NS_IF_RELEASE(mParent);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the proper widget
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::Create(nsIWidget *aParent)
|
||||
{
|
||||
|
||||
mParent = aParent;
|
||||
NS_ADDREF(mParent);
|
||||
|
||||
mMenu = gtk_menu_new();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::AddItem(const nsString &aText)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = gtk_menu_item_new_with_label ((const char*)nsAutoCString(mLabel));
|
||||
gtk_widget_show(widget);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::AddItem(nsIMenuItem * aMenuItem)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
void *voidData;
|
||||
|
||||
aMenuItem->GetNativeData(voidData);
|
||||
widget = GTK_WIDGET(voidData);
|
||||
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
|
||||
|
||||
// XXX add aMenuItem to internal data structor list
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::AddMenu(nsIMenu * aMenu)
|
||||
{
|
||||
nsString Label;
|
||||
GtkWidget *item=NULL, *parentmenu=NULL, *newmenu=NULL;
|
||||
void *voidData=NULL;
|
||||
|
||||
aMenu->GetLabel(Label);
|
||||
|
||||
GetNativeData(voidData);
|
||||
parentmenu = GTK_WIDGET(voidData);
|
||||
|
||||
item = gtk_menu_item_new_with_label ((const char*)nsAutoCString(Label));
|
||||
gtk_widget_show(item);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (parentmenu), item);
|
||||
|
||||
voidData = NULL;
|
||||
|
||||
aMenu->GetNativeData(&voidData);
|
||||
newmenu = GTK_WIDGET(voidData);
|
||||
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), newmenu);
|
||||
|
||||
// XXX add aMenu to internal data structor list
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::AddSeparator()
|
||||
{
|
||||
GtkWidget *widget;
|
||||
widget = gtk_menu_item_new ();
|
||||
gtk_widget_show(widget);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::GetItemCount(PRUint32 &aCount)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::GetItemAt(const PRUint32 aCount, nsIMenuItem *& aMenuItem)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::InsertItemAt(const PRUint32 aCount, nsIMenuItem *& aMenuItem)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::InsertItemAt(const PRUint32 aCount, const nsString & aMenuItemName)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::InsertSeparator(const PRUint32 aCount)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::RemoveItem(const PRUint32 aCount)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::RemoveAll()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void nsPopUpMenu::GetXY(GtkMenu *menu, gint *x, gint *y, gpointer user_data)
|
||||
{
|
||||
*x = ((nsPopUpMenu *)(user_data))->mX;
|
||||
*y = ((nsPopUpMenu *)(user_data))->mY;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::ShowMenu(PRInt32 aX, PRInt32 aY)
|
||||
{
|
||||
mX = aX;
|
||||
mY = aY;
|
||||
|
||||
gtk_menu_popup (GTK_MENU(mMenu),
|
||||
NULL,
|
||||
NULL,
|
||||
GetXY,
|
||||
this,
|
||||
0,
|
||||
GDK_CURRENT_TIME);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::GetNativeData(void *& aData)
|
||||
{
|
||||
aData = (void *)mMenu;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsPopUpMenu::GetParent(nsIWidget *& aParent)
|
||||
{
|
||||
aParent = mParent;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsPopUpMenu_h__
|
||||
#define nsPopUpMenu_h__
|
||||
|
||||
#include "nsIPopUpMenu.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
/**
|
||||
* Native GTK+ PopUp wrapper
|
||||
*/
|
||||
|
||||
class nsPopUpMenu : public nsIPopUpMenu
|
||||
{
|
||||
|
||||
public:
|
||||
nsPopUpMenu();
|
||||
virtual ~nsPopUpMenu();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD Create(nsIWidget * aParent);
|
||||
|
||||
// nsIPopUpMenu Methods
|
||||
NS_IMETHOD AddItem(const nsString &aText);
|
||||
NS_IMETHOD AddItem(nsIMenuItem * aMenuItem);
|
||||
NS_IMETHOD AddMenu(nsIMenu * aMenu);
|
||||
NS_IMETHOD AddSeparator();
|
||||
NS_IMETHOD GetItemCount(PRUint32 &aCount);
|
||||
NS_IMETHOD GetItemAt(const PRUint32 aCount, nsIMenuItem *& aMenuItem);
|
||||
NS_IMETHOD InsertItemAt(const PRUint32 aCount, nsIMenuItem *& aMenuItem);
|
||||
NS_IMETHOD InsertItemAt(const PRUint32 aCount, const nsString & aMenuItemName);
|
||||
NS_IMETHOD InsertSeparator(const PRUint32 aCount);
|
||||
NS_IMETHOD RemoveItem(const PRUint32 aCount);
|
||||
NS_IMETHOD RemoveAll();
|
||||
static void GetXY(GtkMenu *menu, gint *x, gint *y, gpointer user_data);
|
||||
NS_IMETHOD ShowMenu(PRInt32 aX, PRInt32 aY);
|
||||
NS_IMETHOD GetNativeData(void*& aData);
|
||||
NS_IMETHOD GetParent(nsIWidget*& aParent);
|
||||
|
||||
protected:
|
||||
|
||||
nsString mLabel;
|
||||
|
||||
PRUint32 mNumMenuItems;
|
||||
nsIWidget *mParent;
|
||||
GtkWidget *mMenu;
|
||||
|
||||
gint mX;
|
||||
gint mY;
|
||||
};
|
||||
|
||||
#endif // nsPopUpMenu_h__
|
||||
|
||||
@@ -1,240 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "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);
|
||||
}
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef 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__
|
||||
@@ -1,455 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "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;
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef 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__ */
|
||||
@@ -1,125 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
|
||||
#include "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;
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef __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
|
||||
|
||||
};
|
||||
|
||||
#endif /* __nsSound_h__ */
|
||||
@@ -1,97 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "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);
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsTextAreaWidget_h__
|
||||
#define nsTextAreaWidget_h__
|
||||
|
||||
#include "nsTextHelper.h"
|
||||
#include "nsITextAreaWidget.h"
|
||||
|
||||
/**
|
||||
* Native GTK+ multi-line edit control wrapper.
|
||||
*/
|
||||
|
||||
class nsTextAreaWidget : public nsTextHelper
|
||||
{
|
||||
|
||||
public:
|
||||
nsTextAreaWidget();
|
||||
virtual ~nsTextAreaWidget();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
virtual void SetFontNative(GdkFont *aFont);
|
||||
|
||||
protected:
|
||||
NS_METHOD CreateNative(GtkObject *parentWindow);
|
||||
};
|
||||
|
||||
|
||||
#endif // nsTextAreaWidget_h__
|
||||
@@ -1,216 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "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;
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
#ifndef 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__
|
||||
@@ -1,130 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "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;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsTextWidget_h__
|
||||
#define nsTextWidget_h__
|
||||
|
||||
#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);
|
||||
};
|
||||
|
||||
#endif // nsTextWidget_h__
|
||||
@@ -1,144 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef TOOLKIT_H
|
||||
#define TOOLKIT_H
|
||||
|
||||
#include "nsIToolkit.h"
|
||||
#include <gtk/gtk.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
|
||||
{
|
||||
|
||||
public:
|
||||
nsToolkit();
|
||||
virtual ~nsToolkit();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD Init(PRThread *aThread);
|
||||
|
||||
void CreateSharedGC(void);
|
||||
GdkGC *GetSharedGC(void);
|
||||
|
||||
private:
|
||||
GdkGC *mSharedGC;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // TOOLKIT_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,410 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef 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__ */
|
||||
@@ -1,274 +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 "nsIFactory.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIButton.h"
|
||||
#include "nsITextWidget.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
|
||||
#include "nsToolkit.h"
|
||||
#include "nsWindow.h"
|
||||
#include "nsAppShell.h"
|
||||
#include "nsButton.h"
|
||||
#include "nsScrollbar.h"
|
||||
#include "nsCheckButton.h"
|
||||
#include "nsRadioButton.h"
|
||||
#include "nsTextWidget.h"
|
||||
#include "nsTextAreaWidget.h"
|
||||
#include "nsFileWidget.h"
|
||||
#include "nsFileSpecWithUIImpl.h"
|
||||
#include "nsListBox.h"
|
||||
#include "nsComboBox.h"
|
||||
#include "nsLookAndFeel.h"
|
||||
#include "nsLabel.h"
|
||||
#ifdef LOSER
|
||||
#include "nsMenuBar.h"
|
||||
#include "nsMenu.h"
|
||||
#include "nsMenuItem.h"
|
||||
#include "nsPopUpMenu.h"
|
||||
#include "nsContextMenu.h"
|
||||
#endif
|
||||
#include "nsFontRetrieverService.h"
|
||||
|
||||
// Drag & Drop, Clipboard
|
||||
#include "nsClipboard.h"
|
||||
#include "nsTransferable.h"
|
||||
#include "nsXIFFormatConverter.h"
|
||||
#include "nsDragService.h"
|
||||
|
||||
#include "nsSound.h"
|
||||
|
||||
static NS_DEFINE_IID(kCWindow, NS_WINDOW_CID);
|
||||
static NS_DEFINE_IID(kCChild, NS_CHILD_CID);
|
||||
static NS_DEFINE_IID(kCButton, NS_BUTTON_CID);
|
||||
static NS_DEFINE_IID(kCCheckButton, NS_CHECKBUTTON_CID);
|
||||
static NS_DEFINE_IID(kCCombobox, NS_COMBOBOX_CID);
|
||||
static NS_DEFINE_IID(kCFileOpen, NS_FILEWIDGET_CID);
|
||||
static NS_DEFINE_IID(kCListbox, NS_LISTBOX_CID);
|
||||
static NS_DEFINE_IID(kCRadioButton, NS_RADIOBUTTON_CID);
|
||||
static NS_DEFINE_IID(kCHorzScrollbar, NS_HORZSCROLLBAR_CID);
|
||||
static NS_DEFINE_IID(kCVertScrollbar, NS_VERTSCROLLBAR_CID);
|
||||
static NS_DEFINE_IID(kCTextArea, NS_TEXTAREA_CID);
|
||||
static NS_DEFINE_IID(kCTextField, NS_TEXTFIELD_CID);
|
||||
static NS_DEFINE_IID(kCAppShell, NS_APPSHELL_CID);
|
||||
static NS_DEFINE_IID(kCToolkit, NS_TOOLKIT_CID);
|
||||
static NS_DEFINE_IID(kCLookAndFeel, NS_LOOKANDFEEL_CID);
|
||||
static NS_DEFINE_IID(kCLabel, NS_LABEL_CID);
|
||||
#if 0
|
||||
static NS_DEFINE_IID(kCMenuBar, NS_MENUBAR_CID);
|
||||
static NS_DEFINE_IID(kCMenu, NS_MENU_CID);
|
||||
static NS_DEFINE_IID(kCMenuItem, NS_MENUITEM_CID);
|
||||
static NS_DEFINE_IID(kCPopUpMenu, NS_POPUPMENU_CID);
|
||||
static NS_DEFINE_IID(kCContextMenu, NS_CONTEXTMENU_CID);
|
||||
#endif
|
||||
static NS_DEFINE_IID(kCFontRetrieverService, NS_FONTRETRIEVERSERVICE_CID);
|
||||
|
||||
// Drag & Drop, Clipboard
|
||||
static NS_DEFINE_IID(kCDataObj, NS_DATAOBJ_CID);
|
||||
static NS_DEFINE_IID(kCClipboard, NS_CLIPBOARD_CID);
|
||||
static NS_DEFINE_IID(kCTransferable, NS_TRANSFERABLE_CID);
|
||||
static NS_DEFINE_IID(kCDataFlavor, NS_DATAFLAVOR_CID);
|
||||
static NS_DEFINE_IID(kCXIFFormatConverter, NS_XIFFORMATCONVERTER_CID);
|
||||
static NS_DEFINE_IID(kCDragService, NS_DRAGSERVICE_CID);
|
||||
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
|
||||
|
||||
// Sound services (just Beep for now)
|
||||
static NS_DEFINE_CID(kCSound, NS_SOUND_CID);
|
||||
static NS_DEFINE_CID(kCFileSpecWithUI, NS_FILESPECWITHUI_CID);
|
||||
|
||||
|
||||
class nsWidgetFactory : public nsIFactory
|
||||
{
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_DECL_NSIFACTORY
|
||||
|
||||
nsWidgetFactory(const nsCID &aClass);
|
||||
virtual ~nsWidgetFactory();
|
||||
private:
|
||||
nsCID mClassID;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
nsWidgetFactory::nsWidgetFactory(const nsCID &aClass)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
mClassID = aClass;
|
||||
}
|
||||
|
||||
nsWidgetFactory::~nsWidgetFactory()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsWidgetFactory, NS_GET_IID(nsIFactory))
|
||||
|
||||
nsresult nsWidgetFactory::CreateInstance(nsISupports *aOuter,
|
||||
const nsIID &aIID,
|
||||
void **aResult)
|
||||
{
|
||||
if (aResult == NULL) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
*aResult = NULL;
|
||||
|
||||
if (nsnull != aOuter)
|
||||
return NS_ERROR_NO_AGGREGATION;
|
||||
|
||||
nsISupports *inst = nsnull;
|
||||
if (mClassID.Equals(kCWindow)) {
|
||||
inst = (nsISupports *)new nsWindow();
|
||||
}
|
||||
else if (mClassID.Equals(kCChild)) {
|
||||
inst = (nsISupports *)new ChildWindow();
|
||||
}
|
||||
else if (mClassID.Equals(kCButton)) {
|
||||
inst = (nsISupports*)(nsWidget *)new nsButton();
|
||||
}
|
||||
else if (mClassID.Equals(kCCheckButton)) {
|
||||
inst = (nsISupports*)(nsWidget *)new nsCheckButton();
|
||||
}
|
||||
else if (mClassID.Equals(kCCombobox)) {
|
||||
inst = (nsISupports*)(nsWidget *)new nsComboBox();
|
||||
}
|
||||
else if (mClassID.Equals(kCRadioButton)) {
|
||||
inst = (nsISupports*)(nsWidget *)new nsRadioButton();
|
||||
}
|
||||
else if (mClassID.Equals(kCFileOpen)) {
|
||||
inst = (nsISupports*)new nsFileWidget();
|
||||
}
|
||||
else if (mClassID.Equals(kCListbox)) {
|
||||
inst = (nsISupports*)(nsWidget *)new nsListBox();
|
||||
}
|
||||
else if (mClassID.Equals(kCHorzScrollbar)) {
|
||||
inst = (nsISupports*)(nsWidget *)new nsScrollbar(PR_FALSE);
|
||||
}
|
||||
else if (mClassID.Equals(kCVertScrollbar)) {
|
||||
inst = (nsISupports*)(nsWidget *)new nsScrollbar(PR_TRUE);
|
||||
}
|
||||
else if (mClassID.Equals(kCTextArea)) {
|
||||
inst = (nsISupports*)(nsWidget *)new nsTextAreaWidget();
|
||||
}
|
||||
else if (mClassID.Equals(kCTextField)) {
|
||||
inst = (nsISupports*)(nsWidget *)new nsTextWidget();
|
||||
}
|
||||
else if (mClassID.Equals(kCAppShell)) {
|
||||
inst = (nsISupports*)new nsAppShell();
|
||||
}
|
||||
else if (mClassID.Equals(kCToolkit)) {
|
||||
inst = (nsISupports*)(nsWidget *)new nsToolkit();
|
||||
}
|
||||
else if (mClassID.Equals(kCLookAndFeel)) {
|
||||
inst = (nsISupports*)(nsWidget *)new nsLookAndFeel();
|
||||
}
|
||||
else if (mClassID.Equals(kCLabel)) {
|
||||
inst = (nsISupports*)(nsWidget *)new nsLabel();
|
||||
}
|
||||
#if 0
|
||||
else if (mClassID.Equals(kCMenuBar)) {
|
||||
inst = (nsISupports*)(nsIMenuBar *)new nsMenuBar();
|
||||
}
|
||||
else if (mClassID.Equals(kCMenu)) {
|
||||
inst = (nsISupports*)(nsIMenu *)new nsMenu();
|
||||
}
|
||||
else if (mClassID.Equals(kCMenuItem)) {
|
||||
inst = (nsISupports*)(nsIMenuItem *)new nsMenuItem();
|
||||
}
|
||||
else if (mClassID.Equals(kCPopUpMenu)) {
|
||||
inst = (nsISupports*)new nsPopUpMenu();
|
||||
}
|
||||
/*
|
||||
else if (mClassID.Equals(kCContextMenu)) {
|
||||
inst = (nsISupports*)(nsIContextMenu*)new nsContextMenu();
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
else if (mClassID.Equals(kCSound)) {
|
||||
nsISound* aSound = nsnull;
|
||||
NS_NewSound(&aSound);
|
||||
inst = (nsISupports*) aSound;
|
||||
}
|
||||
else if (mClassID.Equals(kCTransferable)) {
|
||||
inst = (nsISupports*)new nsTransferable();
|
||||
}
|
||||
else if (mClassID.Equals(kCClipboard)) {
|
||||
inst = (nsISupports*)new nsClipboard();
|
||||
}
|
||||
else if (mClassID.Equals(kCXIFFormatConverter))
|
||||
inst = (nsISupports*)new nsXIFFormatConverter();
|
||||
else if (mClassID.Equals(kCFontRetrieverService))
|
||||
inst = (nsISupports*)(nsIFontRetrieverService *) new nsFontRetrieverService();
|
||||
else if (mClassID.Equals(kCDragService))
|
||||
inst = (nsISupports*) (nsIDragService *) new nsDragService();
|
||||
else if (mClassID.Equals(kCFileSpecWithUI))
|
||||
inst = (nsISupports*) (nsIFileSpecWithUI *) new nsFileSpecWithUIImpl;
|
||||
else {
|
||||
printf("nsWidgetFactory::CreateInstance(), unhandled class.\n");
|
||||
}
|
||||
|
||||
if (inst == NULL) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_ADDREF(inst);
|
||||
nsresult res = inst->QueryInterface(aIID, aResult);
|
||||
NS_RELEASE(inst);
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
nsresult nsWidgetFactory::LockFactory(PRBool aLock)
|
||||
{
|
||||
// Not implemented in simplest case.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// return the proper factory to the caller
|
||||
extern "C" NS_WIDGET nsresult
|
||||
NSGetFactory(nsISupports* serviceMgr,
|
||||
const nsCID &aClass,
|
||||
const char *aClassName,
|
||||
const char *aProgID,
|
||||
nsIFactory **aFactory)
|
||||
{
|
||||
if (nsnull == aFactory) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
*aFactory = new nsWidgetFactory(aClass);
|
||||
|
||||
if (nsnull == aFactory) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return (*aFactory)->QueryInterface(kIFactoryIID, (void**)aFactory);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user