/* -*- 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 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.
*
* Contributor(s):
*/
#ifndef nsTextTransformer_h___
#define nsTextTransformer_h___
#include "nsTextFragment.h"
#include "nsISupports.h"
class nsIContent;
class nsIFrame;
class nsTextRun;
class nsILineBreaker;
class nsIWordBreaker;
// XXX I'm sure there are other special characters
#define CH_NBSP 160
#define CH_SHY 173
#define NS_TEXT_TRANSFORMER_AUTO_WORD_BUF_SIZE 100
// A growable text buffer that tries to avoid using malloc by having a
// builtin buffer. Ideally used as an automatic variable.
class nsAutoTextBuffer {
public:
nsAutoTextBuffer();
~nsAutoTextBuffer();
nsresult GrowBy(PRInt32 aAtLeast, PRBool aCopyToHead = PR_TRUE);
nsresult GrowTo(PRInt32 aNewSize, PRBool aCopyToHead = PR_TRUE);
PRUnichar* GetBuffer() { return mBuffer; }
PRUnichar* GetBufferEnd() { return mBuffer + mBufferLen; }
PRInt32 GetBufferLength() const { return mBufferLen; }
PRUnichar* mBuffer;
PRInt32 mBufferLen;
PRUnichar mAutoBuffer[NS_TEXT_TRANSFORMER_AUTO_WORD_BUF_SIZE];
};
//----------------------------------------
/**
* This object manages the transformation of text:
*
*
* - whitespace compression
*
- capitalization
*
- lowercasing
*
- uppercasing
*
*
* Note that no transformations are applied that would impact word
* breaking (like mapping 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:
// Note: The text transformer does not hold a reference to the line
// breaker and work breaker objects
nsTextTransformer(nsILineBreaker* aLineBreaker,
nsIWordBreaker* aWordBreaker);
~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(nsIFrame* aFrame,
nsIContent* aContent,
PRInt32 aStartingOffset);
PRInt32 GetContentLength() const {
return mFrag ? mFrag->GetLength() : 0;
}
PRUnichar* GetNextWord(PRBool aInWord,
PRInt32* aWordLenResult,
PRInt32* aContentLenResult,
PRBool* aIsWhitespaceResult,
PRBool aForLineBreak = PR_TRUE);
PRUnichar* GetPrevWord(PRBool aInWord,
PRInt32* aWordLenResult,
PRInt32* aContentLenResult,
PRBool* aIsWhitespaceResult,
PRBool aForLineBreak = PR_TRUE);
PRBool HasMultibyte() const {
return mHasMultibyte;
}
PRUnichar* GetWordBuffer() {
return mTransformBuf.GetBuffer();
}
PRInt32 GetWordBufferLength() const {
return mTransformBuf.GetBufferLength();
}
static nsresult Initialize();
static void Shutdown();
protected:
// Helper methods for GetNextWord (F == forwards)
PRInt32 ScanNormalWhiteSpace_F();
PRInt32 ScanNormalAsciiText_F(PRInt32* aWordLen);
PRInt32 ScanNormalUnicodeText_F(PRBool aForLineBreak, PRInt32* aWordLen);
PRInt32 ScanPreWrapWhiteSpace_F(PRInt32* aWordLen);
PRInt32 ScanPreAsciiData_F(PRInt32* aWordLen);
PRInt32 ScanPreData_F(PRInt32* aWordLen);
// Helper methods for GetPrevWord (B == backwards)
PRInt32 ScanNormalWhiteSpace_B();
PRInt32 ScanNormalAsciiText_B(PRInt32* aWordLen);
PRInt32 ScanNormalUnicodeText_B(PRBool aForLineBreak, PRInt32* aWordLen);
PRInt32 ScanPreWrapWhiteSpace_B(PRInt32* aWordLen);
PRInt32 ScanPreData_B(PRInt32* aWordLen);
// Set to true if at any point during GetNextWord or GetPrevWord we
// run across a multibyte (> 127) unicode character.
PRBool mHasMultibyte;
// The text fragment that we are looking at
const nsTextFragment* mFrag;
// Our current offset into the text fragment
PRInt32 mOffset;
// The frame's text-transform state
PRUint8 mTextTransform;
// The frame's white-space mode we are using to process text
enum {
eNormal,
ePreformatted,
ePreWrap
} mMode;
nsILineBreaker* mLineBreaker; // [WEAK]
nsIWordBreaker* mWordBreaker; // [WEAK]
// Buffer used to hold the transformed words from GetNextWord or
// GetPrevWord
nsAutoTextBuffer mTransformBuf;
#ifdef DEBUG
static void SelfTest(nsILineBreaker* aLineBreaker,
nsIWordBreaker* aWordBreaker);
nsresult Init2(const nsTextFragment* aFrag,
PRInt32 aStartingOffset,
PRUint8 aWhiteSpace,
PRUint8 aTextTransform);
#endif
};
#endif /* nsTextTransformer_h___ */