sl@0: /* sl@0: * Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * sl@0: */ sl@0: sl@0: sl@0: #include sl@0: #include sl@0: sl@0: #include "FLDSET.H" sl@0: #include "FLDDEF.H" sl@0: #include "FLDARRAY.H" sl@0: #include "FLDSTD.H" sl@0: sl@0: sl@0: EXPORT_C void CTextFieldSet::__DbgTestInvariant()const sl@0: // Provides class invariants. Explanations below: sl@0: // sl@0: { sl@0: #ifdef _DEBUG sl@0: if (!iFieldArray) sl@0: return; sl@0: // check that every entry in the array has length >=0 and that all but the last have valid header handles sl@0: TBool valid = ETrue; sl@0: TInt index = iFieldArray->Count()-1; sl@0: if (index<0) sl@0: valid = EFalse; sl@0: else sl@0: {// check last entry: should have null fieldHeader, zero field length and non-negative PreFieldLen sl@0: if ( (*iFieldArray)[index].iFieldHeader.iField sl@0: ||(*iFieldArray)[index].iFieldValueLen!=0 sl@0: ||(*iFieldArray)[index].iPreFieldLen<0 ) sl@0: { sl@0: valid = EFalse; sl@0: } sl@0: index--; sl@0: // check the other entries: should have non-null fieldHeader and non-negative field length and PreFieldLen sl@0: for (; (index>=0)&&(valid) ; index--) sl@0: { sl@0: if ((*iFieldArray)[index].iFieldValueLen<0 sl@0: ||(*iFieldArray)[index].iPreFieldLen<0 ) sl@0: { sl@0: valid = EFalse; sl@0: } sl@0: } sl@0: } sl@0: __ASSERT_ALWAYS(valid,User::Invariant()); sl@0: #endif sl@0: } sl@0: sl@0: sl@0: EXPORT_C CTextFieldSet* CTextFieldSet::NewL(TInt aDocumentLength) sl@0: { sl@0: CTextFieldSet* self=new(ELeave) CTextFieldSet(); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aDocumentLength); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: sl@0: EXPORT_C CTextFieldSet* CTextFieldSet::NewL(const MTextFieldFactory* aFactory,const CStreamStore& aFieldStore,TStreamId aStreamId) sl@0: { sl@0: CTextFieldSet* self=new(ELeave) CTextFieldSet(); sl@0: CleanupStack::PushL(self); sl@0: self->SetFieldFactory(CONST_CAST(MTextFieldFactory*,aFactory)); sl@0: self->ConstructL(0); sl@0: self->DoRestoreL(aFieldStore,aStreamId); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: sl@0: CTextFieldSet::CTextFieldSet() sl@0: {} sl@0: sl@0: sl@0: void CTextFieldSet::ConstructL(TInt aDocumentLength) sl@0: // Creates an array in which to store all fields sl@0: // Inserts an initial entry into the array to cover any text that lies after the last field sl@0: // sl@0: { sl@0: iFieldArray = new(ELeave) CArrayFixSeg(KFieldArrayGranularity); sl@0: AddInitialFieldEntryL(iFieldArray,aDocumentLength); sl@0: sl@0: __TEST_INVARIANT; sl@0: } sl@0: sl@0: sl@0: EXPORT_C CTextFieldSet::~CTextFieldSet() sl@0: { sl@0: delete iRollbackInfo; sl@0: if (iFieldArray) sl@0: { sl@0: TInt fieldCount=iFieldArray->Count(); sl@0: for (TInt index=fieldCount-1;index>=0;index--) sl@0: delete (*iFieldArray)[index].iFieldHeader.iField.AsPtr(); // Delete the textField objects sl@0: delete iFieldArray; sl@0: } sl@0: } sl@0: sl@0: sl@0: EXPORT_C void CTextFieldSet::SetFieldFactory(MTextFieldFactory* aFactory) sl@0: { sl@0: iFieldFactory = aFactory; sl@0: } sl@0: sl@0: sl@0: EXPORT_C MTextFieldFactory* CTextFieldSet::FieldFactory()const sl@0: { sl@0: return iFieldFactory; sl@0: } sl@0: sl@0: sl@0: void CTextFieldSet::InsertEntryL(TInt aIndex,TTextFieldEntry& aEntry) sl@0: { sl@0: InsertEntryL(aIndex,aEntry,iFieldArray); sl@0: } sl@0: sl@0: sl@0: void CTextFieldSet::InsertEntryL(TInt aIndex,TTextFieldEntry& aEntry,CArrayFixSeg* aArray) sl@0: // if this function leaves it will be as if it had never been called... sl@0: // sl@0: { sl@0: if (aEntry.iFieldHeader.iField.IsPtr()) sl@0: CleanupStack::PushL(aEntry.iFieldHeader.iField.AsPtr()); sl@0: aArray->InsertL(aIndex,aEntry); // insert new entry sl@0: if (aEntry.iFieldHeader.iField.IsPtr()) sl@0: CleanupStack::Pop(); sl@0: } sl@0: sl@0: sl@0: void CTextFieldSet::AppendEntryL(TTextFieldEntry& aEntry) sl@0: { sl@0: AppendEntryL(aEntry,iFieldArray); sl@0: } sl@0: sl@0: sl@0: void CTextFieldSet::AppendEntryL(TTextFieldEntry& aEntry,CArrayFixSeg* aArray) sl@0: { sl@0: if (aEntry.iFieldHeader.iField.IsPtr()) sl@0: CleanupStack::PushL(aEntry.iFieldHeader.iField.AsPtr()); sl@0: aArray->AppendL(aEntry); // insert new entry sl@0: if (aEntry.iFieldHeader.iField.IsPtr()) sl@0: CleanupStack::Pop(); sl@0: } sl@0: sl@0: sl@0: TInt CTextFieldSet::EntryLen(TInt aIndex)const sl@0: { sl@0: return EntryLen((*iFieldArray)[aIndex]); sl@0: } sl@0: sl@0: sl@0: TInt CTextFieldSet::EntryLen(const TTextFieldEntry& aEntry)const sl@0: { sl@0: return aEntry.iPreFieldLen+aEntry.iFieldValueLen; sl@0: } sl@0: sl@0: sl@0: TTextFieldEntry CTextFieldSet::SplitEntry(TInt aIndex,TInt aOffset, TInt aRange)const sl@0: // Splits the entry aIndex, returning the part demarked by the offset (from the start of the entry) and the range sl@0: // sl@0: { sl@0: __TEST_INVARIANT; sl@0: sl@0: __ASSERT_DEBUG((aIndex>=0)&&(aIndexCount()),Panic(EIndexOutOfRange)); sl@0: TInt entryLength = EntryLen(aIndex); sl@0: __ASSERT_DEBUG((aOffset>=0)&&(aOffset<=entryLength),Panic(EPosOutOfRange)); sl@0: __ASSERT_DEBUG((aRange>=0),Panic(ENegativeRange)); sl@0: sl@0: if ((aOffset+aRange)>entryLength) sl@0: aRange = entryLength-aOffset; // scale range down to entry size if neccessary sl@0: sl@0: if ((aOffset==0)&&(aRange==entryLength)) sl@0: return (*iFieldArray)[aIndex]; //entry does not need to be split sl@0: sl@0: TInt charsCopied=0; sl@0: TTextFieldEntry entry; sl@0: entry.iPreFieldLen = 0; sl@0: entry.iFieldValueLen = 0; sl@0: entry.iFieldHeader.iField = NULL; sl@0: if (aOffset<(*iFieldArray)[aIndex].iPreFieldLen) sl@0: {// At least some of the pre needs to be copied sl@0: entry.iPreFieldLen = (*iFieldArray)[aIndex].iPreFieldLen-aOffset; sl@0: if ((entry.iPreFieldLen)>aRange) sl@0: entry.iPreFieldLen = aRange; sl@0: charsCopied = entry.iPreFieldLen; sl@0: } sl@0: sl@0: if (charsCopied* aArray,TInt aDocumentLength) sl@0: // Add initial entry sl@0: { sl@0: TTextFieldEntry initialEntry; sl@0: initialEntry.iPreFieldLen = aDocumentLength; sl@0: initialEntry.iFieldValueLen = 0; sl@0: initialEntry.iFieldHeader.iFieldType = KNullUid; sl@0: initialEntry.iFieldHeader.iField = NULL; sl@0: aArray->AppendL(initialEntry); sl@0: } sl@0: sl@0: sl@0: EXPORT_C void CTextFieldSet::Reset() sl@0: // deletes all fields (but not corresponding text) and reinitialises the field array sl@0: // sl@0: { sl@0: __TEST_INVARIANT; sl@0: sl@0: for (TInt index=FieldCount()-1 ; index>=0 ; index--) sl@0: delete (*iFieldArray)[index].iFieldHeader.iField.AsPtr(); // Delete the textField objects sl@0: iFieldArray->Reset(); sl@0: AddInitialFieldEntryL(iFieldArray,0); // cannot leave in this context sl@0: iFieldArray->Compress(); // compress array sl@0: sl@0: __TEST_INVARIANT; sl@0: } sl@0: sl@0: sl@0: EXPORT_C CTextField* CTextFieldSet::NewFieldL(TUid aFieldType) sl@0: { sl@0: if (iFieldFactory) sl@0: return iFieldFactory->NewFieldL(aFieldType); sl@0: else sl@0: return NULL; sl@0: } sl@0: sl@0: sl@0: EXPORT_C TInt CTextFieldSet::InsertFieldL(TInt aPos,CTextField* aField,TUid aFieldType) sl@0: // Inserts a field header aField at aPos (aField should be declared on the heap) sl@0: // The field initially has zero length: Update must be called afterward sl@0: // sl@0: { sl@0: __TEST_INVARIANT; sl@0: __ASSERT_ALWAYS((aPos>=0),Panic(EPosOutsideDoc)); sl@0: __ASSERT_DEBUG(aPos<=CharCount(),Panic(EPosOutsideDoc)); sl@0: __ASSERT_ALWAYS(aField,Panic(ENoTextField)); sl@0: sl@0: TInt errLevel=KErrAlreadyExists; sl@0: TTextFieldEntry entry; sl@0: entry.iFieldHeader.iField = aField; sl@0: entry.iFieldHeader.iFieldType = aFieldType; sl@0: entry.iFieldValueLen = 0; sl@0: TInt index; TInt offset; sl@0: TBool inField = InField(aPos,index,offset); sl@0: if (!inField) sl@0: {// not inserting into a field sl@0: entry.iPreFieldLen = offset; sl@0: iFieldArray->InsertL(index,entry); // insert new entry sl@0: (*iFieldArray)[index+1].iPreFieldLen -= offset; // update old entry sl@0: errLevel = KErrNone; sl@0: } sl@0: else if (offset==0) sl@0: {// at start of field sl@0: entry.iPreFieldLen = (*iFieldArray)[index].iPreFieldLen; sl@0: iFieldArray->InsertL(index,entry); // insert new entry sl@0: (*iFieldArray)[index+1].iPreFieldLen = 0; // update old entry sl@0: errLevel = KErrNone; sl@0: } sl@0: sl@0: __TEST_INVARIANT; sl@0: return errLevel; sl@0: } sl@0: sl@0: sl@0: EXPORT_C const CTextField* CTextFieldSet::TextField(TInt aPos)const sl@0: // Return a handle to the concrete field at document position aPos. sl@0: // Returns NULL if there is no field at position aPos. sl@0: // sl@0: { sl@0: __TEST_INVARIANT; sl@0: sl@0: TInt index=-1; sl@0: TInt offset=0; sl@0: TBool inField=InField(aPos,index,offset); sl@0: if (!inField) sl@0: return NULL; sl@0: TSwizzle field=(*iFieldArray)[index].iFieldHeader.iField; sl@0: __ASSERT_DEBUG(field.IsPtr(),User::Invariant()); sl@0: return field.AsPtr(); sl@0: } sl@0: sl@0: sl@0: EXPORT_C TInt CTextFieldSet::RemoveField(TInt aPos) sl@0: // Removes the field from the array, adding it's content to the "before" of the next field. sl@0: // After this function is called the text the field contained should be deleted. If this does sl@0: // not happen this function acts as a "ConvertFieldToText()" sl@0: // sl@0: { sl@0: __TEST_INVARIANT; sl@0: __ASSERT_ALWAYS((aPos>=0),Panic(EPosOutsideDoc)); sl@0: __ASSERT_DEBUG(aPos<=CharCount(),Panic(EPosOutsideDoc)); sl@0: sl@0: TInt errLevel=KErrNone; sl@0: TInt index; TInt offset; sl@0: if (!InField(aPos,index,offset)) sl@0: errLevel = KErrNotFound; sl@0: else sl@0: // delete the field entry tidily sl@0: DeleteFieldEntry(index); sl@0: sl@0: __TEST_INVARIANT; sl@0: return errLevel; sl@0: } sl@0: sl@0: sl@0: EXPORT_C TInt CTextFieldSet::FieldCount() const sl@0: { sl@0: __TEST_INVARIANT; sl@0: sl@0: // return count-1 because there is always an entry in the array for the text at the sl@0: // end of the document, after the last field (maybe just the end of doc char) sl@0: return (iFieldArray->Count()-1); sl@0: } sl@0: sl@0: sl@0: EXPORT_C TInt CTextFieldSet::CharCount() const sl@0: // returns the number of characters in the document according to the field array sl@0: { sl@0: __TEST_INVARIANT; sl@0: sl@0: TInt charCount = 0; sl@0: for (TInt index=FieldCount() ; index>=0 ; index--) sl@0: charCount += (*iFieldArray)[index].iPreFieldLen+(*iFieldArray)[index].iFieldValueLen; sl@0: return charCount; sl@0: } sl@0: sl@0: sl@0: EXPORT_C TBool CTextFieldSet::FindFields(TInt aPos) const sl@0: // Return ETrue if aPos is in a field sl@0: // sl@0: { sl@0: TFindFieldInfo dummy; sl@0: return (FindFields(dummy,aPos,0)); sl@0: } sl@0: sl@0: sl@0: EXPORT_C TBool CTextFieldSet::FindFields(TFindFieldInfo& aInfo,TInt aPos, TInt aRange) const sl@0: // Check whether aPos is in a field, then check whether any fields start in aRange sl@0: // sl@0: { sl@0: __TEST_INVARIANT; sl@0: __ASSERT_ALWAYS(aRange>=0,Panic(ENegativeRange)); sl@0: __ASSERT_ALWAYS(aPos>=0,Panic(EPosOutsideDoc)); sl@0: __ASSERT_ALWAYS(aPos+aRange<=CharCount(),Panic(EPosOutsideDoc)); sl@0: sl@0: aInfo.iFieldCountInRange = 0; sl@0: aInfo.iFirstFieldLen = 0; sl@0: aInfo.iFirstFieldPos = 0; sl@0: TInt pos=aPos; // position in doc sl@0: // are we in a field to begin with? sl@0: TInt index; TInt offset; sl@0: if (InField(aPos,index,offset)) sl@0: { sl@0: aInfo.iFieldCountInRange++; sl@0: aInfo.iFirstFieldLen = (*iFieldArray)[index].iFieldValueLen; sl@0: aInfo.iFirstFieldPos = aPos-offset; sl@0: pos += (*iFieldArray)[index].iFieldValueLen-offset+(*iFieldArray)[index+1].iPreFieldLen; sl@0: index++; sl@0: } sl@0: else sl@0: pos += (*iFieldArray)[index].iPreFieldLen-offset; sl@0: // step through array until aRange sl@0: while (posCount()-1)) && ((*iFieldArray)[index].iFieldValueLen==0) ) sl@0: { sl@0: aInfo.iFieldCountInRange++; sl@0: index++; sl@0: while ( ((*iFieldArray)[index].iPreFieldLen==0) && ((*iFieldArray)[index].iFieldValueLen==0) && (index<(iFieldArray->Count()-1)) ) sl@0: { sl@0: aInfo.iFieldCountInRange++; sl@0: index++; sl@0: } sl@0: } sl@0: sl@0: __ASSERT_DEBUG(aInfo.iFieldCountInRange<=FieldCount(),Panic(EDebug)); sl@0: return aInfo.iFieldCountInRange; sl@0: } sl@0: sl@0: sl@0: EXPORT_C TInt CTextFieldSet::NewFieldValueL(HBufC*& aBuf, TInt aPos) sl@0: // Returns the new value of the field at aPos (if applicable). sl@0: // The method might reallocate aBuf parameter, so don't forget to: sl@0: // 1) Push aBuf parameter in the CleanupStack before the call. The call sl@0: // may fail, then aBuf gets lost. sl@0: // 2) Pop aBuf parameter from the CleanupStack after the call - aBuf may get sl@0: // reallocated, so the pushed pointer becomes invalid. sl@0: // 3) Push aBuf in the CleanupStack again. sl@0: { sl@0: __TEST_INVARIANT; sl@0: __ASSERT_ALWAYS(aBuf,Panic(ENoBuffer)); sl@0: __ASSERT_ALWAYS((aPos>=0),Panic(EPosOutsideDoc)); sl@0: __ASSERT_DEBUG(aPos<=CharCount(),Panic(EPosOutsideDoc)); sl@0: sl@0: TInt errLevel = KErrNotFound; sl@0: TInt index; TInt offset; sl@0: if (InField(aPos,index,offset)) sl@0: {// There's a field at aPos sl@0: TPtr bufPtr = aBuf->Des(); sl@0: TInt reqLen = (*iFieldArray)[index].iFieldHeader.iField->Value(bufPtr); sl@0: while (reqLen>0) sl@0: {// If more storage is required for the value then reallocate the buffer sl@0: aBuf = aBuf->ReAllocL(reqLen); // for unicode compatability, rounds up sl@0: TPtr pointer = aBuf->Des(); sl@0: reqLen = (*iFieldArray)[index].iFieldHeader.iField->Value(pointer); sl@0: } sl@0: // dont set new field length - this will be done in a subsequent NotifyInsert() sl@0: errLevel = KErrNone; sl@0: } sl@0: sl@0: __TEST_INVARIANT; sl@0: return errLevel; sl@0: } sl@0: sl@0: sl@0: EXPORT_C void CTextFieldSet::NotifyInsertion(TInt aPos, TInt aNumberAdded) sl@0: // Informs the array that aNumberAdded characters have been inserted in the document sl@0: // sl@0: { sl@0: __TEST_INVARIANT; sl@0: __ASSERT_ALWAYS(aPos>=0,Panic(EPosOutsideDoc)); sl@0: __ASSERT_DEBUG(aPos<=CharCount(),Panic(EPosOutsideDoc)); sl@0: __ASSERT_ALWAYS(aNumberAdded>=0,Panic(EIllegalNegativeValue)); sl@0: sl@0: TInt index; TInt offset; sl@0: // are the extra characters in a field (matching away from fields)? sl@0: if (!InField(aPos,index,offset)) sl@0: (*iFieldArray)[index].iPreFieldLen += aNumberAdded; sl@0: else sl@0: if (offset>0) sl@0: (*iFieldArray)[index].iFieldValueLen += aNumberAdded; sl@0: else sl@0: (*iFieldArray)[index].iPreFieldLen += aNumberAdded; sl@0: sl@0: __TEST_INVARIANT; sl@0: } sl@0: sl@0: sl@0: EXPORT_C void CTextFieldSet::NotifyFieldUpdate(TInt aPos, TInt aNewFieldValueLength) sl@0: { sl@0: __TEST_INVARIANT; sl@0: __ASSERT_ALWAYS((aPos>=0),Panic(EPosOutsideDoc)); sl@0: __ASSERT_DEBUG(aPos<=CharCount(),Panic(EPosOutsideDoc)); sl@0: __ASSERT_ALWAYS(aNewFieldValueLength>=0,Panic(EIllegalNegativeValue)); sl@0: sl@0: // Is the insert pos in a field? If so which? sl@0: TInt index; TInt offset; sl@0: __ASSERT_ALWAYS(InField(aPos,index,offset),Panic(EPosNotInField)); sl@0: // Update the length of the relevant field sl@0: (*iFieldArray)[index].iFieldValueLen = aNewFieldValueLength; sl@0: sl@0: __TEST_INVARIANT; sl@0: } sl@0: sl@0: sl@0: EXPORT_C void CTextFieldSet::NotifyDeletion(TInt aPos,TInt aTotalRemoved) sl@0: // Informs the array that aTotalRemoved characters have been removed from the document sl@0: // Any fields wholely contained will be removed, those partially intersecting will just be shortened sl@0: // sl@0: { sl@0: __TEST_INVARIANT; sl@0: __ASSERT_ALWAYS(aPos>=0,Panic(EPosOutsideDoc)); sl@0: __ASSERT_DEBUG(aPos<=CharCount(),Panic(EPosOutsideDoc)); sl@0: __ASSERT_ALWAYS(aTotalRemoved>=0,Panic(EIllegalNegativeValue)); sl@0: sl@0: TInt charCount = CharCount(); sl@0: sl@0: //There is a possibility that there exists hidden end-of-document character in rich text objects. sl@0: //This is checked by the if statement & accordingly aTotalRemoved is decremented. sl@0: //i.e. aPos + aTotalRemoved could be greater by 1 than the CharCount(), sl@0: //this is because the aTotalRemoved might also include 1 hidden character. - DEF095911 sl@0: if(aPos+aTotalRemoved > charCount) sl@0: aTotalRemoved--; sl@0: sl@0: __ASSERT_DEBUG(aPos+aTotalRemoved<=charCount, Panic(EPosOutsideDoc)); sl@0: sl@0: int index = 0; sl@0: int offset = 0; sl@0: int cur_pos = aPos; sl@0: int end_pos = aPos + aTotalRemoved; sl@0: TBool in_field = InField(cur_pos,index,offset); sl@0: TTextFieldEntry* field = NULL; sl@0: int field_start = 0; sl@0: int field_end = 0; sl@0: if (index >= 0 && index < iFieldArray->Count()) sl@0: { sl@0: field = &(*iFieldArray)[index]; sl@0: field_start = cur_pos - offset; sl@0: if (!in_field) sl@0: field_start += field->iPreFieldLen; sl@0: field_end = field_start + field->iFieldValueLen; sl@0: } sl@0: sl@0: while (field) sl@0: { sl@0: // Reduce the size of the gap before the field if any. sl@0: int gap = Min(end_pos,field_start) - cur_pos; sl@0: if (gap > 0) sl@0: { sl@0: cur_pos += gap; sl@0: field->iPreFieldLen -= gap; sl@0: } sl@0: if (cur_pos >= end_pos) sl@0: break; sl@0: sl@0: // Reduce the field length. sl@0: int remove_start = cur_pos; sl@0: int remove_end = Min(field_end,end_pos); sl@0: cur_pos = field_end; sl@0: field->iFieldValueLen -= (remove_end - remove_start); sl@0: sl@0: // Delete the field if it is now of zero length. sl@0: int added_to_next = 0; sl@0: if (field->iFieldValueLen == 0) sl@0: { sl@0: added_to_next = field->iPreFieldLen; sl@0: DeleteFieldEntry(index); sl@0: } sl@0: else sl@0: index++; sl@0: sl@0: // Move to the next field. sl@0: if (index < iFieldArray->Count()) sl@0: { sl@0: field = &(*iFieldArray)[index]; sl@0: field_start = cur_pos + field->iPreFieldLen - added_to_next; sl@0: field_end = field_start + field->iFieldValueLen; sl@0: } sl@0: else sl@0: field = NULL; sl@0: } sl@0: sl@0: __TEST_INVARIANT; sl@0: } sl@0: sl@0: sl@0: TBool CTextFieldSet::InField(const TInt aPos, TInt& anIndex, TInt& anOffset) const sl@0: // works out whether or not aPos is in a field (matching right), sl@0: // sets anIndex to the index number of the field entry, sl@0: // and sets anOffset to the distance aPos is into the field or its preceeding gap sl@0: // sl@0: { sl@0: __ASSERT_ALWAYS((aPos>=0),Panic(EPosOutsideDoc)); sl@0: __ASSERT_DEBUG(aPos<=CharCount(),Panic(EPosOutsideDoc)); sl@0: sl@0: TBool inField; sl@0: TInt currentPos = 0; sl@0: anIndex = 0; sl@0: TInt lengthOfDoc = CharCount(); sl@0: TInt lastFieldNum = iFieldArray->Count()-1; sl@0: // Find the index of the entry containing aPos sl@0: if (aPos == lengthOfDoc) sl@0: { sl@0: anIndex = lastFieldNum; sl@0: currentPos = aPos; sl@0: } sl@0: else sl@0: { sl@0: anIndex = -1; sl@0: while (aPos >= currentPos) sl@0: { sl@0: anIndex++; sl@0: currentPos += (*iFieldArray)[anIndex].iPreFieldLen+(*iFieldArray)[anIndex].iFieldValueLen; sl@0: } sl@0: } sl@0: // Check that we have not skipped over any zero-length fields sl@0: if ( ((anIndex-1)>=0) && ((*iFieldArray)[anIndex-1].iFieldValueLen==0) ) sl@0: { sl@0: TInt temp = currentPos - ((*iFieldArray)[anIndex].iPreFieldLen+(*iFieldArray)[anIndex].iFieldValueLen); sl@0: if (temp==aPos) sl@0: {// aPos is on a field boundary sl@0: currentPos = temp; sl@0: anIndex--; sl@0: while ( ((anIndex-1)>=0) sl@0: &&((*iFieldArray)[anIndex].iPreFieldLen==0) sl@0: &&((*iFieldArray)[anIndex-1].iFieldValueLen==0) ) sl@0: { sl@0: anIndex--; sl@0: } sl@0: } sl@0: } sl@0: // Move to the start of the field (end of prefield) in entry [anIndex] sl@0: currentPos -= (*iFieldArray)[anIndex].iFieldValueLen; sl@0: // Determine whether or not aPos is in the field of entry[anIndex] sl@0: if (anIndex == lastFieldNum) sl@0: inField = EFalse; sl@0: else if (aPos >= currentPos) sl@0: inField = ETrue; sl@0: else sl@0: inField = EFalse; sl@0: // Calculate the offset sl@0: if (inField) sl@0: anOffset = aPos-currentPos; sl@0: else sl@0: anOffset = aPos+(*iFieldArray)[anIndex].iPreFieldLen-currentPos; sl@0: return inField; sl@0: } sl@0: sl@0: sl@0: void CTextFieldSet::DeleteFieldEntry(TInt anIndex) sl@0: { sl@0: DeleteFieldEntry(iFieldArray,anIndex); sl@0: } sl@0: sl@0: sl@0: void CTextFieldSet::DeleteFieldEntry(CArrayFixSeg* aArray,TInt anIndex) sl@0: // remove the entry anIndex from the array but don't delete the text from the doc. sl@0: // sl@0: { sl@0: __ASSERT_ALWAYS(anIndex<(aArray->Count()-1),Panic(EIndexOutOfRange)); sl@0: sl@0: // add the entry's "before" to the "before" of the next entry. sl@0: (*aArray)[anIndex+1].iPreFieldLen += (*aArray)[anIndex].iPreFieldLen; sl@0: // add the field's length to the "before" of the next entry. sl@0: (*aArray)[anIndex+1].iPreFieldLen += (*aArray)[anIndex].iFieldValueLen; sl@0: if ((*aArray)[anIndex].iFieldHeader.iField.IsPtr()) sl@0: delete (*aArray)[anIndex].iFieldHeader.iField.AsPtr(); // delete the field sl@0: aArray->Delete(anIndex); // remove the entry from the array sl@0: } sl@0: sl@0: sl@0: /////////////////////////////////////////////// sl@0: // TTextFieldEntry sl@0: /////////////////////////////////////////////// sl@0: sl@0: sl@0: EXPORT_C void TTextFieldEntry::InternalizeL(RReadStream& aStream) sl@0: // entry must have a header (ie cant be last entry in the array) sl@0: { sl@0: iPreFieldLen = aStream.ReadInt32L(); sl@0: iFieldValueLen = aStream.ReadInt32L(); sl@0: aStream>> iFieldHeader; sl@0: } sl@0: sl@0: sl@0: EXPORT_C void TTextFieldEntry::ExternalizeL(RWriteStream& aStream)const sl@0: // entry must have a header (ie cant be last entry in the array) sl@0: { sl@0: aStream.WriteInt32L(iPreFieldLen); sl@0: aStream.WriteInt32L(iFieldValueLen); sl@0: aStream<< iFieldHeader; sl@0: } sl@0: sl@0: