Added code to track iterator status, and modified first/last/next/prev

methods to set the iterator based on this status.
This commit is contained in:
kin%netscape.com 1999-04-21 14:38:15 +00:00
Родитель ea93f4c0c8
Коммит 2ee9b5ab4a
4 изменённых файлов: 382 добавлений и 72 удалений

Просмотреть файл

@ -25,6 +25,8 @@
#include "nsIDOMSelection.h" #include "nsIDOMSelection.h"
#include "nsTextServicesDocument.h" #include "nsTextServicesDocument.h"
// #define HAVE_EDIT_ACTION_LISTENERS 1
#define LOCK_DOC(doc) #define LOCK_DOC(doc)
#define UNLOCK_DOC(doc) #define UNLOCK_DOC(doc)
@ -107,6 +109,8 @@ nsTextServicesDocument::nsTextServicesDocument()
mSelEndIndex = -1; mSelEndIndex = -1;
mSelEndOffset = -1; mSelEndOffset = -1;
mIteratorStatus = eUninitialized;
if (sInstanceCount <= 0) if (sInstanceCount <= 0)
{ {
sAAtom = NS_NewAtom("a"); sAAtom = NS_NewAtom("a");
@ -432,24 +436,43 @@ nsTextServicesDocument::GetCurrentTextBlock(nsString *aStr)
NS_IMETHODIMP NS_IMETHODIMP
nsTextServicesDocument::PrevBlock() nsTextServicesDocument::PrevBlock()
{ {
nsresult result;
if (!mIterator) if (!mIterator)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
LOCK_DOC(this); LOCK_DOC(this);
nsresult result = FirstTextNodeInPrevBlock(); if (mIteratorStatus == nsTextServicesDocument::eValid || mIteratorStatus == nsTextServicesDocument::eNext)
if (NS_FAILED(result))
{ {
UNLOCK_DOC(this); result = FirstTextNodeInPrevBlock();
return result;
if (NS_FAILED(result))
{
UNLOCK_DOC(this);
return result;
}
// XXX: Check to make sure the iterator is pointing
// to a valid text block, and set mIteratorStatus
// accordingly!
}
else if (mIteratorStatus == nsTextServicesDocument::ePrev)
{
// The iterator already points to the previous
// block, so don't do anything.
mIteratorStatus = nsTextServicesDocument::eValid;
} }
// Keep track of prev and next blocks, just in case // Keep track of prev and next blocks, just in case
// the text service blows away the current block. // the text service blows away the current block.
result = FindFirstTextNodeInPrevBlock(getter_AddRefs(mPrevTextBlock)); if (eValid)
result = FindFirstTextNodeInNextBlock(getter_AddRefs(mNextTextBlock)); {
result = FindFirstTextNodeInPrevBlock(getter_AddRefs(mPrevTextBlock));
result = FindFirstTextNodeInNextBlock(getter_AddRefs(mNextTextBlock));
}
UNLOCK_DOC(this); UNLOCK_DOC(this);
@ -459,24 +482,49 @@ nsTextServicesDocument::PrevBlock()
NS_IMETHODIMP NS_IMETHODIMP
nsTextServicesDocument::NextBlock() nsTextServicesDocument::NextBlock()
{ {
nsresult result;
if (!mIterator) if (!mIterator)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
LOCK_DOC(this); LOCK_DOC(this);
nsresult result = FirstTextNodeInNextBlock(); if (mIteratorStatus == nsTextServicesDocument::eValid)
if (NS_FAILED(result))
{ {
UNLOCK_DOC(this); result = FirstTextNodeInNextBlock();
return result;
if (NS_FAILED(result))
{
UNLOCK_DOC(this);
return result;
}
// XXX: check if the iterator is pointing to a text node,
// then set mIteratorStatus.
}
else if (mIteratorStatus == nsTextServicesDocument::eNext)
{
// The iterator already points to the next block,
// so don't do anything to it!
mIteratorStatus = nsTextServicesDocument::eValid;
}
else if (mIteratorStatus == nsTextServicesDocument::ePrev)
{
// If the iterator is pointing to the previous block,
// we know that there is no next text block!
mIteratorStatus = nsTextServicesDocument::eInvalid;
} }
// Keep track of prev and next blocks, just in case // Keep track of prev and next blocks, just in case
// the text service blows away the current block. // the text service blows away the current block.
result = FindFirstTextNodeInPrevBlock(getter_AddRefs(mPrevTextBlock)); if (mIteratorStatus == nsTextServicesDocument::eValid)
result = FindFirstTextNodeInNextBlock(getter_AddRefs(mNextTextBlock)); {
result = FindFirstTextNodeInPrevBlock(getter_AddRefs(mPrevTextBlock));
result = FindFirstTextNodeInNextBlock(getter_AddRefs(mNextTextBlock));
}
UNLOCK_DOC(this); UNLOCK_DOC(this);
@ -648,9 +696,9 @@ nsTextServicesDocument::DeleteSelection()
LOCK_DOC(this); LOCK_DOC(this);
//**** KDEBUG **** //**** KDEBUG ****
// printf("\n---- Before Delete\n"); printf("\n---- Before Delete\n");
// printf("Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset); printf("Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset);
// PrintOffsetTable(); PrintOffsetTable();
//**** KDEBUG **** //**** KDEBUG ****
PRInt32 i, selLength; PRInt32 i, selLength;
@ -840,9 +888,9 @@ nsTextServicesDocument::DeleteSelection()
result = RemoveInvalidOffsetEntries(); result = RemoveInvalidOffsetEntries();
//**** KDEBUG **** //**** KDEBUG ****
// printf("\n---- After Delete\n"); printf("\n---- After Delete\n");
// printf("Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset); printf("Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset);
// PrintOffsetTable(); PrintOffsetTable();
//**** KDEBUG **** //**** KDEBUG ****
UNLOCK_DOC(this); UNLOCK_DOC(this);
@ -863,23 +911,34 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (!aText) if (!aText)
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
LOCK_DOC(this);
result = mEditor->BeginTransaction();
if (NS_FAILED(result))
{
UNLOCK_DOC(this);
return result;
}
// We have to call DeleteSelection(), just in case there is // We have to call DeleteSelection(), just in case there is
// a selection, to make sure that our offset table is kept in sync! // a selection, to make sure that our offset table is kept in sync!
result = DeleteSelection(); result = DeleteSelection();
if (NS_FAILED(result)) if (NS_FAILED(result))
{
mEditor->EndTransaction();
UNLOCK_DOC(this);
return result; return result;
}
#if 1
LOCK_DOC(this);
result = mEditor->InsertText(*aText); result = mEditor->InsertText(*aText);
if (NS_FAILED(result)) if (NS_FAILED(result))
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return result; return result;
} }
@ -919,6 +978,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (!itEntry) if (!itEntry)
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
@ -927,6 +987,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (!mOffsetTable.InsertElementAt(itEntry, mSelStartIndex)) if (!mOffsetTable.InsertElementAt(itEntry, mSelStartIndex))
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -948,6 +1009,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (!itEntry) if (!itEntry)
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -968,6 +1030,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (!itEntry) if (!itEntry)
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
@ -994,6 +1057,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (NS_FAILED(result)) if (NS_FAILED(result))
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return result; return result;
} }
@ -1002,6 +1066,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (NS_FAILED(result)) if (NS_FAILED(result))
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return result; return result;
} }
@ -1018,6 +1083,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (NS_FAILED(result)) if (NS_FAILED(result))
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return result; return result;
} }
@ -1026,6 +1092,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (!itEntry) if (!itEntry)
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
@ -1035,6 +1102,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (!mOffsetTable.InsertElementAt(itEntry, mSelStartIndex + 1)) if (!mOffsetTable.InsertElementAt(itEntry, mSelStartIndex + 1))
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -1066,9 +1134,15 @@ nsTextServicesDocument::InsertText(const nsString *aText)
//**** KDEBUG **** //**** KDEBUG ****
} }
UNLOCK_DOC(this); result = mEditor->EndTransaction();
#endif if (NS_FAILED(result))
{
UNLOCK_DOC(this);
return result;
}
UNLOCK_DOC(this);
return result; return result;
} }
@ -1358,7 +1432,7 @@ nsTextServicesDocument::InitContentIterator()
} }
// //
// Create a range containing the document bodies contents: // Create a range containing the document body's contents:
// //
nsCOMPtr<nsIDOMNodeList>nodeList; nsCOMPtr<nsIDOMNodeList>nodeList;
@ -1432,6 +1506,8 @@ nsTextServicesDocument::InitContentIterator()
result = mIterator->Init(range); result = mIterator->Init(range);
mIteratorStatus = eInvalid;
UNLOCK_DOC(this); UNLOCK_DOC(this);
return result; return result;
@ -1512,10 +1588,48 @@ nsTextServicesDocument::AdjustContentIterator()
content = do_QueryInterface(nextValidNode); content = do_QueryInterface(nextValidNode);
if (content) if (content)
return mIterator->PositionAt(content); {
result = mIterator->PositionAt(content);
// XXX: If we get here, there arent' any valid entries if (NS_FAILED(result))
// in the offset table! mIteratorStatus = eInvalid;
else
mIteratorStatus = eValid;
return result;
}
// If we get here, there aren't any valid entries
// in the offset table! Try to position the iterator
// on the next text block first, then previous if
// one doesn't exist!
if (mNextTextBlock)
{
result = mIterator->PositionAt(mNextTextBlock);
if (NS_FAILED(result))
{
mIteratorStatus = eInvalid;
return result;
}
mIteratorStatus = eNext;
}
else if (mPrevTextBlock)
{
result = mIterator->PositionAt(mPrevTextBlock);
if (NS_FAILED(result))
{
mIteratorStatus = eInvalid;
return result;
}
mIteratorStatus = ePrev;
}
else
mIteratorStatus = eInvalid;
return NS_OK; return NS_OK;
} }
@ -1658,6 +1772,7 @@ nsTextServicesDocument::FirstBlock()
return result; return result;
nsCOMPtr<nsIContent> content; nsCOMPtr<nsIContent> content;
PRBool foundTextBlock = PR_FALSE;
while (NS_COMFALSE == mIterator->IsDone()) while (NS_COMFALSE == mIterator->IsDone())
{ {
@ -1667,7 +1782,10 @@ nsTextServicesDocument::FirstBlock()
return result; return result;
if (IsTextNode(content)) if (IsTextNode(content))
{
foundTextBlock = PR_TRUE;
break; break;
}
mIterator->Next(); mIterator->Next();
} }
@ -1675,8 +1793,20 @@ nsTextServicesDocument::FirstBlock()
// Keep track of prev and next blocks, just in case // Keep track of prev and next blocks, just in case
// the text service blows away the current block. // the text service blows away the current block.
mPrevTextBlock = nsCOMPtr<nsIContent>(); if (foundTextBlock)
result = FindFirstTextNodeInNextBlock(getter_AddRefs(mNextTextBlock)); {
mIteratorStatus = nsTextServicesDocument::eValid;
mPrevTextBlock = nsCOMPtr<nsIContent>();
result = FindFirstTextNodeInNextBlock(getter_AddRefs(mNextTextBlock));
}
else
{
// There's no text block in the document!
mIteratorStatus = nsTextServicesDocument::eInvalid;
mPrevTextBlock = nsCOMPtr<nsIContent>();
mNextTextBlock = nsCOMPtr<nsIContent>();
}
return result; return result;
} }
@ -1700,6 +1830,7 @@ nsTextServicesDocument::LastBlock()
nsCOMPtr<nsIContent> content; nsCOMPtr<nsIContent> content;
nsCOMPtr<nsIContent> last; nsCOMPtr<nsIContent> last;
PRBool foundTextBlock = PR_FALSE;
while (NS_COMFALSE == mIterator->IsDone()) while (NS_COMFALSE == mIterator->IsDone())
{ {
@ -1709,7 +1840,16 @@ nsTextServicesDocument::LastBlock()
return result; return result;
if (IsTextNode(content)) if (IsTextNode(content))
return FirstTextNodeInCurrentBlock(); {
foundTextBlock = PR_TRUE;
result = FirstTextNodeInCurrentBlock();
if (NS_FAILED(result))
return result;
break;
}
mIterator->Prev(); mIterator->Prev();
} }
@ -1717,8 +1857,20 @@ nsTextServicesDocument::LastBlock()
// Keep track of prev and next blocks, just in case // Keep track of prev and next blocks, just in case
// the text service blows away the current block. // the text service blows away the current block.
result = FindFirstTextNodeInPrevBlock(getter_AddRefs(mPrevTextBlock)); if (foundTextBlock)
mNextTextBlock = nsCOMPtr<nsIContent>(); {
mIteratorStatus = eValid;
result = FindFirstTextNodeInPrevBlock(getter_AddRefs(mPrevTextBlock));
mNextTextBlock = nsCOMPtr<nsIContent>();
}
else
{
// There's no text block in the document!
mIteratorStatus = eInvalid;
mPrevTextBlock = nsCOMPtr<nsIContent>();
mNextTextBlock = nsCOMPtr<nsIContent>();
}
return result; return result;
} }

Просмотреть файл

@ -66,10 +66,13 @@ private:
static PRInt32 sInstanceCount; static PRInt32 sInstanceCount;
typedef enum { eUninitialized=0, eInvalid, eValid, ePrev, eNext } TSDIteratorStatus;
nsCOMPtr<nsIDOMDocument> mDOMDocument; nsCOMPtr<nsIDOMDocument> mDOMDocument;
nsCOMPtr<nsIPresShell> mPresShell; nsCOMPtr<nsIPresShell> mPresShell;
nsCOMPtr<nsIEditor> mEditor; nsCOMPtr<nsIEditor> mEditor;
nsCOMPtr<nsIContentIterator> mIterator; nsCOMPtr<nsIContentIterator> mIterator;
TSDIteratorStatus mIteratorStatus;
nsCOMPtr<nsIContent> mPrevTextBlock; nsCOMPtr<nsIContent> mPrevTextBlock;
nsCOMPtr<nsIContent> mNextTextBlock; nsCOMPtr<nsIContent> mNextTextBlock;
nsCOMPtr<nsIEditActionListener> mNotifier; nsCOMPtr<nsIEditActionListener> mNotifier;

Просмотреть файл

@ -25,6 +25,8 @@
#include "nsIDOMSelection.h" #include "nsIDOMSelection.h"
#include "nsTextServicesDocument.h" #include "nsTextServicesDocument.h"
// #define HAVE_EDIT_ACTION_LISTENERS 1
#define LOCK_DOC(doc) #define LOCK_DOC(doc)
#define UNLOCK_DOC(doc) #define UNLOCK_DOC(doc)
@ -107,6 +109,8 @@ nsTextServicesDocument::nsTextServicesDocument()
mSelEndIndex = -1; mSelEndIndex = -1;
mSelEndOffset = -1; mSelEndOffset = -1;
mIteratorStatus = eUninitialized;
if (sInstanceCount <= 0) if (sInstanceCount <= 0)
{ {
sAAtom = NS_NewAtom("a"); sAAtom = NS_NewAtom("a");
@ -432,24 +436,43 @@ nsTextServicesDocument::GetCurrentTextBlock(nsString *aStr)
NS_IMETHODIMP NS_IMETHODIMP
nsTextServicesDocument::PrevBlock() nsTextServicesDocument::PrevBlock()
{ {
nsresult result;
if (!mIterator) if (!mIterator)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
LOCK_DOC(this); LOCK_DOC(this);
nsresult result = FirstTextNodeInPrevBlock(); if (mIteratorStatus == nsTextServicesDocument::eValid || mIteratorStatus == nsTextServicesDocument::eNext)
if (NS_FAILED(result))
{ {
UNLOCK_DOC(this); result = FirstTextNodeInPrevBlock();
return result;
if (NS_FAILED(result))
{
UNLOCK_DOC(this);
return result;
}
// XXX: Check to make sure the iterator is pointing
// to a valid text block, and set mIteratorStatus
// accordingly!
}
else if (mIteratorStatus == nsTextServicesDocument::ePrev)
{
// The iterator already points to the previous
// block, so don't do anything.
mIteratorStatus = nsTextServicesDocument::eValid;
} }
// Keep track of prev and next blocks, just in case // Keep track of prev and next blocks, just in case
// the text service blows away the current block. // the text service blows away the current block.
result = FindFirstTextNodeInPrevBlock(getter_AddRefs(mPrevTextBlock)); if (eValid)
result = FindFirstTextNodeInNextBlock(getter_AddRefs(mNextTextBlock)); {
result = FindFirstTextNodeInPrevBlock(getter_AddRefs(mPrevTextBlock));
result = FindFirstTextNodeInNextBlock(getter_AddRefs(mNextTextBlock));
}
UNLOCK_DOC(this); UNLOCK_DOC(this);
@ -459,24 +482,49 @@ nsTextServicesDocument::PrevBlock()
NS_IMETHODIMP NS_IMETHODIMP
nsTextServicesDocument::NextBlock() nsTextServicesDocument::NextBlock()
{ {
nsresult result;
if (!mIterator) if (!mIterator)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
LOCK_DOC(this); LOCK_DOC(this);
nsresult result = FirstTextNodeInNextBlock(); if (mIteratorStatus == nsTextServicesDocument::eValid)
if (NS_FAILED(result))
{ {
UNLOCK_DOC(this); result = FirstTextNodeInNextBlock();
return result;
if (NS_FAILED(result))
{
UNLOCK_DOC(this);
return result;
}
// XXX: check if the iterator is pointing to a text node,
// then set mIteratorStatus.
}
else if (mIteratorStatus == nsTextServicesDocument::eNext)
{
// The iterator already points to the next block,
// so don't do anything to it!
mIteratorStatus = nsTextServicesDocument::eValid;
}
else if (mIteratorStatus == nsTextServicesDocument::ePrev)
{
// If the iterator is pointing to the previous block,
// we know that there is no next text block!
mIteratorStatus = nsTextServicesDocument::eInvalid;
} }
// Keep track of prev and next blocks, just in case // Keep track of prev and next blocks, just in case
// the text service blows away the current block. // the text service blows away the current block.
result = FindFirstTextNodeInPrevBlock(getter_AddRefs(mPrevTextBlock)); if (mIteratorStatus == nsTextServicesDocument::eValid)
result = FindFirstTextNodeInNextBlock(getter_AddRefs(mNextTextBlock)); {
result = FindFirstTextNodeInPrevBlock(getter_AddRefs(mPrevTextBlock));
result = FindFirstTextNodeInNextBlock(getter_AddRefs(mNextTextBlock));
}
UNLOCK_DOC(this); UNLOCK_DOC(this);
@ -648,9 +696,9 @@ nsTextServicesDocument::DeleteSelection()
LOCK_DOC(this); LOCK_DOC(this);
//**** KDEBUG **** //**** KDEBUG ****
// printf("\n---- Before Delete\n"); printf("\n---- Before Delete\n");
// printf("Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset); printf("Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset);
// PrintOffsetTable(); PrintOffsetTable();
//**** KDEBUG **** //**** KDEBUG ****
PRInt32 i, selLength; PRInt32 i, selLength;
@ -840,9 +888,9 @@ nsTextServicesDocument::DeleteSelection()
result = RemoveInvalidOffsetEntries(); result = RemoveInvalidOffsetEntries();
//**** KDEBUG **** //**** KDEBUG ****
// printf("\n---- After Delete\n"); printf("\n---- After Delete\n");
// printf("Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset); printf("Sel: (%2d, %4d) (%2d, %4d)\n", mSelStartIndex, mSelStartOffset, mSelEndIndex, mSelEndOffset);
// PrintOffsetTable(); PrintOffsetTable();
//**** KDEBUG **** //**** KDEBUG ****
UNLOCK_DOC(this); UNLOCK_DOC(this);
@ -863,23 +911,34 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (!aText) if (!aText)
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
LOCK_DOC(this);
result = mEditor->BeginTransaction();
if (NS_FAILED(result))
{
UNLOCK_DOC(this);
return result;
}
// We have to call DeleteSelection(), just in case there is // We have to call DeleteSelection(), just in case there is
// a selection, to make sure that our offset table is kept in sync! // a selection, to make sure that our offset table is kept in sync!
result = DeleteSelection(); result = DeleteSelection();
if (NS_FAILED(result)) if (NS_FAILED(result))
{
mEditor->EndTransaction();
UNLOCK_DOC(this);
return result; return result;
}
#if 1
LOCK_DOC(this);
result = mEditor->InsertText(*aText); result = mEditor->InsertText(*aText);
if (NS_FAILED(result)) if (NS_FAILED(result))
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return result; return result;
} }
@ -919,6 +978,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (!itEntry) if (!itEntry)
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
@ -927,6 +987,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (!mOffsetTable.InsertElementAt(itEntry, mSelStartIndex)) if (!mOffsetTable.InsertElementAt(itEntry, mSelStartIndex))
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -948,6 +1009,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (!itEntry) if (!itEntry)
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -968,6 +1030,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (!itEntry) if (!itEntry)
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
@ -994,6 +1057,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (NS_FAILED(result)) if (NS_FAILED(result))
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return result; return result;
} }
@ -1002,6 +1066,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (NS_FAILED(result)) if (NS_FAILED(result))
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return result; return result;
} }
@ -1018,6 +1083,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (NS_FAILED(result)) if (NS_FAILED(result))
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return result; return result;
} }
@ -1026,6 +1092,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (!itEntry) if (!itEntry)
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
@ -1035,6 +1102,7 @@ nsTextServicesDocument::InsertText(const nsString *aText)
if (!mOffsetTable.InsertElementAt(itEntry, mSelStartIndex + 1)) if (!mOffsetTable.InsertElementAt(itEntry, mSelStartIndex + 1))
{ {
mEditor->EndTransaction();
UNLOCK_DOC(this); UNLOCK_DOC(this);
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -1066,9 +1134,15 @@ nsTextServicesDocument::InsertText(const nsString *aText)
//**** KDEBUG **** //**** KDEBUG ****
} }
UNLOCK_DOC(this); result = mEditor->EndTransaction();
#endif if (NS_FAILED(result))
{
UNLOCK_DOC(this);
return result;
}
UNLOCK_DOC(this);
return result; return result;
} }
@ -1358,7 +1432,7 @@ nsTextServicesDocument::InitContentIterator()
} }
// //
// Create a range containing the document bodies contents: // Create a range containing the document body's contents:
// //
nsCOMPtr<nsIDOMNodeList>nodeList; nsCOMPtr<nsIDOMNodeList>nodeList;
@ -1432,6 +1506,8 @@ nsTextServicesDocument::InitContentIterator()
result = mIterator->Init(range); result = mIterator->Init(range);
mIteratorStatus = eInvalid;
UNLOCK_DOC(this); UNLOCK_DOC(this);
return result; return result;
@ -1512,10 +1588,48 @@ nsTextServicesDocument::AdjustContentIterator()
content = do_QueryInterface(nextValidNode); content = do_QueryInterface(nextValidNode);
if (content) if (content)
return mIterator->PositionAt(content); {
result = mIterator->PositionAt(content);
// XXX: If we get here, there arent' any valid entries if (NS_FAILED(result))
// in the offset table! mIteratorStatus = eInvalid;
else
mIteratorStatus = eValid;
return result;
}
// If we get here, there aren't any valid entries
// in the offset table! Try to position the iterator
// on the next text block first, then previous if
// one doesn't exist!
if (mNextTextBlock)
{
result = mIterator->PositionAt(mNextTextBlock);
if (NS_FAILED(result))
{
mIteratorStatus = eInvalid;
return result;
}
mIteratorStatus = eNext;
}
else if (mPrevTextBlock)
{
result = mIterator->PositionAt(mPrevTextBlock);
if (NS_FAILED(result))
{
mIteratorStatus = eInvalid;
return result;
}
mIteratorStatus = ePrev;
}
else
mIteratorStatus = eInvalid;
return NS_OK; return NS_OK;
} }
@ -1658,6 +1772,7 @@ nsTextServicesDocument::FirstBlock()
return result; return result;
nsCOMPtr<nsIContent> content; nsCOMPtr<nsIContent> content;
PRBool foundTextBlock = PR_FALSE;
while (NS_COMFALSE == mIterator->IsDone()) while (NS_COMFALSE == mIterator->IsDone())
{ {
@ -1667,7 +1782,10 @@ nsTextServicesDocument::FirstBlock()
return result; return result;
if (IsTextNode(content)) if (IsTextNode(content))
{
foundTextBlock = PR_TRUE;
break; break;
}
mIterator->Next(); mIterator->Next();
} }
@ -1675,8 +1793,20 @@ nsTextServicesDocument::FirstBlock()
// Keep track of prev and next blocks, just in case // Keep track of prev and next blocks, just in case
// the text service blows away the current block. // the text service blows away the current block.
mPrevTextBlock = nsCOMPtr<nsIContent>(); if (foundTextBlock)
result = FindFirstTextNodeInNextBlock(getter_AddRefs(mNextTextBlock)); {
mIteratorStatus = nsTextServicesDocument::eValid;
mPrevTextBlock = nsCOMPtr<nsIContent>();
result = FindFirstTextNodeInNextBlock(getter_AddRefs(mNextTextBlock));
}
else
{
// There's no text block in the document!
mIteratorStatus = nsTextServicesDocument::eInvalid;
mPrevTextBlock = nsCOMPtr<nsIContent>();
mNextTextBlock = nsCOMPtr<nsIContent>();
}
return result; return result;
} }
@ -1700,6 +1830,7 @@ nsTextServicesDocument::LastBlock()
nsCOMPtr<nsIContent> content; nsCOMPtr<nsIContent> content;
nsCOMPtr<nsIContent> last; nsCOMPtr<nsIContent> last;
PRBool foundTextBlock = PR_FALSE;
while (NS_COMFALSE == mIterator->IsDone()) while (NS_COMFALSE == mIterator->IsDone())
{ {
@ -1709,7 +1840,16 @@ nsTextServicesDocument::LastBlock()
return result; return result;
if (IsTextNode(content)) if (IsTextNode(content))
return FirstTextNodeInCurrentBlock(); {
foundTextBlock = PR_TRUE;
result = FirstTextNodeInCurrentBlock();
if (NS_FAILED(result))
return result;
break;
}
mIterator->Prev(); mIterator->Prev();
} }
@ -1717,8 +1857,20 @@ nsTextServicesDocument::LastBlock()
// Keep track of prev and next blocks, just in case // Keep track of prev and next blocks, just in case
// the text service blows away the current block. // the text service blows away the current block.
result = FindFirstTextNodeInPrevBlock(getter_AddRefs(mPrevTextBlock)); if (foundTextBlock)
mNextTextBlock = nsCOMPtr<nsIContent>(); {
mIteratorStatus = eValid;
result = FindFirstTextNodeInPrevBlock(getter_AddRefs(mPrevTextBlock));
mNextTextBlock = nsCOMPtr<nsIContent>();
}
else
{
// There's no text block in the document!
mIteratorStatus = eInvalid;
mPrevTextBlock = nsCOMPtr<nsIContent>();
mNextTextBlock = nsCOMPtr<nsIContent>();
}
return result; return result;
} }

Просмотреть файл

@ -66,10 +66,13 @@ private:
static PRInt32 sInstanceCount; static PRInt32 sInstanceCount;
typedef enum { eUninitialized=0, eInvalid, eValid, ePrev, eNext } TSDIteratorStatus;
nsCOMPtr<nsIDOMDocument> mDOMDocument; nsCOMPtr<nsIDOMDocument> mDOMDocument;
nsCOMPtr<nsIPresShell> mPresShell; nsCOMPtr<nsIPresShell> mPresShell;
nsCOMPtr<nsIEditor> mEditor; nsCOMPtr<nsIEditor> mEditor;
nsCOMPtr<nsIContentIterator> mIterator; nsCOMPtr<nsIContentIterator> mIterator;
TSDIteratorStatus mIteratorStatus;
nsCOMPtr<nsIContent> mPrevTextBlock; nsCOMPtr<nsIContent> mPrevTextBlock;
nsCOMPtr<nsIContent> mNextTextBlock; nsCOMPtr<nsIContent> mNextTextBlock;
nsCOMPtr<nsIEditActionListener> mNotifier; nsCOMPtr<nsIEditActionListener> mNotifier;