// Revision: 70 1.47.1.8 source/core/text/itext/itext.hpp, text, ioc.v400, 001006 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// IText.h
//
// Contains IText, the variable-length styled Unicode text-storage object.
//
// IBM Open Class Library
// (C) Copyright International Business Machines Corporation 1997
// Licensed Material - Program-Property of IBM - All Rights Reserved.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#ifndef _ITEXT_
#define _ITEXT_

#include <itxtstyl.hpp>
#include <iprimtyp.hpp>

// [itxtiter.hpp is also included at the end of the file.]

#include <stddef.h>
#include <iostream.h>
#include <ctype.h>

#ifdef IC_BUILD
#define __IOC_INLINE
#else
#define __IOC_INLINE inline
#endif

#if __IBMCPP__ >= 400
#pragma namemangling(compat)
#endif

class IString;
class ITextStorage;
class IDataStream;
class ITextStyleSet;
class istream;

class ICharacterReference;
class ITextIterator;
class IConstTextIterator;
// NOTE: I'm not real nuts on having to nail down here just what I mean by
// IReverseTextIterator and IReverseConstTextIterator, but it can't be avoided,
// and multiple typedefs that are consistent are apparently allowed.
template <class ARealIterator, class AReturnType> class IReverseIterator;
typedef IReverseIterator<ITextIterator, ICharacterReference> IReverseTextIterator;
typedef IReverseIterator<IConstTextIterator, UniChar> IReverseConstTextIterator;

#pragma pack(push,4)
#pragma enum(4)

//========================================================================================
// CLASS IText
// Variable length styled Unicode text storage object.
//========================================================================================
class IText {
public:
    //--------------------------------------------------------------
    // Typedefs and constant definitions
    //--------------------------------------------------------------
    typedef size_t length_type; // not ANSI
    typedef size_t offset_type; // not ANSI
    static const length_type _IMPORT npos;
    
    //--------------------------------------------------------------
    // Lazy evaluation access methods
    //--------------------------------------------------------------
    static const IText& emptyText();
    
    //--------------------------------------------------------------
    // Constructors and destructor
    //--------------------------------------------------------------
    
    IText();
    IText( const IText& that);
    IText( const IText& that,
           offset_type thatPos,
           length_type thatLength);
    IText( const UniChar that[],
           length_type thatLength);
    IText( const UniChar* that);
    IText( length_type thatCopies,
           UniChar that);
    IText( ITextIterator thatFrom,
           ITextIterator thatTo);
    IText( UniChar that); // not ANSI
    IText( const char* that); // not ANSI
    IText( const IString& that); // not ANSI
    
    ~IText();
    
    //--------------------------------------------------------------
    // Assignment
    //--------------------------------------------------------------
    
    IText& operator=(const IText& that);
    IText& operator=(const UniChar* that);
    IText& operator=(UniChar that);
    
    IText& assign( const IText& that);
    IText& assign( const IText& that,
                   offset_type thatPos,
                   length_type thatLength);
    IText& assign( const UniChar that[],
                   length_type thatLength);
    IText& assign( const UniChar* that);
    IText& assign( length_type thatCopies,
                   UniChar that);
    IText& assign( ITextIterator thatFrom,
                   ITextIterator thatTo);
    
    //--------------------------------------------------------------
    // Conversion operators
    //--------------------------------------------------------------
    
    operator const char*() const; // not ANSI
    // operator IString() const; // not ANSI
    operator const UniChar*() const; // not ANSI
    
    //--------------------------------------------------------------
    // Streaming
    //--------------------------------------------------------------
    
    void operator>>=(IDataStream& toWhere) const; // not ANSI
    void operator<<=(IDataStream& fromWhere); // not ANSI
    
    //--------------------------------------------------------------
    // Size/capacity/internal storage
    //--------------------------------------------------------------
    
    length_type size() const;
    length_type length() const;
    length_type max_size() const;
    void resize( length_type numChars,
                 UniChar fillChar);
    void resize( length_type numChars);
    length_type capacity() const;
    void reserve(length_type numChars);
    bool empty() const;
    
    const UniChar* c_str() const;
    const UniChar* data() const;
    
    const UniChar* storage_chunk( offset_type searchPos,
                                  offset_type& chunkPos,
                                  length_type& chunkLength) const; // not ANSI
    
    //--------------------------------------------------------------
    // Iterators
    //--------------------------------------------------------------
    
    ITextIterator begin();
    IConstTextIterator begin() const;
    ITextIterator end();
    IConstTextIterator end() const;
    IReverseTextIterator rbegin();
    IReverseConstTextIterator rbegin() const;
    IReverseTextIterator rend();
    IReverseConstTextIterator  rend() const;
    
    //--------------------------------------------------------------
    // Character access
    //--------------------------------------------------------------
    
    UniChar operator[]( offset_type pos) const;
    ICharacterReference operator[]( offset_type pos);
    
    UniChar at( offset_type pos) const;
    ICharacterReference at( offset_type pos);
    
    void at_put( offset_type pos,
                 UniChar newChar); // not ANSI
    
    //--------------------------------------------------------------
    // Substring extraction
    //--------------------------------------------------------------
    
    IText substr( offset_type pos = 0,
                  length_type length = npos) const;
    
    //--------------------------------------------------------------
    // Appending
    //--------------------------------------------------------------
    
    IText& operator+=( const IText& that);
    IText& operator+=( const UniChar* that);
    IText& operator+=( UniChar that);
    
    IText& append( const IText& that);
    IText& append( const IText& that,
                   offset_type thatPos,
                   length_type thatLength);
    IText& append( const UniChar that[],
                   length_type thatLength);
    IText& append( const UniChar* that);
    IText& append( length_type thatCopies,
                   UniChar that);
    IText& append( ITextIterator thatFrom,
                   ITextIterator thatTo);
    
    //--------------------------------------------------------------
    // Insertion
    //--------------------------------------------------------------
    
    IText& insert( offset_type insertPos,
                   const IText& that);
    IText& insert( offset_type insertPos,
                   const IText& that,
                   offset_type thatPos,
                   length_type thatLength);
    IText& insert( offset_type insertPos,
                   const UniChar that[],
                   length_type thatLength);
    IText& insert( offset_type insertPos,
                   const UniChar* that);
    IText& insert( offset_type insertPos,
                   length_type thatCopies,
                   UniChar that);
    ITextIterator insert( ITextIterator insertPos,
                          UniChar that);
    void insert( ITextIterator insertPos,
                 length_type thatCopies,
                 UniChar that);
    void insert( ITextIterator insertPos,
                 ITextIterator thatFrom,
                 ITextIterator thatTo);
    
    IText& insert_and_propagate_styles( offset_type insertPos,
                                        const UniChar that[],
                                        length_type thatLength);
    IText& insert_and_propagate_styles( offset_type insertPos,
                                        length_type thatCopies,
                                        UniChar that);
    
    //--------------------------------------------------------------
    // Deletion
    //--------------------------------------------------------------
    
    IText& erase( offset_type pos = 0,
                  length_type numChars = npos);
    ITextIterator erase( ITextIterator pos);
    ITextIterator erase( ITextIterator from,
                         ITextIterator to);
    
    //--------------------------------------------------------------
    // Replacement
    //--------------------------------------------------------------
    
    IText& replace( offset_type thisPos,
                    length_type thisLength,
                    const IText& that);
    IText& replace( offset_type thisPos,
                    length_type thisLength,
                    const IText& that,
                    offset_type thatPos,
                    length_type thatLength);
    IText& replace( offset_type thisPos,
                    length_type thisLength,
                    const UniChar that[],
                    length_type thatLength);
    IText& replace( offset_type thisPos,
                    length_type thisLength,
                    const UniChar* that);
    IText& replace( offset_type thisPos,
                    length_type thisLength,
                    length_type thatCopies,
                    UniChar that);
    IText& replace( ITextIterator thisFrom,
                    ITextIterator thisTo,
                    const IText& that);
    IText& replace( ITextIterator thisFrom,
                    ITextIterator thisTo,
                    const UniChar that[],
                    length_type thatLength);
    IText& replace( ITextIterator thisFrom,
                    ITextIterator thisTo,
                    const UniChar* that);
    IText& replace( ITextIterator thisFrom,
                    ITextIterator thisTo,
                    length_type thatCopies,
                    UniChar that);
    IText& replace( ITextIterator thisFrom,
                    ITextIterator thisTo,
                    ITextIterator thatFrom,
                    ITextIterator thatTo);
    
    //--------------------------------------------------------------
    // Comparison
    //--------------------------------------------------------------
    
    int compare( const IText& that) const;
    int compare( offset_type thisPos,
                 length_type thisLength,
                 const IText& that) const;
    int compare( offset_type thisPos,
                 length_type thisLength,
                 const IText& that,
                 offset_type thatPos,
                 length_type thatLength) const;
    int compare( const UniChar* that) const;
    int compare( offset_type thisPos,
                 length_type thisLength,
                 const UniChar that[],
                 length_type thatLength) const;
    
    long hash() const; // not ANSI
    
    //--------------------------------------------------------------
    // Miscellaneous
    //--------------------------------------------------------------
    
    length_type copy( UniChar that[],
                      length_type maxChars,
                      offset_type startPos = 0) const;
    
    void swap( IText& that);
    
    //--------------------------------------------------------------
    // Searching
    //--------------------------------------------------------------
    
    offset_type find( const IText& key,
                      offset_type startPos = 0) const;
    offset_type find( const UniChar key[],
                      offset_type startPos,
                      length_type keyLength) const;
    offset_type find( const UniChar* key,
                      offset_type startPos = 0) const;
    offset_type find( UniChar key,
                      offset_type startPos = 0) const;
    
    offset_type rfind( const IText& key,
                       offset_type startPos = npos) const;
    offset_type rfind( const UniChar key[],
                       offset_type startPos,
                       length_type keyLength) const;
    offset_type rfind( const UniChar* key,
                       offset_type startPos = npos) const;
    offset_type rfind( UniChar key,
                       offset_type startPos = npos) const;
    
    offset_type find_first_of( const IText& keys,
                               offset_type startPos = 0) const;
    offset_type find_first_of( const UniChar keys[],
                               offset_type startPos,
                               length_type numKeys) const;
    offset_type find_first_of( const UniChar* keys,
                               offset_type startPos = 0) const;
    offset_type find_first_of( UniChar key,
                               offset_type startPos = 0) const;
    
    offset_type find_last_of( const IText& keys,
                              offset_type startPos = npos) const;
    offset_type find_last_of( const UniChar keys[],
                              offset_type startPos,
                              length_type numKeys) const;
    offset_type find_last_of( const UniChar* keys,
                              offset_type startPos = npos) const;
    offset_type find_last_of( UniChar key,
                              offset_type startPos = npos) const;
    
    offset_type find_first_not_of( const IText& keys,
                                   offset_type startPos = 0) const;
    offset_type find_first_not_of( const UniChar keys[],
                                   offset_type startPos,
                                   length_type numKeys) const;
    offset_type find_first_not_of( const UniChar* keys,
                                   offset_type startPos = 0) const;
    offset_type find_first_not_of( UniChar key,
                                   offset_type startPos = 0) const;
    
    offset_type find_last_not_of( const IText& keys,
                                  offset_type startPos = npos) const;
    offset_type find_last_not_of( const UniChar keys[],
                                  offset_type startPos,
                                  length_type numKeys) const;
    offset_type find_last_not_of( const UniChar* keys,
                                  offset_type startPos = npos) const;
    offset_type find_last_not_of( UniChar key,
                                  offset_type startPos = npos) const;
    
    //--------------------------------------------------------------
    // Adding and removing styles
    //--------------------------------------------------------------
    
    void addStyles( const ITextStyle& style,
                    offset_type starting = 0,
                    length_type count = npos); // not ANSI
    void addStyles( const ITextStyleSet& styles,
                    offset_type starting = 0,
                    length_type count = npos); // not ANSI
    
    void removeStyles( const ITextStyle& style,
                       offset_type starting = 0,
                       length_type count = npos); // not ANSI
    void removeStyles( const ITextStyleSet& styles,
                       offset_type starting = 0,
                       length_type count = npos); // not ANSI
    void removeStyles( offset_type starting = 0,
                       length_type count = npos); // not ANSI
    
    //--------------------------------------------------------------
    // Getting style information
    //--------------------------------------------------------------
    
    const ITextStyleSet*
    stylesAt( offset_type position,
              offset_type& starting,
              length_type& count) const; // not ANSI
    void stylesAt( offset_type position,
                   ITextStyleSet& set,
                   offset_type& starting,
                   length_type& count,
                   ITextStyle::EStylePropagation propagationToMatch
                   = ITextStyle::kMaximumPropagation) const; // not ANSI
    
    bool maximumStyleSpan( offset_type position,
                           const ITextStyle& style,
                           offset_type& starting,
                           length_type& count) const; // not ANSI
    bool maximumStyleSpan( offset_type position,
                           const ITextStyleSet& set,
                           offset_type& starting,
                           length_type& count) const; // not ANSI
    
    bool continuousStylesOver( offset_type starting,
                               length_type count,
                               ITextStyleSet& styles) const; // not ANSI
    bool continuousStylesOver( offset_type starting,
                               length_type count,
                               ITextStyleSet& styles,
                               ITextStyle::EStylePropagation propagationToMatch) const; // not ANSI
    
    bool isStyled() const; // not ANSI
    
    bool sameStyledText(const IText& other) const; // not ANSI
    bool sameCharacters(const IText& other) const; // not ANSI
    
    //--------------------------------------------------------------
    // Debugging
    //--------------------------------------------------------------
    
    void printDebugInfo() const; // not ANSI
    
private:
    IText( ITextStorage* storage);
    void writeToStream(IDataStream& toWhere) const;
    void readFromStream(IDataStream& fromWhere);
    
    ITextStorage* fStorage;
    
    friend class ITextStorage;
    friend class IStyleStorage;
    friend class IFastTextIterator;
};

#pragma enum(pop)
#pragma pack(pop)

//========================================================================================
// NON-MEMBER FUNCTIONS ON ITEXT
//========================================================================================

//--------------------------------------------------------------
// Concatenation
//--------------------------------------------------------------

IText operator+( const IText& a, const IText& b);
IText operator+( const UniChar* a, const IText& b);
IText operator+( UniChar a, const IText& b);
IText operator+( const IText& a, const UniChar* b);
IText operator+( const IText& a, UniChar b);

//--------------------------------------------------------------
// Comparison
//--------------------------------------------------------------

bool operator==( const IText& a, const IText& b);
bool operator==( const UniChar* a, const IText& b);
bool operator==( const IText& a, const UniChar* b);

bool operator!=( const IText& a, const IText& b);
bool operator!=( const UniChar* a, const IText& b);
bool operator!=( const IText& a, const UniChar* b);

bool operator<( const IText& a,
                const IText& b);
bool operator<( const UniChar* a,
                const IText& b);
bool operator<( const IText& a,
                const UniChar* b);

bool operator>( const IText& a,
                const IText& b);
bool operator>( const UniChar* a,
                const IText& b);
bool operator>( const IText& a,
                const UniChar* b);

bool operator<=( const IText& a,
                 const IText& b);
bool operator<=( const UniChar* a,
                 const IText& b);
bool operator<=( const IText& a,
                 const UniChar* b);

bool operator>=( const IText& a,
                 const IText& b);
bool operator>=( const UniChar* a,
                 const IText& b);
bool operator>=( const IText& a,
                 const UniChar* b);
//--------------------------------------------------------------
// Miscellaneous
//--------------------------------------------------------------

void swap( IText& a,
           IText& b);

//--------------------------------------------------------------
// Console I/O
//--------------------------------------------------------------

__IOC_INLINE 
ostream& operator<<(ostream& stream, const IText& text);

__IOC_INLINE
istream& operator>>(istream& stream, IText& text);

__IOC_INLINE
istream& getline(istream& stream, IText& text, char delimiter = '\n');

#if __IBMCPP__ >= 400
#pragma namemangling()
#endif

// This include is here only for the convenience of the client programmer. itxtiter.hpp
// is not actually needed by itext.hpp itself. It's included here at the end of the file
// because itxtiter.inl, which is included by itxtiter.hpp, needs to see the definition
// of IText in order to compile.

#include <itxtiter.hpp>

#include <itext.inl>

#endif // _ITEXT_
