git-svn-id: svn://10.0.0.236/trunk@13148 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
kipp%netscape.com
1998-10-20 00:17:17 +00:00
parent 0c0aa03bc8
commit 1100db045f
12 changed files with 2789 additions and 0 deletions

View File

@@ -0,0 +1,213 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* 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.
*/
#ifndef nsTextFragment_h___
#define nsTextFragment_h___
#include "nslayout.h"
class nsString;
// XXX should this normalize the code to keep a \u0000 at the end?
// XXX nsTextFragmentPool?
/**
* A fragment of text. If mIs2b is 1 then the m2b pointer is valid
* otherwise the m1b pointer is valid. If m1b is used then each byte
* of data represents a single ucs2 character with the high byte being
* zero.
*
* This class does not have a virtual destructor therefore it is not
* meant to be subclassed.
*/
class NS_LAYOUT nsTextFragment {
public:
/**
* Default constructor. Initialize the fragment to be empty.
*/
nsTextFragment() {
m1b = nsnull;
mInHeap = 0;
mIs2b = 0;
mLength = 0;
}
~nsTextFragment();
/**
* Initialize the contents of this fragment to be a copy of
* the argument fragment.
*/
nsTextFragment(const nsTextFragment& aOther);
/**
* Initialize the contents of this fragment to be a copy of
* the argument 7bit ascii string.
*/
nsTextFragment(const char* aString);
/**
* Initialize the contents of this fragment to be a copy of
* the argument ucs2 string.
*/
nsTextFragment(const PRUnichar* aString);
/**
* Initialize the contents of this fragment to be a copy of
* the argument string.
*/
nsTextFragment(const nsString& aString);
/**
* Change the contents of this fragment to be a copy of the
* the argument fragment.
*/
nsTextFragment& operator=(const nsTextFragment& aOther);
/**
* Change the contents of this fragment to be a copy of the
* the argument 7bit ascii string.
*/
nsTextFragment& operator=(const char* aString);
/**
* Change the contents of this fragment to be a copy of the
* the argument ucs2 string.
*/
nsTextFragment& operator=(const PRUnichar* aString);
/**
* Change the contents of this fragment to be a copy of the
* the argument string.
*/
nsTextFragment& operator=(const nsString& aString);
/**
* Return PR_TRUE if this fragment is represented by PRUnichar data
*/
PRBool Is2b() const {
return mIs2b;
}
/**
* Get a pointer to constant PRUnichar data.
*/
const PRUnichar* Get2b() const {
NS_ASSERTION(Is2b(), "not 2b text");
return m2b;
}
/**
* Get a pointer to constant char data.
*/
const char* Get1b() const {
NS_ASSERTION(!Is2b(), "not 1b text");
return (const char*) m1b;
}
/**
* Get the length of the fragment. The length is the number of logical
* characters, not the number of bytes to store the characters.
*/
PRInt32 GetLength() const {
return PRInt32(mLength);
}
/**
* Mutable version of Get2b. Only works for a non-const object.
* Returns a pointer to the PRUnichar data.
*/
PRUnichar* Get2b() {
NS_ASSERTION(Is2b(), "not 2b text");
return m2b;
}
/**
* Mutable version of Get1b. Only works for a non-const object.
* Returns a pointer to the char data.
*/
char* Get1b() {
NS_ASSERTION(!Is2b(), "not 1b text");
return (char*) m1b;
}
/**
* Change the contents of this fragment to be the given buffer and
* length. The memory becomes owned by the fragment. In addition,
* the memory for aBuffer must have been allocated using the "new[]"
* because it will be released with "delete []".
*/
void SetTo(PRUnichar* aBuffer, PRInt32 aLength, PRBool aRelease);
/**
* Change the contents of this fragment to be a copy of the given
* buffer. Like operator= except a length is specified instead of
* assuming 0 termination.
*/
void SetTo(const PRUnichar* aBuffer, PRInt32 aLength);
/**
* Change the contents of this fragment to be a copy of the given
* buffer. Like operator= except a length is specified instead of
* assuming 0 termination.
*/
void SetTo(const char* aBuffer, PRInt32 aLength);
/**
* Append the contents of this string fragment to aString
*/
void AppendTo(nsString& aString) const;
/**
* Make a copy of the fragments contents starting at offset for
* count characters. The offset and count will be adjusted to
* lie within the fragments data. The fragments data is converted if
* necessary.
*/
void CopyTo(PRUnichar* aDest, PRInt32 aOffset, PRInt32 aCount);
/**
* Make a copy of the fragments contents starting at offset for
* count characters. The offset and count will be adjusted to
* lie within the fragments data. The fragments data is converted if
* necessary.
*/
void CopyTo(char* aDest, PRInt32 aOffset, PRInt32 aCount);
/**
* Return the character in the text-fragment at the given
* index. This always returns a PRUnichar.
*/
PRUnichar CharAt(PRInt32 aIndex) const {
NS_ASSERTION(PRUint32(aIndex) < mLength, "bad index");
return mIs2b ? m2b[aIndex] : PRUnichar(m1b[aIndex]);
}
protected:
union {
PRUnichar* m2b;
unsigned char* m1b;
};
PRUint32 mInHeap : 1;
PRUint32 mIs2b : 1;
PRUint32 mLength : 30;
void ReleaseText();
};
#endif /* nsTextFragment_h___ */

View File

@@ -0,0 +1,234 @@
/* -*- 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.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* 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.
*/
#include "nsTextFragment.h"
#include "nsString.h"
#include "nsCRT.h"
nsTextFragment::~nsTextFragment()
{
ReleaseText();
}
void
nsTextFragment::ReleaseText()
{
if (mLength && m1b && mInHeap) {
if (mIs2b) {
delete [] m2b;
}
else {
delete [] m1b;
}
}
m1b = nsnull;
mIs2b = 0;
mInHeap = 0;
mLength = 0;
}
nsTextFragment::nsTextFragment(const nsTextFragment& aOther)
{
if (aOther.Is2b()) {
SetTo(aOther.Get2b(), aOther.GetLength());
}
else {
SetTo(aOther.Get1b(), aOther.GetLength());
}
}
nsTextFragment::nsTextFragment(const char* aString)
{
SetTo(aString, strlen(aString));
}
nsTextFragment::nsTextFragment(const PRUnichar* aString)
{
SetTo(aString, nsCRT::strlen(aString));
}
nsTextFragment::nsTextFragment(const nsString& aString)
{
SetTo(aString.GetUnicode(), aString.Length());
}
nsTextFragment&
nsTextFragment::operator=(const nsTextFragment& aOther)
{
if (aOther.Is2b()) {
SetTo(aOther.Get2b(), aOther.GetLength());
}
else {
SetTo(aOther.Get1b(), aOther.GetLength());
}
return *this;
}
nsTextFragment&
nsTextFragment::operator=(const char* aString)
{
SetTo(aString, nsCRT::strlen(aString));
return *this;
}
nsTextFragment&
nsTextFragment::operator=(const PRUnichar* aString)
{
SetTo(aString, nsCRT::strlen(aString));
return *this;
}
nsTextFragment&
nsTextFragment::operator=(const nsString& aString)
{
SetTo(aString.GetUnicode(), aString.Length());
return *this;
}
void
nsTextFragment::SetTo(PRUnichar* aBuffer, PRInt32 aLength, PRBool aRelease)
{
ReleaseText();
m2b = aBuffer;
mIs2b = 1;
mInHeap = aRelease ? 1 : 0;
mLength = aLength;
}
void
nsTextFragment::SetTo(const PRUnichar* aBuffer, PRInt32 aLength)
{
ReleaseText();
if (0 != aLength) {
// See if we need to store the data in ucs2 or not
PRBool need2 = PR_FALSE;
const PRUnichar* cp = aBuffer;
const PRUnichar* end = aBuffer + aLength;
while (cp < end) {
PRUnichar ch = *cp++;
if (ch >> 8) {
need2 = PR_TRUE;
break;
}
}
if (need2) {
// Use ucs2 storage because we have to
PRUnichar* nt = new PRUnichar[aLength];
if (nsnull != nt) {
// Copy data
nsCRT::memcpy(nt, aBuffer, sizeof(PRUnichar) * aLength);
// Setup our fields
m2b = nt;
mIs2b = 1;
mInHeap = 1;
mLength = aLength;
}
}
else {
// Use 1 byte storage because we can
unsigned char* nt = new unsigned char[aLength];
if (nsnull != nt) {
// Copy data
unsigned char* cp = nt;
unsigned char* end = nt + aLength;
while (cp < end) {
*cp++ = (unsigned char) *aBuffer++;
}
// Setup our fields
m1b = nt;
mIs2b = 0;
mInHeap = 1;
mLength = aLength;
}
}
}
}
void
nsTextFragment::SetTo(const char* aBuffer, PRInt32 aLength)
{
ReleaseText();
if (0 != aLength) {
unsigned char* nt = new unsigned char[aLength];
if (nsnull != nt) {
nsCRT::memcpy(nt, aBuffer, sizeof(unsigned char) * aLength);
m1b = nt;
mIs2b = 0;
mInHeap = 1;
mLength = aLength;
}
}
}
void
nsTextFragment::AppendTo(nsString& aString) const
{
if (mIs2b) {
aString.Append(m2b, mLength);
}
else {
aString.Append((char*)m1b, mLength);
}
}
void
nsTextFragment::CopyTo(PRUnichar* aDest, PRInt32 aOffset, PRInt32 aCount)
{
if (aOffset < 0) aOffset = 0;
if (aOffset + aCount > GetLength()) {
aCount = mLength - aOffset;
}
if (0 != aCount) {
if (mIs2b) {
nsCRT::memcpy(aDest, m2b + aOffset, sizeof(PRUnichar) * aCount);
}
else {
unsigned char* cp = m1b + aOffset;
unsigned char* end = cp + aCount;
while (cp < end) {
*aDest = PRUnichar(*cp++);
}
}
}
}
void
nsTextFragment::CopyTo(char* aDest, PRInt32 aOffset, PRInt32 aCount)
{
if (aOffset < 0) aOffset = 0;
if (aOffset + aCount > GetLength()) {
aCount = mLength - aOffset;
}
if (0 != aCount) {
if (mIs2b) {
PRUnichar* cp = m2b + aOffset;
PRUnichar* end = cp + aCount;
while (cp < end) {
*aDest = (unsigned char) (*cp++);
}
}
else {
nsCRT::memcpy(aDest, m1b + aOffset, sizeof(char) * aCount);
}
}
}

View File

@@ -0,0 +1,213 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* 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.
*/
#ifndef nsTextFragment_h___
#define nsTextFragment_h___
#include "nslayout.h"
class nsString;
// XXX should this normalize the code to keep a \u0000 at the end?
// XXX nsTextFragmentPool?
/**
* A fragment of text. If mIs2b is 1 then the m2b pointer is valid
* otherwise the m1b pointer is valid. If m1b is used then each byte
* of data represents a single ucs2 character with the high byte being
* zero.
*
* This class does not have a virtual destructor therefore it is not
* meant to be subclassed.
*/
class NS_LAYOUT nsTextFragment {
public:
/**
* Default constructor. Initialize the fragment to be empty.
*/
nsTextFragment() {
m1b = nsnull;
mInHeap = 0;
mIs2b = 0;
mLength = 0;
}
~nsTextFragment();
/**
* Initialize the contents of this fragment to be a copy of
* the argument fragment.
*/
nsTextFragment(const nsTextFragment& aOther);
/**
* Initialize the contents of this fragment to be a copy of
* the argument 7bit ascii string.
*/
nsTextFragment(const char* aString);
/**
* Initialize the contents of this fragment to be a copy of
* the argument ucs2 string.
*/
nsTextFragment(const PRUnichar* aString);
/**
* Initialize the contents of this fragment to be a copy of
* the argument string.
*/
nsTextFragment(const nsString& aString);
/**
* Change the contents of this fragment to be a copy of the
* the argument fragment.
*/
nsTextFragment& operator=(const nsTextFragment& aOther);
/**
* Change the contents of this fragment to be a copy of the
* the argument 7bit ascii string.
*/
nsTextFragment& operator=(const char* aString);
/**
* Change the contents of this fragment to be a copy of the
* the argument ucs2 string.
*/
nsTextFragment& operator=(const PRUnichar* aString);
/**
* Change the contents of this fragment to be a copy of the
* the argument string.
*/
nsTextFragment& operator=(const nsString& aString);
/**
* Return PR_TRUE if this fragment is represented by PRUnichar data
*/
PRBool Is2b() const {
return mIs2b;
}
/**
* Get a pointer to constant PRUnichar data.
*/
const PRUnichar* Get2b() const {
NS_ASSERTION(Is2b(), "not 2b text");
return m2b;
}
/**
* Get a pointer to constant char data.
*/
const char* Get1b() const {
NS_ASSERTION(!Is2b(), "not 1b text");
return (const char*) m1b;
}
/**
* Get the length of the fragment. The length is the number of logical
* characters, not the number of bytes to store the characters.
*/
PRInt32 GetLength() const {
return PRInt32(mLength);
}
/**
* Mutable version of Get2b. Only works for a non-const object.
* Returns a pointer to the PRUnichar data.
*/
PRUnichar* Get2b() {
NS_ASSERTION(Is2b(), "not 2b text");
return m2b;
}
/**
* Mutable version of Get1b. Only works for a non-const object.
* Returns a pointer to the char data.
*/
char* Get1b() {
NS_ASSERTION(!Is2b(), "not 1b text");
return (char*) m1b;
}
/**
* Change the contents of this fragment to be the given buffer and
* length. The memory becomes owned by the fragment. In addition,
* the memory for aBuffer must have been allocated using the "new[]"
* because it will be released with "delete []".
*/
void SetTo(PRUnichar* aBuffer, PRInt32 aLength, PRBool aRelease);
/**
* Change the contents of this fragment to be a copy of the given
* buffer. Like operator= except a length is specified instead of
* assuming 0 termination.
*/
void SetTo(const PRUnichar* aBuffer, PRInt32 aLength);
/**
* Change the contents of this fragment to be a copy of the given
* buffer. Like operator= except a length is specified instead of
* assuming 0 termination.
*/
void SetTo(const char* aBuffer, PRInt32 aLength);
/**
* Append the contents of this string fragment to aString
*/
void AppendTo(nsString& aString) const;
/**
* Make a copy of the fragments contents starting at offset for
* count characters. The offset and count will be adjusted to
* lie within the fragments data. The fragments data is converted if
* necessary.
*/
void CopyTo(PRUnichar* aDest, PRInt32 aOffset, PRInt32 aCount);
/**
* Make a copy of the fragments contents starting at offset for
* count characters. The offset and count will be adjusted to
* lie within the fragments data. The fragments data is converted if
* necessary.
*/
void CopyTo(char* aDest, PRInt32 aOffset, PRInt32 aCount);
/**
* Return the character in the text-fragment at the given
* index. This always returns a PRUnichar.
*/
PRUnichar CharAt(PRInt32 aIndex) const {
NS_ASSERTION(PRUint32(aIndex) < mLength, "bad index");
return mIs2b ? m2b[aIndex] : PRUnichar(m1b[aIndex]);
}
protected:
union {
PRUnichar* m2b;
unsigned char* m1b;
};
PRUint32 mInHeap : 1;
PRUint32 mIs2b : 1;
PRUint32 mLength : 30;
void ReleaseText();
};
#endif /* nsTextFragment_h___ */

View File

@@ -0,0 +1,213 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* 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.
*/
#ifndef nsTextFragment_h___
#define nsTextFragment_h___
#include "nslayout.h"
class nsString;
// XXX should this normalize the code to keep a \u0000 at the end?
// XXX nsTextFragmentPool?
/**
* A fragment of text. If mIs2b is 1 then the m2b pointer is valid
* otherwise the m1b pointer is valid. If m1b is used then each byte
* of data represents a single ucs2 character with the high byte being
* zero.
*
* This class does not have a virtual destructor therefore it is not
* meant to be subclassed.
*/
class NS_LAYOUT nsTextFragment {
public:
/**
* Default constructor. Initialize the fragment to be empty.
*/
nsTextFragment() {
m1b = nsnull;
mInHeap = 0;
mIs2b = 0;
mLength = 0;
}
~nsTextFragment();
/**
* Initialize the contents of this fragment to be a copy of
* the argument fragment.
*/
nsTextFragment(const nsTextFragment& aOther);
/**
* Initialize the contents of this fragment to be a copy of
* the argument 7bit ascii string.
*/
nsTextFragment(const char* aString);
/**
* Initialize the contents of this fragment to be a copy of
* the argument ucs2 string.
*/
nsTextFragment(const PRUnichar* aString);
/**
* Initialize the contents of this fragment to be a copy of
* the argument string.
*/
nsTextFragment(const nsString& aString);
/**
* Change the contents of this fragment to be a copy of the
* the argument fragment.
*/
nsTextFragment& operator=(const nsTextFragment& aOther);
/**
* Change the contents of this fragment to be a copy of the
* the argument 7bit ascii string.
*/
nsTextFragment& operator=(const char* aString);
/**
* Change the contents of this fragment to be a copy of the
* the argument ucs2 string.
*/
nsTextFragment& operator=(const PRUnichar* aString);
/**
* Change the contents of this fragment to be a copy of the
* the argument string.
*/
nsTextFragment& operator=(const nsString& aString);
/**
* Return PR_TRUE if this fragment is represented by PRUnichar data
*/
PRBool Is2b() const {
return mIs2b;
}
/**
* Get a pointer to constant PRUnichar data.
*/
const PRUnichar* Get2b() const {
NS_ASSERTION(Is2b(), "not 2b text");
return m2b;
}
/**
* Get a pointer to constant char data.
*/
const char* Get1b() const {
NS_ASSERTION(!Is2b(), "not 1b text");
return (const char*) m1b;
}
/**
* Get the length of the fragment. The length is the number of logical
* characters, not the number of bytes to store the characters.
*/
PRInt32 GetLength() const {
return PRInt32(mLength);
}
/**
* Mutable version of Get2b. Only works for a non-const object.
* Returns a pointer to the PRUnichar data.
*/
PRUnichar* Get2b() {
NS_ASSERTION(Is2b(), "not 2b text");
return m2b;
}
/**
* Mutable version of Get1b. Only works for a non-const object.
* Returns a pointer to the char data.
*/
char* Get1b() {
NS_ASSERTION(!Is2b(), "not 1b text");
return (char*) m1b;
}
/**
* Change the contents of this fragment to be the given buffer and
* length. The memory becomes owned by the fragment. In addition,
* the memory for aBuffer must have been allocated using the "new[]"
* because it will be released with "delete []".
*/
void SetTo(PRUnichar* aBuffer, PRInt32 aLength, PRBool aRelease);
/**
* Change the contents of this fragment to be a copy of the given
* buffer. Like operator= except a length is specified instead of
* assuming 0 termination.
*/
void SetTo(const PRUnichar* aBuffer, PRInt32 aLength);
/**
* Change the contents of this fragment to be a copy of the given
* buffer. Like operator= except a length is specified instead of
* assuming 0 termination.
*/
void SetTo(const char* aBuffer, PRInt32 aLength);
/**
* Append the contents of this string fragment to aString
*/
void AppendTo(nsString& aString) const;
/**
* Make a copy of the fragments contents starting at offset for
* count characters. The offset and count will be adjusted to
* lie within the fragments data. The fragments data is converted if
* necessary.
*/
void CopyTo(PRUnichar* aDest, PRInt32 aOffset, PRInt32 aCount);
/**
* Make a copy of the fragments contents starting at offset for
* count characters. The offset and count will be adjusted to
* lie within the fragments data. The fragments data is converted if
* necessary.
*/
void CopyTo(char* aDest, PRInt32 aOffset, PRInt32 aCount);
/**
* Return the character in the text-fragment at the given
* index. This always returns a PRUnichar.
*/
PRUnichar CharAt(PRInt32 aIndex) const {
NS_ASSERTION(PRUint32(aIndex) < mLength, "bad index");
return mIs2b ? m2b[aIndex] : PRUnichar(m1b[aIndex]);
}
protected:
union {
PRUnichar* m2b;
unsigned char* m1b;
};
PRUint32 mInHeap : 1;
PRUint32 mIs2b : 1;
PRUint32 mLength : 30;
void ReleaseText();
};
#endif /* nsTextFragment_h___ */

View File

@@ -0,0 +1,234 @@
/* -*- 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.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* 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.
*/
#include "nsTextFragment.h"
#include "nsString.h"
#include "nsCRT.h"
nsTextFragment::~nsTextFragment()
{
ReleaseText();
}
void
nsTextFragment::ReleaseText()
{
if (mLength && m1b && mInHeap) {
if (mIs2b) {
delete [] m2b;
}
else {
delete [] m1b;
}
}
m1b = nsnull;
mIs2b = 0;
mInHeap = 0;
mLength = 0;
}
nsTextFragment::nsTextFragment(const nsTextFragment& aOther)
{
if (aOther.Is2b()) {
SetTo(aOther.Get2b(), aOther.GetLength());
}
else {
SetTo(aOther.Get1b(), aOther.GetLength());
}
}
nsTextFragment::nsTextFragment(const char* aString)
{
SetTo(aString, strlen(aString));
}
nsTextFragment::nsTextFragment(const PRUnichar* aString)
{
SetTo(aString, nsCRT::strlen(aString));
}
nsTextFragment::nsTextFragment(const nsString& aString)
{
SetTo(aString.GetUnicode(), aString.Length());
}
nsTextFragment&
nsTextFragment::operator=(const nsTextFragment& aOther)
{
if (aOther.Is2b()) {
SetTo(aOther.Get2b(), aOther.GetLength());
}
else {
SetTo(aOther.Get1b(), aOther.GetLength());
}
return *this;
}
nsTextFragment&
nsTextFragment::operator=(const char* aString)
{
SetTo(aString, nsCRT::strlen(aString));
return *this;
}
nsTextFragment&
nsTextFragment::operator=(const PRUnichar* aString)
{
SetTo(aString, nsCRT::strlen(aString));
return *this;
}
nsTextFragment&
nsTextFragment::operator=(const nsString& aString)
{
SetTo(aString.GetUnicode(), aString.Length());
return *this;
}
void
nsTextFragment::SetTo(PRUnichar* aBuffer, PRInt32 aLength, PRBool aRelease)
{
ReleaseText();
m2b = aBuffer;
mIs2b = 1;
mInHeap = aRelease ? 1 : 0;
mLength = aLength;
}
void
nsTextFragment::SetTo(const PRUnichar* aBuffer, PRInt32 aLength)
{
ReleaseText();
if (0 != aLength) {
// See if we need to store the data in ucs2 or not
PRBool need2 = PR_FALSE;
const PRUnichar* cp = aBuffer;
const PRUnichar* end = aBuffer + aLength;
while (cp < end) {
PRUnichar ch = *cp++;
if (ch >> 8) {
need2 = PR_TRUE;
break;
}
}
if (need2) {
// Use ucs2 storage because we have to
PRUnichar* nt = new PRUnichar[aLength];
if (nsnull != nt) {
// Copy data
nsCRT::memcpy(nt, aBuffer, sizeof(PRUnichar) * aLength);
// Setup our fields
m2b = nt;
mIs2b = 1;
mInHeap = 1;
mLength = aLength;
}
}
else {
// Use 1 byte storage because we can
unsigned char* nt = new unsigned char[aLength];
if (nsnull != nt) {
// Copy data
unsigned char* cp = nt;
unsigned char* end = nt + aLength;
while (cp < end) {
*cp++ = (unsigned char) *aBuffer++;
}
// Setup our fields
m1b = nt;
mIs2b = 0;
mInHeap = 1;
mLength = aLength;
}
}
}
}
void
nsTextFragment::SetTo(const char* aBuffer, PRInt32 aLength)
{
ReleaseText();
if (0 != aLength) {
unsigned char* nt = new unsigned char[aLength];
if (nsnull != nt) {
nsCRT::memcpy(nt, aBuffer, sizeof(unsigned char) * aLength);
m1b = nt;
mIs2b = 0;
mInHeap = 1;
mLength = aLength;
}
}
}
void
nsTextFragment::AppendTo(nsString& aString) const
{
if (mIs2b) {
aString.Append(m2b, mLength);
}
else {
aString.Append((char*)m1b, mLength);
}
}
void
nsTextFragment::CopyTo(PRUnichar* aDest, PRInt32 aOffset, PRInt32 aCount)
{
if (aOffset < 0) aOffset = 0;
if (aOffset + aCount > GetLength()) {
aCount = mLength - aOffset;
}
if (0 != aCount) {
if (mIs2b) {
nsCRT::memcpy(aDest, m2b + aOffset, sizeof(PRUnichar) * aCount);
}
else {
unsigned char* cp = m1b + aOffset;
unsigned char* end = cp + aCount;
while (cp < end) {
*aDest = PRUnichar(*cp++);
}
}
}
}
void
nsTextFragment::CopyTo(char* aDest, PRInt32 aOffset, PRInt32 aCount)
{
if (aOffset < 0) aOffset = 0;
if (aOffset + aCount > GetLength()) {
aCount = mLength - aOffset;
}
if (0 != aCount) {
if (mIs2b) {
PRUnichar* cp = m2b + aOffset;
PRUnichar* end = cp + aCount;
while (cp < end) {
*aDest = (unsigned char) (*cp++);
}
}
else {
nsCRT::memcpy(aDest, m1b + aOffset, sizeof(char) * aCount);
}
}
}

View File

@@ -0,0 +1,213 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* 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.
*/
#ifndef nsTextFragment_h___
#define nsTextFragment_h___
#include "nslayout.h"
class nsString;
// XXX should this normalize the code to keep a \u0000 at the end?
// XXX nsTextFragmentPool?
/**
* A fragment of text. If mIs2b is 1 then the m2b pointer is valid
* otherwise the m1b pointer is valid. If m1b is used then each byte
* of data represents a single ucs2 character with the high byte being
* zero.
*
* This class does not have a virtual destructor therefore it is not
* meant to be subclassed.
*/
class NS_LAYOUT nsTextFragment {
public:
/**
* Default constructor. Initialize the fragment to be empty.
*/
nsTextFragment() {
m1b = nsnull;
mInHeap = 0;
mIs2b = 0;
mLength = 0;
}
~nsTextFragment();
/**
* Initialize the contents of this fragment to be a copy of
* the argument fragment.
*/
nsTextFragment(const nsTextFragment& aOther);
/**
* Initialize the contents of this fragment to be a copy of
* the argument 7bit ascii string.
*/
nsTextFragment(const char* aString);
/**
* Initialize the contents of this fragment to be a copy of
* the argument ucs2 string.
*/
nsTextFragment(const PRUnichar* aString);
/**
* Initialize the contents of this fragment to be a copy of
* the argument string.
*/
nsTextFragment(const nsString& aString);
/**
* Change the contents of this fragment to be a copy of the
* the argument fragment.
*/
nsTextFragment& operator=(const nsTextFragment& aOther);
/**
* Change the contents of this fragment to be a copy of the
* the argument 7bit ascii string.
*/
nsTextFragment& operator=(const char* aString);
/**
* Change the contents of this fragment to be a copy of the
* the argument ucs2 string.
*/
nsTextFragment& operator=(const PRUnichar* aString);
/**
* Change the contents of this fragment to be a copy of the
* the argument string.
*/
nsTextFragment& operator=(const nsString& aString);
/**
* Return PR_TRUE if this fragment is represented by PRUnichar data
*/
PRBool Is2b() const {
return mIs2b;
}
/**
* Get a pointer to constant PRUnichar data.
*/
const PRUnichar* Get2b() const {
NS_ASSERTION(Is2b(), "not 2b text");
return m2b;
}
/**
* Get a pointer to constant char data.
*/
const char* Get1b() const {
NS_ASSERTION(!Is2b(), "not 1b text");
return (const char*) m1b;
}
/**
* Get the length of the fragment. The length is the number of logical
* characters, not the number of bytes to store the characters.
*/
PRInt32 GetLength() const {
return PRInt32(mLength);
}
/**
* Mutable version of Get2b. Only works for a non-const object.
* Returns a pointer to the PRUnichar data.
*/
PRUnichar* Get2b() {
NS_ASSERTION(Is2b(), "not 2b text");
return m2b;
}
/**
* Mutable version of Get1b. Only works for a non-const object.
* Returns a pointer to the char data.
*/
char* Get1b() {
NS_ASSERTION(!Is2b(), "not 1b text");
return (char*) m1b;
}
/**
* Change the contents of this fragment to be the given buffer and
* length. The memory becomes owned by the fragment. In addition,
* the memory for aBuffer must have been allocated using the "new[]"
* because it will be released with "delete []".
*/
void SetTo(PRUnichar* aBuffer, PRInt32 aLength, PRBool aRelease);
/**
* Change the contents of this fragment to be a copy of the given
* buffer. Like operator= except a length is specified instead of
* assuming 0 termination.
*/
void SetTo(const PRUnichar* aBuffer, PRInt32 aLength);
/**
* Change the contents of this fragment to be a copy of the given
* buffer. Like operator= except a length is specified instead of
* assuming 0 termination.
*/
void SetTo(const char* aBuffer, PRInt32 aLength);
/**
* Append the contents of this string fragment to aString
*/
void AppendTo(nsString& aString) const;
/**
* Make a copy of the fragments contents starting at offset for
* count characters. The offset and count will be adjusted to
* lie within the fragments data. The fragments data is converted if
* necessary.
*/
void CopyTo(PRUnichar* aDest, PRInt32 aOffset, PRInt32 aCount);
/**
* Make a copy of the fragments contents starting at offset for
* count characters. The offset and count will be adjusted to
* lie within the fragments data. The fragments data is converted if
* necessary.
*/
void CopyTo(char* aDest, PRInt32 aOffset, PRInt32 aCount);
/**
* Return the character in the text-fragment at the given
* index. This always returns a PRUnichar.
*/
PRUnichar CharAt(PRInt32 aIndex) const {
NS_ASSERTION(PRUint32(aIndex) < mLength, "bad index");
return mIs2b ? m2b[aIndex] : PRUnichar(m1b[aIndex]);
}
protected:
union {
PRUnichar* m2b;
unsigned char* m1b;
};
PRUint32 mInHeap : 1;
PRUint32 mIs2b : 1;
PRUint32 mLength : 30;
void ReleaseText();
};
#endif /* nsTextFragment_h___ */

View File

@@ -0,0 +1,234 @@
/* -*- 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.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* 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.
*/
#include "nsTextFragment.h"
#include "nsString.h"
#include "nsCRT.h"
nsTextFragment::~nsTextFragment()
{
ReleaseText();
}
void
nsTextFragment::ReleaseText()
{
if (mLength && m1b && mInHeap) {
if (mIs2b) {
delete [] m2b;
}
else {
delete [] m1b;
}
}
m1b = nsnull;
mIs2b = 0;
mInHeap = 0;
mLength = 0;
}
nsTextFragment::nsTextFragment(const nsTextFragment& aOther)
{
if (aOther.Is2b()) {
SetTo(aOther.Get2b(), aOther.GetLength());
}
else {
SetTo(aOther.Get1b(), aOther.GetLength());
}
}
nsTextFragment::nsTextFragment(const char* aString)
{
SetTo(aString, strlen(aString));
}
nsTextFragment::nsTextFragment(const PRUnichar* aString)
{
SetTo(aString, nsCRT::strlen(aString));
}
nsTextFragment::nsTextFragment(const nsString& aString)
{
SetTo(aString.GetUnicode(), aString.Length());
}
nsTextFragment&
nsTextFragment::operator=(const nsTextFragment& aOther)
{
if (aOther.Is2b()) {
SetTo(aOther.Get2b(), aOther.GetLength());
}
else {
SetTo(aOther.Get1b(), aOther.GetLength());
}
return *this;
}
nsTextFragment&
nsTextFragment::operator=(const char* aString)
{
SetTo(aString, nsCRT::strlen(aString));
return *this;
}
nsTextFragment&
nsTextFragment::operator=(const PRUnichar* aString)
{
SetTo(aString, nsCRT::strlen(aString));
return *this;
}
nsTextFragment&
nsTextFragment::operator=(const nsString& aString)
{
SetTo(aString.GetUnicode(), aString.Length());
return *this;
}
void
nsTextFragment::SetTo(PRUnichar* aBuffer, PRInt32 aLength, PRBool aRelease)
{
ReleaseText();
m2b = aBuffer;
mIs2b = 1;
mInHeap = aRelease ? 1 : 0;
mLength = aLength;
}
void
nsTextFragment::SetTo(const PRUnichar* aBuffer, PRInt32 aLength)
{
ReleaseText();
if (0 != aLength) {
// See if we need to store the data in ucs2 or not
PRBool need2 = PR_FALSE;
const PRUnichar* cp = aBuffer;
const PRUnichar* end = aBuffer + aLength;
while (cp < end) {
PRUnichar ch = *cp++;
if (ch >> 8) {
need2 = PR_TRUE;
break;
}
}
if (need2) {
// Use ucs2 storage because we have to
PRUnichar* nt = new PRUnichar[aLength];
if (nsnull != nt) {
// Copy data
nsCRT::memcpy(nt, aBuffer, sizeof(PRUnichar) * aLength);
// Setup our fields
m2b = nt;
mIs2b = 1;
mInHeap = 1;
mLength = aLength;
}
}
else {
// Use 1 byte storage because we can
unsigned char* nt = new unsigned char[aLength];
if (nsnull != nt) {
// Copy data
unsigned char* cp = nt;
unsigned char* end = nt + aLength;
while (cp < end) {
*cp++ = (unsigned char) *aBuffer++;
}
// Setup our fields
m1b = nt;
mIs2b = 0;
mInHeap = 1;
mLength = aLength;
}
}
}
}
void
nsTextFragment::SetTo(const char* aBuffer, PRInt32 aLength)
{
ReleaseText();
if (0 != aLength) {
unsigned char* nt = new unsigned char[aLength];
if (nsnull != nt) {
nsCRT::memcpy(nt, aBuffer, sizeof(unsigned char) * aLength);
m1b = nt;
mIs2b = 0;
mInHeap = 1;
mLength = aLength;
}
}
}
void
nsTextFragment::AppendTo(nsString& aString) const
{
if (mIs2b) {
aString.Append(m2b, mLength);
}
else {
aString.Append((char*)m1b, mLength);
}
}
void
nsTextFragment::CopyTo(PRUnichar* aDest, PRInt32 aOffset, PRInt32 aCount)
{
if (aOffset < 0) aOffset = 0;
if (aOffset + aCount > GetLength()) {
aCount = mLength - aOffset;
}
if (0 != aCount) {
if (mIs2b) {
nsCRT::memcpy(aDest, m2b + aOffset, sizeof(PRUnichar) * aCount);
}
else {
unsigned char* cp = m1b + aOffset;
unsigned char* end = cp + aCount;
while (cp < end) {
*aDest = PRUnichar(*cp++);
}
}
}
}
void
nsTextFragment::CopyTo(char* aDest, PRInt32 aOffset, PRInt32 aCount)
{
if (aOffset < 0) aOffset = 0;
if (aOffset + aCount > GetLength()) {
aCount = mLength - aOffset;
}
if (0 != aCount) {
if (mIs2b) {
PRUnichar* cp = m2b + aOffset;
PRUnichar* end = cp + aCount;
while (cp < end) {
*aDest = (unsigned char) (*cp++);
}
}
else {
nsCRT::memcpy(aDest, m1b + aOffset, sizeof(char) * aCount);
}
}
}

View File

@@ -0,0 +1,442 @@
/* -*- 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.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* 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.
*/
#include "nsTextTransformer.h"
#include "nsIContent.h"
#include "nsIFrame.h"
#include "nsIStyleContext.h"
#include "nsITextContent.h"
#include "nsStyleConsts.h"
// XXX put a copy in nsHTMLIIDs
static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);
// XXX temporary
#define XP_IS_SPACE(_ch) \
(((_ch) == ' ') || ((_ch) == '\t') || ((_ch) == '\n'))
// XXX need more of this in nsIRenderingContext.GetWidth
#define CH_NBSP 160
#define MAX_UNIBYTE 127
nsTextTransformer::nsTextTransformer(PRUnichar* aBuffer, PRInt32 aBufLen)
: mAutoBuffer(aBuffer),
mBuffer(aBuffer),
mBufferLength(aBufLen < 0 ? 0 : aBufLen),
mHasMultibyte(PR_FALSE)
{
}
nsTextTransformer::~nsTextTransformer()
{
if (mBuffer != mAutoBuffer) {
delete [] mBuffer;
}
}
nsresult
nsTextTransformer::Init(/*nsTextRun& aTextRun, XXX*/
nsIFrame* aFrame,
PRInt32 aStartingOffset)
{
// Make sure we have *some* space in case arguments to the ctor were
// bizzare.
if (mBufferLength < 100) {
if (!GrowBuffer()) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
// Get the frames text content
nsIContent* content;
aFrame->GetContent(content);
nsITextContent* tc;
if (NS_OK != content->QueryInterface(kITextContentIID, (void**) &tc)) {
NS_RELEASE(content);
return NS_OK;
}
tc->GetText(mFrags, mNumFrags);
NS_RELEASE(tc);
NS_RELEASE(content);
mStartingOffset = aStartingOffset;
mOffset = mStartingOffset;
// Compute the total length of the text content.
PRInt32 sum = 0;
PRInt32 n = mNumFrags;
const nsTextFragment* frag = mFrags;
for (; --n >= 0; frag++) {
sum += frag->GetLength();
}
mContentLength = sum;
// Set current fragment and current fragment offset
mCurrentFrag = mFrags;
mCurrentFragOffset = 0;
PRInt32 offset = 0;
n = mNumFrags;
for (frag = mFrags; --n >= 0; frag++) {
if (aStartingOffset < offset + frag->GetLength()) {
mCurrentFrag = frag;
mCurrentFragOffset = aStartingOffset - offset;
break;
}
offset += frag->GetLength();
}
// Get the frames style and choose a transform proc
const nsStyleText* styleText;
aFrame->GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&) styleText);
mCompressWS = NS_STYLE_WHITESPACE_PRE != styleText->mWhiteSpace;
return NS_OK;
}
PRBool
nsTextTransformer::GrowBuffer()
{
PRInt32 newLen = mBufferLength * 2;
if (newLen <= 100) {
newLen = 100;
}
PRUnichar* newBuffer = new PRUnichar[newLen];
if (nsnull == newBuffer) {
return PR_FALSE;
}
if (0 != mBufferLength) {
nsCRT::memcpy(newBuffer, mBuffer, sizeof(PRUnichar) * mBufferLength);
if (mBuffer != mAutoBuffer) {
delete [] mBuffer;
}
}
mBuffer = newBuffer;
return PR_TRUE;
}
PRUnichar*
nsTextTransformer::GetNextWord(PRInt32& aWordLenResult,
PRInt32& aContentLenResult,
PRBool& aIsWhitespaceResult)
{
NS_PRECONDITION(mOffset <= mContentLength, "bad offset");
// See if the content has been exhausted
if (mOffset == mContentLength) {
aWordLenResult = 0;
aContentLenResult = 0;
return nsnull;
}
PRUnichar* bp = mBuffer;
PRUnichar* bufEnd = mBuffer + mBufferLength;
const nsTextFragment* frag = mCurrentFrag;
const nsTextFragment* lastFrag = frag + mNumFrags;
// Set the isWhitespace flag by examining the next character in the
// text fragment.
PRInt32 offset = mCurrentFragOffset;
PRUnichar firstChar;
if (frag->Is2b()) {
const PRUnichar* up = frag->Get2b();
firstChar = up[offset];
}
else {
const unsigned char* cp = (const unsigned char*) frag->Get1b();
firstChar = PRUnichar(cp[offset]);
}
PRBool isWhitespace = XP_IS_SPACE(firstChar);
offset++;
if (isWhitespace || (CH_NBSP == firstChar)) {
*bp++ = ' ';
}
else {
*bp++ = firstChar;
}
PRInt32 contentLen = 1;
PRInt32 wordLen = 1;
if (offset == frag->GetLength()) {
mCurrentFrag = ++frag;
offset = 0;
}
mCurrentFragOffset = offset;
// XXX here is where we switch out to type specific handlers; this
// code assumes mCompressWS is PR_TRUE
// Now that we know what we are looking for, scan through the text
// content and find the end of it.
PRInt32 numChars;
while (frag < lastFrag) {
PRInt32 fragLen = frag->GetLength();
// Scan characters in this fragment that are the same kind as the
// isWhitespace flag indicates.
if (frag->Is2b()) {
const PRUnichar* cp0 = frag->Get2b();
const PRUnichar* end = cp0 + fragLen;
const PRUnichar* cp = cp0 + offset;
if (isWhitespace) {
while (cp < end) {
PRUnichar ch = *cp;
if (XP_IS_SPACE(ch)) {
cp++;
continue;
}
numChars = (cp - offset) - cp0;
contentLen += numChars;
mCurrentFragOffset += numChars;
goto done;
}
numChars = (cp - offset) - cp0;
contentLen += numChars;
}
else {
while (cp < end) {
PRUnichar ch = *cp;
if (!XP_IS_SPACE(ch)) {
if (CH_NBSP == ch) ch = ' ';
if (ch > MAX_UNIBYTE) mHasMultibyte = PR_TRUE;
cp++;
// Store character in buffer; grow buffer if we have to
*bp++ = ch;
if (bp == bufEnd) {
PRInt32 delta = bp - mBuffer;
if (!GrowBuffer()) {
goto done;
}
bp = mBuffer + delta;
bufEnd = mBuffer + mBufferLength;
}
continue;
}
numChars = (cp - offset) - cp0;
wordLen += numChars;
contentLen += numChars;
mCurrentFragOffset += numChars;
goto done;
}
numChars = (cp - offset) - cp0;
wordLen += numChars;
contentLen += numChars;
}
}
else {
const unsigned char* cp0 = (const unsigned char*) frag->Get1b();
const unsigned char* end = cp0 + fragLen;
const unsigned char* cp = cp0 + offset;
if (isWhitespace) {
while (cp < end) {
PRUnichar ch = PRUnichar(*cp);
if (XP_IS_SPACE(ch)) {
cp++;
continue;
}
numChars = (cp - offset) - cp0;
contentLen += numChars;
mCurrentFragOffset += numChars;
goto done;
}
numChars = (cp - offset) - cp0;
contentLen += numChars;
}
else {
while (cp < end) {
PRUnichar ch = PRUnichar(*cp);
if (!XP_IS_SPACE(ch)) {
if (CH_NBSP == ch) ch = ' ';
if (ch > MAX_UNIBYTE) mHasMultibyte = PR_TRUE;
cp++;
// Store character in buffer; grow buffer if we have to
*bp++ = ch;
if (bp == bufEnd) {
PRInt32 delta = bp - mBuffer;
if (!GrowBuffer()) {
goto done;
}
bp = mBuffer + delta;
bufEnd = mBuffer + mBufferLength;
}
continue;
}
numChars = (cp - offset) - cp0;
wordLen += numChars;
contentLen += numChars;
mCurrentFragOffset += numChars;
goto done;
}
numChars = (cp - offset) - cp0;
wordLen += numChars;
contentLen += numChars;
}
}
// Advance to next text fragment
frag++;
mCurrentFrag = frag;
mCurrentFragOffset = 0;
offset = 0;
}
done:;
mOffset += contentLen;
NS_ASSERTION(mOffset <= mContentLength, "whoops");
aWordLenResult = wordLen;
aContentLenResult = contentLen;
aIsWhitespaceResult = isWhitespace;
return mBuffer;
}
PRUnichar*
nsTextTransformer::GetNextSection(PRInt32& aLineLenResult,
PRInt32& aContentLenResult)
{
NS_PRECONDITION(mOffset <= mContentLength, "bad offset");
// See if the content has been exhausted
if (mOffset == mContentLength) {
aLineLenResult = 0;
aContentLenResult = 0;
return nsnull;
}
PRUnichar* bp = mBuffer;
PRUnichar* bufEnd = mBuffer + mBufferLength;
const nsTextFragment* frag = mCurrentFrag;
const nsTextFragment* lastFrag = frag + mNumFrags;
PRInt32 contentLen = 0;
PRInt32 lineLen = 0;
while (frag < lastFrag) {
PRInt32 fragLen = frag->GetLength();
// Scan characters in the fragment until we run out or we hit a
// newline.
if (frag->Is2b()) {
const PRUnichar* cp0 = frag->Get2b();
const PRUnichar* end = cp0 + fragLen;
const PRUnichar* cp = cp0 + mCurrentFragOffset;
while (cp < end) {
PRUnichar ch = *cp++;
if ('\t' == ch) {
// Keep tabs seperate from other content
if (0 != lineLen) {
goto done;
}
*bp++ = ch;
lineLen++;
contentLen++;
mCurrentFragOffset++;
goto done;
}
else if ('\n' == ch) {
// Keep newlines seperate from other content
if (0 != lineLen) {
goto done;
}
// Include newline in content-len but not in line-len
contentLen++;
mCurrentFragOffset++;
goto done;
}
else if (CH_NBSP == ch) {
ch = ' ';
}
if (ch > MAX_UNIBYTE) mHasMultibyte = PR_TRUE;
*bp++ = ch;
if (bp == bufEnd) {
PRInt32 delta = bp - mBuffer;
if (!GrowBuffer()) {
goto done;
}
bp = mBuffer + delta;
bufEnd = mBuffer + mBufferLength;
}
lineLen++;
contentLen++;
mCurrentFragOffset++;
}
}
else {
const unsigned char* cp0 = (const unsigned char*) frag->Get1b();
const unsigned char* end = cp0 + fragLen;
const unsigned char* cp = cp0 + mCurrentFragOffset;
while (cp < end) {
PRUnichar ch = PRUnichar(*cp++);
if ('\t' == ch) {
// Keep tabs seperate from other content
if (0 != lineLen) {
goto done;
}
*bp++ = ch;
lineLen++;
contentLen++;
mCurrentFragOffset++;
goto done;
}
else if ('\n' == ch) {
// Keep newlines seperate from other content
if (0 != lineLen) {
goto done;
}
// Include newline in content-len but not in line-len
contentLen++;
mCurrentFragOffset++;
goto done;
}
else if (CH_NBSP == ch) {
ch = ' ';
}
if (ch > MAX_UNIBYTE) mHasMultibyte = PR_TRUE;
*bp++ = ch;
if (bp == bufEnd) {
PRInt32 delta = bp - mBuffer;
if (!GrowBuffer()) {
goto done;
}
bp = mBuffer + delta;
bufEnd = mBuffer + mBufferLength;
}
lineLen++;
contentLen++;
mCurrentFragOffset++;
}
}
// Advance to next text fragment
frag++;
mCurrentFrag = frag;
mCurrentFragOffset = 0;
}
done:;
mOffset += contentLen;
NS_ASSERTION(mOffset <= mContentLength, "whoops");
aLineLenResult = lineLen;
aContentLenResult = contentLen;
return mBuffer;
}
PRUnichar*
nsTextTransformer::GetTextAt(PRInt32 aOffset)
{
// XXX
return mBuffer + aOffset;
}

View File

@@ -0,0 +1,138 @@
/* -*- 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.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* 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.
*/
#ifndef nsTextTransformer_h___
#define nsTextTransformer_h___
#include "nsTextFragment.h"
#include "nsISupports.h"
class nsIFrame;
class nsTextRun;
/**
* This object manages the transformation of text:
*
* <UL>
* <LI>whitespace compression
* <LI>capitalization
* <LI>lowercasing
* <LI>uppercasing
* </UL>
*
* Note that no transformations are applied that would impact word
* breaking (like mapping &nbsp; into space, for example). In
* addition, this logic will not strip leading or trailing whitespace
* (across the entire run of text; leading whitespace can be skipped
* for a frames text because of whitespace compression).
*/
class nsTextTransformer {
public:
nsTextTransformer(PRUnichar* aBuffer, PRInt32 aBufLen);
~nsTextTransformer();
/**
* Initialize the text transform. This is when the transformation
* occurs. Subsequent calls to GetTransformedTextFor will just
* return the result of the single transformation.
*/
nsresult Init(/*nsTextRun& aTextRun, XXX*/
nsIFrame* aFrame,
PRInt32 aStartingOffset);
PRInt32 GetContentLength() const {
return mContentLength;
}
PRUnichar* GetNextWord(PRInt32& aWordLenResult,
PRInt32& aContentLenResult,
PRBool& aIsWhitespaceResult);
PRUnichar* GetNextSection(PRInt32& aLineLenResult,
PRInt32& aContentLenResult);
PRBool HasMultibyte() const {
return mHasMultibyte;
}
PRUnichar* GetTextAt(PRInt32 aOffset);
protected:
PRUnichar* mAutoBuffer;
PRInt32 mAutoBufferLength;
PRUnichar* mBuffer;
PRInt32 mBufferLength;
PRBool mHasMultibyte;
PRInt32 mContentLength;
PRInt32 mStartingOffset;
PRInt32 mOffset;
const nsTextFragment* mFrags;
PRInt32 mNumFrags;
const nsTextFragment* mCurrentFrag;
PRInt32 mCurrentFragOffset;
// XXX temporary
PRBool mCompressWS;
PRBool GrowBuffer();
#if 0
// For each piece of content in the text-run we keep track of this
// state.
struct Text {
nsIContent* mContent;
nsTransformedTextFragment* mFrags;
PRInt32 mNumFrags;
Text* mNext;
};
Text* mTextList;
void ReleaseResources();
#endif
// A little state object used to do bookeeping between the low level
// transform calls.
struct TransformerState {
PRBool mSkipLeadingWS;
PRInt32 mContentOffset;
};
nsresult Transform2b(TransformerState& aState,
const nsTextFragment& frag);
nsresult Transform1b(TransformerState& aState,
const nsTextFragment& frag);
nsresult CompressWS2b(TransformerState& aState,
const nsTextFragment& frag);
nsresult CompressWS1b(TransformerState& aState,
const nsTextFragment& frag);
nsresult CompressWSAndTransform2b(TransformerState& aState,
const nsTextFragment& frag);
nsresult CompressWSAndTransform1b(TransformerState& aState,
const nsTextFragment& frag);
};
#endif /* nsTextTransformer_h___ */

View File

@@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* 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.
*/
#ifndef nsTextReflow_h___
#define nsTextReflow_h___
#include "nslayout.h"
#include "nsIFrame.h"
#include "nsVoidArray.h"
class nsIContent;
class nsTextFragment;
// XXX it might be cheaper to have the text-run only contain the
// content pointer instead of the frame pointer
// A run of text. In mText are the nsIFrame's that are considered text
// frames.
class nsTextRun {
public:
nsTextRun();
~nsTextRun();
nsIFrame* FindNextText(nsIFrame* aFrame);
nsTextRun* GetNext() const {
return mNext;
}
void SetNext(nsTextRun* aNext) {
mNext = aNext;
}
PRInt32 Count() const {
return mArray.Count();
}
nsIFrame* operator[](PRInt32 aIndex) const {
return (nsIFrame*) mArray[aIndex];
}
void List(FILE* out, PRInt32 aIndent);
static void DeleteTextRuns(nsTextRun* aRun) {
while (nsnull != aRun) {
nsTextRun* next = aRun->GetNext();
delete aRun;
aRun = next;
}
}
protected:
nsVoidArray mArray;
nsTextRun* mNext;
// XXX get rid of this
friend class nsLineLayout;
};
#endif /* nsTextReflow_h___ */

View File

@@ -0,0 +1,442 @@
/* -*- 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.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* 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.
*/
#include "nsTextTransformer.h"
#include "nsIContent.h"
#include "nsIFrame.h"
#include "nsIStyleContext.h"
#include "nsITextContent.h"
#include "nsStyleConsts.h"
// XXX put a copy in nsHTMLIIDs
static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);
// XXX temporary
#define XP_IS_SPACE(_ch) \
(((_ch) == ' ') || ((_ch) == '\t') || ((_ch) == '\n'))
// XXX need more of this in nsIRenderingContext.GetWidth
#define CH_NBSP 160
#define MAX_UNIBYTE 127
nsTextTransformer::nsTextTransformer(PRUnichar* aBuffer, PRInt32 aBufLen)
: mAutoBuffer(aBuffer),
mBuffer(aBuffer),
mBufferLength(aBufLen < 0 ? 0 : aBufLen),
mHasMultibyte(PR_FALSE)
{
}
nsTextTransformer::~nsTextTransformer()
{
if (mBuffer != mAutoBuffer) {
delete [] mBuffer;
}
}
nsresult
nsTextTransformer::Init(/*nsTextRun& aTextRun, XXX*/
nsIFrame* aFrame,
PRInt32 aStartingOffset)
{
// Make sure we have *some* space in case arguments to the ctor were
// bizzare.
if (mBufferLength < 100) {
if (!GrowBuffer()) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
// Get the frames text content
nsIContent* content;
aFrame->GetContent(content);
nsITextContent* tc;
if (NS_OK != content->QueryInterface(kITextContentIID, (void**) &tc)) {
NS_RELEASE(content);
return NS_OK;
}
tc->GetText(mFrags, mNumFrags);
NS_RELEASE(tc);
NS_RELEASE(content);
mStartingOffset = aStartingOffset;
mOffset = mStartingOffset;
// Compute the total length of the text content.
PRInt32 sum = 0;
PRInt32 n = mNumFrags;
const nsTextFragment* frag = mFrags;
for (; --n >= 0; frag++) {
sum += frag->GetLength();
}
mContentLength = sum;
// Set current fragment and current fragment offset
mCurrentFrag = mFrags;
mCurrentFragOffset = 0;
PRInt32 offset = 0;
n = mNumFrags;
for (frag = mFrags; --n >= 0; frag++) {
if (aStartingOffset < offset + frag->GetLength()) {
mCurrentFrag = frag;
mCurrentFragOffset = aStartingOffset - offset;
break;
}
offset += frag->GetLength();
}
// Get the frames style and choose a transform proc
const nsStyleText* styleText;
aFrame->GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&) styleText);
mCompressWS = NS_STYLE_WHITESPACE_PRE != styleText->mWhiteSpace;
return NS_OK;
}
PRBool
nsTextTransformer::GrowBuffer()
{
PRInt32 newLen = mBufferLength * 2;
if (newLen <= 100) {
newLen = 100;
}
PRUnichar* newBuffer = new PRUnichar[newLen];
if (nsnull == newBuffer) {
return PR_FALSE;
}
if (0 != mBufferLength) {
nsCRT::memcpy(newBuffer, mBuffer, sizeof(PRUnichar) * mBufferLength);
if (mBuffer != mAutoBuffer) {
delete [] mBuffer;
}
}
mBuffer = newBuffer;
return PR_TRUE;
}
PRUnichar*
nsTextTransformer::GetNextWord(PRInt32& aWordLenResult,
PRInt32& aContentLenResult,
PRBool& aIsWhitespaceResult)
{
NS_PRECONDITION(mOffset <= mContentLength, "bad offset");
// See if the content has been exhausted
if (mOffset == mContentLength) {
aWordLenResult = 0;
aContentLenResult = 0;
return nsnull;
}
PRUnichar* bp = mBuffer;
PRUnichar* bufEnd = mBuffer + mBufferLength;
const nsTextFragment* frag = mCurrentFrag;
const nsTextFragment* lastFrag = frag + mNumFrags;
// Set the isWhitespace flag by examining the next character in the
// text fragment.
PRInt32 offset = mCurrentFragOffset;
PRUnichar firstChar;
if (frag->Is2b()) {
const PRUnichar* up = frag->Get2b();
firstChar = up[offset];
}
else {
const unsigned char* cp = (const unsigned char*) frag->Get1b();
firstChar = PRUnichar(cp[offset]);
}
PRBool isWhitespace = XP_IS_SPACE(firstChar);
offset++;
if (isWhitespace || (CH_NBSP == firstChar)) {
*bp++ = ' ';
}
else {
*bp++ = firstChar;
}
PRInt32 contentLen = 1;
PRInt32 wordLen = 1;
if (offset == frag->GetLength()) {
mCurrentFrag = ++frag;
offset = 0;
}
mCurrentFragOffset = offset;
// XXX here is where we switch out to type specific handlers; this
// code assumes mCompressWS is PR_TRUE
// Now that we know what we are looking for, scan through the text
// content and find the end of it.
PRInt32 numChars;
while (frag < lastFrag) {
PRInt32 fragLen = frag->GetLength();
// Scan characters in this fragment that are the same kind as the
// isWhitespace flag indicates.
if (frag->Is2b()) {
const PRUnichar* cp0 = frag->Get2b();
const PRUnichar* end = cp0 + fragLen;
const PRUnichar* cp = cp0 + offset;
if (isWhitespace) {
while (cp < end) {
PRUnichar ch = *cp;
if (XP_IS_SPACE(ch)) {
cp++;
continue;
}
numChars = (cp - offset) - cp0;
contentLen += numChars;
mCurrentFragOffset += numChars;
goto done;
}
numChars = (cp - offset) - cp0;
contentLen += numChars;
}
else {
while (cp < end) {
PRUnichar ch = *cp;
if (!XP_IS_SPACE(ch)) {
if (CH_NBSP == ch) ch = ' ';
if (ch > MAX_UNIBYTE) mHasMultibyte = PR_TRUE;
cp++;
// Store character in buffer; grow buffer if we have to
*bp++ = ch;
if (bp == bufEnd) {
PRInt32 delta = bp - mBuffer;
if (!GrowBuffer()) {
goto done;
}
bp = mBuffer + delta;
bufEnd = mBuffer + mBufferLength;
}
continue;
}
numChars = (cp - offset) - cp0;
wordLen += numChars;
contentLen += numChars;
mCurrentFragOffset += numChars;
goto done;
}
numChars = (cp - offset) - cp0;
wordLen += numChars;
contentLen += numChars;
}
}
else {
const unsigned char* cp0 = (const unsigned char*) frag->Get1b();
const unsigned char* end = cp0 + fragLen;
const unsigned char* cp = cp0 + offset;
if (isWhitespace) {
while (cp < end) {
PRUnichar ch = PRUnichar(*cp);
if (XP_IS_SPACE(ch)) {
cp++;
continue;
}
numChars = (cp - offset) - cp0;
contentLen += numChars;
mCurrentFragOffset += numChars;
goto done;
}
numChars = (cp - offset) - cp0;
contentLen += numChars;
}
else {
while (cp < end) {
PRUnichar ch = PRUnichar(*cp);
if (!XP_IS_SPACE(ch)) {
if (CH_NBSP == ch) ch = ' ';
if (ch > MAX_UNIBYTE) mHasMultibyte = PR_TRUE;
cp++;
// Store character in buffer; grow buffer if we have to
*bp++ = ch;
if (bp == bufEnd) {
PRInt32 delta = bp - mBuffer;
if (!GrowBuffer()) {
goto done;
}
bp = mBuffer + delta;
bufEnd = mBuffer + mBufferLength;
}
continue;
}
numChars = (cp - offset) - cp0;
wordLen += numChars;
contentLen += numChars;
mCurrentFragOffset += numChars;
goto done;
}
numChars = (cp - offset) - cp0;
wordLen += numChars;
contentLen += numChars;
}
}
// Advance to next text fragment
frag++;
mCurrentFrag = frag;
mCurrentFragOffset = 0;
offset = 0;
}
done:;
mOffset += contentLen;
NS_ASSERTION(mOffset <= mContentLength, "whoops");
aWordLenResult = wordLen;
aContentLenResult = contentLen;
aIsWhitespaceResult = isWhitespace;
return mBuffer;
}
PRUnichar*
nsTextTransformer::GetNextSection(PRInt32& aLineLenResult,
PRInt32& aContentLenResult)
{
NS_PRECONDITION(mOffset <= mContentLength, "bad offset");
// See if the content has been exhausted
if (mOffset == mContentLength) {
aLineLenResult = 0;
aContentLenResult = 0;
return nsnull;
}
PRUnichar* bp = mBuffer;
PRUnichar* bufEnd = mBuffer + mBufferLength;
const nsTextFragment* frag = mCurrentFrag;
const nsTextFragment* lastFrag = frag + mNumFrags;
PRInt32 contentLen = 0;
PRInt32 lineLen = 0;
while (frag < lastFrag) {
PRInt32 fragLen = frag->GetLength();
// Scan characters in the fragment until we run out or we hit a
// newline.
if (frag->Is2b()) {
const PRUnichar* cp0 = frag->Get2b();
const PRUnichar* end = cp0 + fragLen;
const PRUnichar* cp = cp0 + mCurrentFragOffset;
while (cp < end) {
PRUnichar ch = *cp++;
if ('\t' == ch) {
// Keep tabs seperate from other content
if (0 != lineLen) {
goto done;
}
*bp++ = ch;
lineLen++;
contentLen++;
mCurrentFragOffset++;
goto done;
}
else if ('\n' == ch) {
// Keep newlines seperate from other content
if (0 != lineLen) {
goto done;
}
// Include newline in content-len but not in line-len
contentLen++;
mCurrentFragOffset++;
goto done;
}
else if (CH_NBSP == ch) {
ch = ' ';
}
if (ch > MAX_UNIBYTE) mHasMultibyte = PR_TRUE;
*bp++ = ch;
if (bp == bufEnd) {
PRInt32 delta = bp - mBuffer;
if (!GrowBuffer()) {
goto done;
}
bp = mBuffer + delta;
bufEnd = mBuffer + mBufferLength;
}
lineLen++;
contentLen++;
mCurrentFragOffset++;
}
}
else {
const unsigned char* cp0 = (const unsigned char*) frag->Get1b();
const unsigned char* end = cp0 + fragLen;
const unsigned char* cp = cp0 + mCurrentFragOffset;
while (cp < end) {
PRUnichar ch = PRUnichar(*cp++);
if ('\t' == ch) {
// Keep tabs seperate from other content
if (0 != lineLen) {
goto done;
}
*bp++ = ch;
lineLen++;
contentLen++;
mCurrentFragOffset++;
goto done;
}
else if ('\n' == ch) {
// Keep newlines seperate from other content
if (0 != lineLen) {
goto done;
}
// Include newline in content-len but not in line-len
contentLen++;
mCurrentFragOffset++;
goto done;
}
else if (CH_NBSP == ch) {
ch = ' ';
}
if (ch > MAX_UNIBYTE) mHasMultibyte = PR_TRUE;
*bp++ = ch;
if (bp == bufEnd) {
PRInt32 delta = bp - mBuffer;
if (!GrowBuffer()) {
goto done;
}
bp = mBuffer + delta;
bufEnd = mBuffer + mBufferLength;
}
lineLen++;
contentLen++;
mCurrentFragOffset++;
}
}
// Advance to next text fragment
frag++;
mCurrentFrag = frag;
mCurrentFragOffset = 0;
}
done:;
mOffset += contentLen;
NS_ASSERTION(mOffset <= mContentLength, "whoops");
aLineLenResult = lineLen;
aContentLenResult = contentLen;
return mBuffer;
}
PRUnichar*
nsTextTransformer::GetTextAt(PRInt32 aOffset)
{
// XXX
return mBuffer + aOffset;
}

View File

@@ -0,0 +1,138 @@
/* -*- 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.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* 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.
*/
#ifndef nsTextTransformer_h___
#define nsTextTransformer_h___
#include "nsTextFragment.h"
#include "nsISupports.h"
class nsIFrame;
class nsTextRun;
/**
* This object manages the transformation of text:
*
* <UL>
* <LI>whitespace compression
* <LI>capitalization
* <LI>lowercasing
* <LI>uppercasing
* </UL>
*
* Note that no transformations are applied that would impact word
* breaking (like mapping &nbsp; into space, for example). In
* addition, this logic will not strip leading or trailing whitespace
* (across the entire run of text; leading whitespace can be skipped
* for a frames text because of whitespace compression).
*/
class nsTextTransformer {
public:
nsTextTransformer(PRUnichar* aBuffer, PRInt32 aBufLen);
~nsTextTransformer();
/**
* Initialize the text transform. This is when the transformation
* occurs. Subsequent calls to GetTransformedTextFor will just
* return the result of the single transformation.
*/
nsresult Init(/*nsTextRun& aTextRun, XXX*/
nsIFrame* aFrame,
PRInt32 aStartingOffset);
PRInt32 GetContentLength() const {
return mContentLength;
}
PRUnichar* GetNextWord(PRInt32& aWordLenResult,
PRInt32& aContentLenResult,
PRBool& aIsWhitespaceResult);
PRUnichar* GetNextSection(PRInt32& aLineLenResult,
PRInt32& aContentLenResult);
PRBool HasMultibyte() const {
return mHasMultibyte;
}
PRUnichar* GetTextAt(PRInt32 aOffset);
protected:
PRUnichar* mAutoBuffer;
PRInt32 mAutoBufferLength;
PRUnichar* mBuffer;
PRInt32 mBufferLength;
PRBool mHasMultibyte;
PRInt32 mContentLength;
PRInt32 mStartingOffset;
PRInt32 mOffset;
const nsTextFragment* mFrags;
PRInt32 mNumFrags;
const nsTextFragment* mCurrentFrag;
PRInt32 mCurrentFragOffset;
// XXX temporary
PRBool mCompressWS;
PRBool GrowBuffer();
#if 0
// For each piece of content in the text-run we keep track of this
// state.
struct Text {
nsIContent* mContent;
nsTransformedTextFragment* mFrags;
PRInt32 mNumFrags;
Text* mNext;
};
Text* mTextList;
void ReleaseResources();
#endif
// A little state object used to do bookeeping between the low level
// transform calls.
struct TransformerState {
PRBool mSkipLeadingWS;
PRInt32 mContentOffset;
};
nsresult Transform2b(TransformerState& aState,
const nsTextFragment& frag);
nsresult Transform1b(TransformerState& aState,
const nsTextFragment& frag);
nsresult CompressWS2b(TransformerState& aState,
const nsTextFragment& frag);
nsresult CompressWS1b(TransformerState& aState,
const nsTextFragment& frag);
nsresult CompressWSAndTransform2b(TransformerState& aState,
const nsTextFragment& frag);
nsresult CompressWSAndTransform1b(TransformerState& aState,
const nsTextFragment& frag);
};
#endif /* nsTextTransformer_h___ */