void BlockableDisplayNode::RefreshAfter()
{
	DisplayDirector* director = GetDisplayDirector();
	if (director == NULL)
		throw InternalException("BlockableDisplayNode::RefreshDocAfter(): not attached to director.");
	director->RefreshDocAfter(Top());
}
예제 #2
0
VfsPosix::Directory::Directory (const char *dirname)
    throw (InternalException)
{
    dir = opendir (dirname);
    if (dir == NULL)
	throw InternalException (errnoToString (errno));
}
예제 #3
0
void Rotate(RectMatrixCol& U, RectMatrixCol& V, Real tau, Real s)
{
   REPORT
   //  (U, V) = (U, V) * (c, s)  where  tau = s/(1+c), c^2 + s^2 = 1
   int n = U.n;
   if (n != V.n)
   {
      Tracer tr("newmatrm");
      Throw(InternalException("Dimensions differ in Rotate"));
   }
   Real* u = U.store; Real* v = V.store;
   int su = U.spacing; int sv = V.spacing;
   //while (n--)
   //{
   //   Real zu = *u; Real zv = *v;
   //   *u -= s * (zv + zu * tau); *v += s * (zu - zv * tau);
   //   u += su;  v += sv;
   //}
   if (n) for(;;)
   {
      Real zu = *u; Real zv = *v;
      *u -= s * (zv + zu * tau); *v += s * (zu - zv * tau);
      if (!(--n)) break;
      u += su;  v += sv;
   }
}
예제 #4
0
char* ScratchPadAllocator::AllocateMemory( int size )
	{
	// Will be set if we dont return in the for loop so we can append a chunk.
	MemoryChunk* lastMemoryChunkInChain = NULL;
	
	// See if any of the blocks in the chain have the memory we need and if so return it.
	for( MemoryChunk* currentMemoryChunk = mMemoryChunkHead; currentMemoryChunk != NULL; currentMemoryChunk = currentMemoryChunk->nextChunk )
		{
		char* possibleReturnValue = currentMemoryChunk->TryToAllocate( size );
		if(possibleReturnValue != NULL)
			return possibleReturnValue;

		lastMemoryChunkInChain = currentMemoryChunk;
		}

	// Get a suitable new chunk ensuring we can get our memory from it.
	MemoryChunk* newMemoryChunk = allocateAndInitializeChunk(size);
	char* returnValue = newMemoryChunk->TryToAllocate( size );
	if(returnValue == NULL)
		throw InternalException("mMemoryChunkHead->TryToAllocate( size ) should always sucseed here.");

	// Place the new meory chunk in the chain.
	if(lastMemoryChunkInChain != NULL)
		lastMemoryChunkInChain->nextChunk = newMemoryChunk;
	else
		mMemoryChunkHead = newMemoryChunk;

	return returnValue;
	}
예제 #5
0
	_ObjectBase* _HiddenObject::asPointer(const char* baseName) {
		// If "list iterator couldn't be dereference" was reported,
		// That mean the object doesn't exist and there must be a bug
		if(!baseName)
			throw InternalException(CREATE_STANDARD_MESSAGE("baseName is null"));
		return pointers.find(Utility::getHiddenDirectBase(name.c_str(), baseName))->second;
	}
예제 #6
0
// Must be called with 'state_mutex' held.
void
ThreadPool::spawnSpareThreads ()
    throw (InternalException)
{
    unsigned long nthreads = spareThreads.getNumElements () +
			     busyThreads.getNumElements ();

    unsigned long tocreate = 0;

    if (nthreads < minThreads)
	tocreate = minThreads - nthreads;

    Ref<WorkerThread> workerThread;
    for (unsigned long i = 0; i < tocreate; i++) {
	try {
	    /* Throws InternalException */
	    workerThread = grab (new WorkerThread (this));

	    spareThreads.append (workerThread);
	} catch (Exception &exc) {
	    if (spareThreads.getNumElements () + busyThreads.getNumElements () == 0) {
		throw InternalException (
			String::forPrintTask (
				(Pr ("MyCpp.ThreadPool.spawnSpareThreads: "
				     "failed to spawn the first thread: "))
				(Pr (exc.getMessage ()))),
			exc.clone ());
	    } else {
		errf->print ("MyCpp.ThreadPool.spawnSpareThreads: "
			     "WARNING: failed to spawn a thread");
	    }
	}
    }
}
예제 #7
0
파일: Rail.cpp 프로젝트: Bubu/SWPSoSe14
 void check(t current, string const & name)
 {
   if (current < min || current > max)
   {
     throw InternalException(name + ": Invalid Rail: "
                             + railToString(current));
   }
 }
예제 #8
0
SHARED_LIBRARY_HANDLE PlatformLoadLibrary(const char* const name)
	{
    SHARED_LIBRARY_HANDLE handle = dlopen(name, RTLD_LAZY);
	if (handle == NULL) 
			{ 
			throw InternalException("FirebirdApiBinding::Initialize - Could not find or load the firebird client library."); 
			}
	return handle; 
	}
void SelectGlyphsAction::Do(DisplayDirector* director)
{
	TextDisplayNode* firstNode =
		dynamic_cast<TextDisplayNode*>(director->DisplayNodeFor(firstText));
	if (firstNode == NULL)
		throw InternalException("SelectGlyphsAction::Do: first TextDisplayNode doesn't exist.");
	Glyph* firstGlyph = firstNode->GlyphAtOffset(firstOffset);
	if (firstGlyph == NULL)
		throw InternalException("SelectGlyphsAction::Do: first glyph doesn't exist.");
	TextDisplayNode* lastNode =
		dynamic_cast<TextDisplayNode*>(director->DisplayNodeFor(lastText));
	if (lastNode == NULL)
		throw InternalException("SelectGlyphsAction::Do: last TextDisplayNode doesn't exist.");
	Glyph* lastGlyph = lastNode->GlyphAtOffset(lastOffset);
	if (lastGlyph == NULL)
		throw InternalException("SelectGlyphsAction::Do: last glyph doesn't exist.");
	director->SetSelection(new GlyphsSelection(GlyphRef(firstNode, firstGlyph), GlyphRef(lastNode, lastGlyph)));
}
int BlockableDisplayNode::LeftSpace()
{
	BlockableDisplayNode* parentNode = dynamic_cast<BlockableDisplayNode*>(parent);
	if (parentNode == NULL)
		throw InternalException("BlockableDisplayNode has non-block parent.");
	return
		parentNode->LeftSpace()
			+ GetPropertyInPixels("margin-left", false);
}
예제 #11
0
Ref<Vfs::StatData>
VfsPosix::stat (const char *_name)
    throw (InternalException)
{
    Ref<String> name = String::forPrintTask ((Pr (root_path)) (Pr ("/")) (Pr (_name)));

    struct stat stat_buf;

    int rv = ::stat (name->getData (), &stat_buf);
    if (rv == -1) {
	throw InternalException (errnoToString (errno));
    } else
    if (rv != 0)
	throw InternalException ();

    Ref<StatData> stat_data = grab (new StatData);

    if (S_ISBLK (stat_buf.st_mode))
	stat_data->file_type = FileType_BlockDevice;
    else
    if (S_ISCHR (stat_buf.st_mode))
	stat_data->file_type = FileType_CharacterDevice;
    else
    if (S_ISDIR (stat_buf.st_mode))
	stat_data->file_type = FileType_Directory;
    else
    if (S_ISFIFO (stat_buf.st_mode))
	stat_data->file_type = FileType_Fifo;
    else
    if (S_ISREG (stat_buf.st_mode))
	stat_data->file_type = FileType_RegularFile;
    else
    if (S_ISLNK (stat_buf.st_mode))
	stat_data->file_type = FileType_SymbolicLink;
    else
    if (S_ISSOCK (stat_buf.st_mode))
	stat_data->file_type = FileType_Socket;
    else
	throw InternalException ();

    stat_data->size = (unsigned long long) stat_buf.st_size;

    return stat_data;
}
Element* EmptyPlaceholderSelection::GetElement()
{
	for (DisplayNode* node = textNode->Parent(); node; node = node->Parent()) {
		ElementDisplayNode* elementNode = dynamic_cast<ElementDisplayNode*>(node);
		if (elementNode)
			return elementNode->GetElement();
		}
	if (useAssertions)
		throw InternalException("EmptyPlaceholderSelection: parent isn't an ElementDisplayNode.");
	return NULL;
}
예제 #13
0
Ref<String>
VfsPosix::Directory::getNextEntry ()
    throw (InternalException)
{
    ArrayHolder<unsigned char> dirent_array (sizeof (struct dirent) + NAME_MAX + 1);
    struct dirent * const dirent = (struct dirent*) &dirent_array [0];
    struct dirent *retp;

    int rv = readdir_r (dir, dirent, &retp);
    if (rv != 0)
	throw InternalException (errnoToString (rv));

    if (retp == NULL)
	return NULL;

    if (retp != dirent)
	throw InternalException ();

    return grab (new String (dirent->d_name));
}
예제 #14
0
void RectMatrixRowCol::Divide(const RectMatrixRowCol& rmrc, Real r)
{
   REPORT
   int i = n; Real* s = store; int d = spacing;
   Real* s1 = rmrc.store; int d1 = rmrc.spacing;
   if (i!=rmrc.n)
   {
      Tracer tr("newmatrm");
      Throw(InternalException("Dimensions differ in Divide"));
   }
   if (i) for (;;) { *s = *s1 / r; if (!(--i)) break; s += d; s1 += d1; }
}
예제 #15
0
파일: Rail.cpp 프로젝트: Bubu/SWPSoSe14
 Dir::t railToDirForward(t current)
 {
   static Dir::t result[] = {Dir::east, Dir::north, Dir::northeast,
                             Dir::southeast};
   check(current, "Rail::railToDirForward()");
   if (current == junction || current == rubble)
   {
     throw InternalException(
       "Rail::railToDirForward(): No inherent direction: "
       + railToString(current));
   }
   return result[current];
 }
예제 #16
0
Ref<AsyncFile>
VfsPosix::openAsyncFile (const char    *_filename,
			 unsigned long  open_flags,
			 AccessMode     access_mode)
    throw (InternalException)
{
    Ref<String> filename = String::forPrintTask ((Pr (root_path)) (Pr ("/")) (Pr (_filename)));

    try {
	return grab (static_cast <AsyncFile*> (new NativeAsyncFile (filename->getData (), open_flags, access_mode)));
    } catch (Exception &exc) {
	throw InternalException (String::nullString (), exc.clone ());
    }
}
예제 #17
0
파일: Rail.cpp 프로젝트: Bubu/SWPSoSe14
 Dir::t correctDirection(t current, Dir::t oldDir)
 {
   static const string functionName = "Rail::correctDirection()";
   check(current, functionName);
   Dir::check(oldDir, functionName);
   Dir::t result = oldDir;
   if (current == junction)
   {
     result = oldDir;
   }
   else if (current == rubble)
   {
     throw InternalException(functionName + ": Encountered rubble");
   }
   else
   {
     Dir::t forward = railToDirForward(current);
     Dir::t backward = railToDirBackward(current);
     if (oldDir == forward || oldDir == Dir::left(forward)
         || oldDir == Dir::right(forward))
     {
       result = forward;
     }
     else if (oldDir == backward || oldDir == Dir::left(backward)
              || oldDir == Dir::right(backward))
     {
       result = backward;
     }
     else
     {
       throw InternalException(functionName + ": Perpendicular direction: "
                               + railToString(current) + " -- "
                               + Dir::dirToString(oldDir));
     }
   }
   return result;
 }
예제 #18
0
Real RectMatrixRowCol::operator*(const RectMatrixRowCol& rmrc) const
{
   REPORT
   long_Real sum = 0.0; int i = n;
   Real* s = store; int d = spacing;
   Real* s1 = rmrc.store; int d1 = rmrc.spacing;
   if (i!=rmrc.n)
   {
      Tracer tr("newmatrm");
      Throw(InternalException("Dimensions differ in *"));
   }
   if (i) for(;;)
      { sum += (long_Real)*s * *s1; if (!(--i)) break; s += d; s1 += d1; }
   return (Real)sum;
}
예제 #19
0
파일: pdb.cpp 프로젝트: salilab/imp
void add_pdb_radii(Hierarchies hs) {
  for (unsigned int i = 0; i < hs.size(); ++i) {
    add_pdb_radii(hs[i]);
    canonicalize(hs[i]);
  }
  IMP_IF_CHECK(USAGE_AND_INTERNAL) {
    for (unsigned int i = 0; i < hs.size(); ++i) {
      if (!hs[i].get_is_valid(true)) {
        IMP_ERROR("Invalid hierarchy produced ");
        IMP_ERROR_WRITE(IMP::core::show<Hierarchy>(hs[i], IMP_STREAM));
        throw InternalException("Bad hierarchy");
        // should clean up
      }
    }
  }
}
예제 #20
0
void ComplexScale(RectMatrixCol& U, RectMatrixCol& V, Real x, Real y)
{
   REPORT
   int n = U.n;
   if (n != V.n)
   {
      Tracer tr("newmatrm");
      Throw(InternalException("Dimensions differ in ComplexScale"));
   }
   Real* u = U.store; Real* v = V.store; 
   int su = U.spacing; int sv = V.spacing;
   if (n) for (;;)
   {
      Real z = *u * x - *v * y;  *v =  *u * y + *v * x;  *u = z;
      if (!(--n)) break;
      u += su;  v += sv;
   }
}
예제 #21
0
void Rotate(RectMatrixCol& U, RectMatrixCol& V, Real tau, Real s)
{
   REPORT
   int n = U.n;
   if (n != V.n)
   {
      Tracer tr("newmatrm");
      Throw(InternalException("Dimensions differ in Rotate"));
   }
   Real* u = U.store; Real* v = V.store;
   int su = U.spacing; int sv = V.spacing;
   if (n) for(;;)
   {
      Real zu = *u; Real zv = *v;
      *u -= s * (zv + zu * tau); *v += s * (zu - zv * tau);
      if (!(--n)) break;
      u += su;  v += sv;
   }
}
예제 #22
0
/**
 * Sets mAuthSvcInfo member variable
 * Throws: InternalException upon error
 */
void
AgentProfileService::setAuthSvcInfo(std::string authURL)
{

    try {
        URL verifyURL(authURL);
    } catch (InternalException &iex) {
        throw InternalException("AuthService::setAuthSvcInfo()",
                                "Malformed URL.",
                                AM_AUTH_FAILURE);
    }

    mAuthSvcInfo.setFromString(authURL);
    Log::log(logModule, Log::LOG_MAX_DEBUG,
             "Number of servers in service:%d, '%s'.",
             mAuthSvcInfo.getNumberOfServers(), authURL.c_str());

    return;
}
예제 #23
0
    std::shared_ptr<TrainStrategy> TrainStrategy::create(
        algorithm::AAMAlgorithm alg, int channels)
    {
        std::shared_ptr<TrainStrategy> ptr;

        switch (alg)
        {
            case algorithm::conventional:
                ptr = std::make_shared<TrainConventional>(channels);
                break;
            case algorithm::inverseComposition:
                ptr = std::make_shared<TrainIC2D>(channels);
                break;
            default:
                throw InternalException();
        }

        return ptr;
    }
void DisplayDirector::SetupDisplayNodes()
	// to be called by any subclass' ctor, after the stylesheet is set up
{
	// find the document's DisplayNode
	docDisplayNode =
		dynamic_cast<DocumentDisplayNode*>(DisplayNodeFor(docSource->GetDocument()));
	if (docDisplayNode == NULL)
		throw InternalException("Couldn't get the DocumentDisplayNode!");

	// load
	docDisplayNode->Load(this);
	docDisplayNode->UpdateProperties();

	// layout
	docDisplayNode->BlockLayout();

	// notify the docSource (we do this *after* setting up the display nodes
	// so it will be able to set a selection, etc.)
	docSource->AttachedToDirector(this);
}
예제 #25
0
    void OnReadable(ServerInterface<TcpChannelCache<ChannelDataT, CacheSize> >* pInterface)
    {
        int dwRemainSize = CacheSize - pInterface->m_Channel.Data.dwCacheAvailableSize;
        if(dwRemainSize <= 0)
        {
            Disconnect();

            throw InternalException((boost::format("[%s:%d][error] package cache is full.") % __FILE__ % __LINE__).str().c_str());
        }

        IOBuffer ioRecvBuffer(&pInterface->m_Channel.Data.cPackageCache[pInterface->m_Channel.Data.dwCacheAvailableSize], 
                              dwRemainSize);
        pInterface->m_Channel >> ioRecvBuffer;

        if(ioRecvBuffer.GetReadSize() == 0)
        {
            Disconnect();
        }
        else
        {
            pInterface->m_Channel.Data.dwCacheAvailableSize += ioRecvBuffer.GetReadSize();

            IOBuffer in(pInterface->m_Channel.Data.cPackageCache, 
                        pInterface->m_Channel.Data.dwCacheAvailableSize,
                        pInterface->m_Channel.Data.dwCacheAvailableSize);
            this->OnMessage(pInterface->m_Channel, in);

            pInterface->m_Channel.Data.dwCacheAvailableSize = in.GetReadSize() - in.GetReadPosition();
            if(in.GetReadPosition() > 0 && pInterface->m_Channel.Data.dwCacheAvailableSize > 0)
            {
                memmove(pInterface->m_Channel.Data.cPackageCache, 
                        &pInterface->m_Channel.Data.cPackageCache[in.GetReadPosition()],
                        pInterface->m_Channel.Data.dwCacheAvailableSize);
            }
        }
    }
예제 #26
0
UnicharStream::UnicharResult
Utf8UnicharStream::doGetNextUnichar (Unichar * const ret_uc)
{
    char cbuf [7] = {};

    unsigned long i = 0;
    for (i = 0; i < 6; i++) {
	char c;
	ByteStream::ByteResult bres;
	bres = byte_stream->getNextByte (&c);
	if (bres == ByteStream::ByteEof) {
	    if (i != 0)
		break;

	    return UnicharEof;
	}

	if (bres != ByteStream::ByteNormal)
	    abortIfReached ();

	cbuf [i] = c;
	if (utf8_validate_sz (cbuf, NULL)) {
	    if (ret_uc != NULL)
		*ret_uc = utf8_valid_to_unichar (cbuf);

	    return UnicharNormal;
	}
    }

    errf->print ("Scruffy.Utf8UnicharStream: "
		 "input is not valid UTF-8")
	 .pendl ();

//    throw ParsingException (fpos);
    throw InternalException ();
}
예제 #27
0
void Codec20::checkForErrorsInResponseStatus(Transport& transport, HeaderParams& params, uint8_t status) const {
    try {
        switch (status) {
        case HotRodConstants::INVALID_MAGIC_OR_MESSAGE_ID_STATUS:
        case HotRodConstants::REQUEST_PARSING_ERROR_STATUS:
        case HotRodConstants::UNKNOWN_COMMAND_STATUS:
        case HotRodConstants::SERVER_ERROR_STATUS:
        case HotRodConstants::COMMAND_TIMEOUT_STATUS:
        case HotRodConstants::UNKNOWN_VERSION_STATUS: {
            // If error, the body of the message just contains a message
            std::string msgFromServer = transport.readString();
            if (msgFromServer.find("SuspectException") != std::string::npos || msgFromServer.find("SuspectedException") != std::string::npos) {
                // Handle both Infinispan's and JGroups' suspicions
                // TODO: This will be better handled with its own status id in version 2 of protocol
                throw RemoteNodeSuspectException(msgFromServer, params.messageId, status);
            } else {
                throw HotRodClientException(msgFromServer); //, params.messageId, status);
            }
        }
        default: {
            throw InternalException("Unknown status: " + status);
        }
        }
    } catch (const Exception &) {
        // Some operations require invalidating the transport
        switch (status) {
        case HotRodConstants::INVALID_MAGIC_OR_MESSAGE_ID_STATUS:
        case HotRodConstants::REQUEST_PARSING_ERROR_STATUS:
        case HotRodConstants::UNKNOWN_COMMAND_STATUS:
        case HotRodConstants::UNKNOWN_VERSION_STATUS: {
            transport.invalidate();
        }
        }
        throw;
    }
}
void GlyphsSelection::AcceptKey(string_slice key, DisplayDirector* director)
{
	int offset;

	if (tagEditor || key == "\t")
		TagSelection::AcceptKey(key, director);
	else if (key == "\n") {
		// not supported yet
		/***/
		}
	else if (key == Keys::LeftArrowKey) {
		offset = firstGlyph.textNode->OffsetOfGlyph(firstGlyph.glyph);
		director->SetSelection(firstGlyph.textNode->GetSelectionAtOffset(offset));
		director->ScrollToSelection();
		}
	else if (key == Keys::RightArrowKey) {
		offset = lastGlyph.textNode->OffsetOfGlyph(lastGlyph.glyph) +
			lastGlyph.glyph->NumCharsInText();
		director->SetSelection(lastGlyph.textNode->GetSelectionAtOffset(offset));
		director->ScrollToSelection();
		}
	else {
		String newText = key;
		if (key == "\b" || key == Keys::DelKey)
			newText = "";
		ReplaceText(newText, director);
#ifdef NOT_ANYMORE
		// set up
		DisplayNode* ancestor = firstGlyph.CommonAncestorWith(lastGlyph);
		if (ancestor == NULL)
			throw InternalException("GlyphsSelection::AcceptKey: No common ancestor.");
		bool hasFirstText = (firstGlyph.textNode->Parent() == ancestor);
		bool hasLastText = (lastGlyph.textNode->Parent() == ancestor);
		bool oneText = (firstGlyph.textNode == lastGlyph.textNode);
		bool hasNodes =
			(!oneText &&
				(!hasFirstText || !hasLastText ||
				 firstGlyph.textNode->NextSibling() != firstGlyph.textNode));
		CompositeAction* action = new CompositeAction();
		action->AddAction(new RestoreGlyphsSelectionAction());
		// clear out anything that's there
		if (oneText) {
			unsigned long startOffset = firstGlyph.StartOffset();
			action->AddAction(new DeleteCharsAction(firstGlyph.textNode->GetText(),
			                                        startOffset,
			                                        lastGlyph.EndOffset() - startOffset));
			}
		else {
			if (hasFirstText) {
				Text* firstText = firstGlyph.textNode->GetText();
				unsigned long offset = firstGlyph.StartOffset();
				action->AddAction(new DeleteCharsAction(firstText, offset,
				                                        firstText->Length() - offset));
				}
			if (hasLastText) {
				action->AddAction(new DeleteCharsAction(lastGlyph.textNode->GetText(),
				                                        0, lastGlyph.EndOffset()));
				}
			if (hasNodes) {
				ElementDisplayNode* ancestorDisplayNode = dynamic_cast<ElementDisplayNode*>(ancestor);
				if (ancestorDisplayNode == NULL)
					throw InternalException("GlyphsSelection::AcceptKey: ancestor isn't an element.");
				Element* ancestorElement = ancestorDisplayNode->GetElement();
				Node* firstDeleteNode = firstGlyph.textNode->GetText();
				while (firstDeleteNode->ParentNode() != ancestorElement)
					firstDeleteNode = firstDeleteNode->ParentNode();
				if (hasFirstText)
					firstDeleteNode = firstDeleteNode->NextSibling();
				Node* lastDeleteNode = lastGlyph.textNode->GetText();
				while (lastDeleteNode->ParentNode() != ancestorElement)
					lastDeleteNode = lastDeleteNode->ParentNode();
				if (hasLastText)
					lastDeleteNode = lastDeleteNode->PreviousSibling();
				action->AddAction(new RemoveNodesAction(firstDeleteNode, lastDeleteNode));
				}
			}
		// add in the key
		if (key == "\b" || key == Keys::DelKey) {
			// just select
			Text* selectText = NULL;
			unsigned long selectOffset = 0;
			if (oneText || hasFirstText) {
				selectText = firstGlyph.textNode->GetText();
				selectOffset = firstGlyph.StartOffset();
				}
			else if (hasLastText) {
				selectText = lastGlyph.textNode->GetText();
				selectOffset = 0;
				}
			else {
				// we don't handle this yet (point selection between two Elements)
				/***/
				}
			if (selectText)
				action->AddAction(new SelectPointAction(selectText, selectOffset));
			}
		else {
			Text* destText;
			unsigned long destOffset;
			if (oneText || hasFirstText) {
				destText = firstGlyph.textNode->GetText();
				destOffset = firstGlyph.StartOffset();
				}
			else if (hasLastText) {
				destText = lastGlyph.textNode->GetText();
				destOffset = 0;
				}
			else {
				NewTextAction* newTextAction =
					new NewTextAction(firstGlyph.textNode->GetText()->OwnerDocument());
				action->AddAction(newTextAction);
				destText = newTextAction->GetText();
				destOffset = 0;
				}
			action->AddAction(new AddCharsAction(key, destText, destOffset));
				// this will do the selection also
			}
		// go!
		director->DoAction(action);
#endif
		}
}
void GlyphsSelection::ReplaceText(String newText, DisplayDirector* director)
{
	// set up
	DisplayNode* ancestor = firstGlyph.CommonAncestorWith(lastGlyph);
	if (ancestor == NULL)
		throw InternalException("GlyphsSelection::AcceptKey: No common ancestor.");
	bool hasFirstText = (firstGlyph.textNode->Parent() == ancestor);
	bool hasLastText = (lastGlyph.textNode->Parent() == ancestor);
	bool oneText = (firstGlyph.textNode == lastGlyph.textNode);
	bool hasNodes =
		(!oneText &&
			(!hasFirstText || !hasLastText ||
			 firstGlyph.textNode->NextSibling() != firstGlyph.textNode));
	CompositeAction* action = new CompositeAction();
	action->AddAction(new RestoreGlyphsSelectionAction());

	// clear out anything that's there
	if (oneText) {
		unsigned long startOffset = firstGlyph.StartOffset();
		action->AddAction(new DeleteCharsAction(firstGlyph.textNode->GetText(),
		                                        startOffset,
		                                        lastGlyph.EndOffset() - startOffset));
		}
	else {
		if (hasFirstText) {
			Text* firstText = firstGlyph.textNode->GetText();
			unsigned long offset = firstGlyph.StartOffset();
			action->AddAction(new DeleteCharsAction(firstText, offset,
			                                        firstText->Length() - offset));
			}
		if (hasLastText) {
			action->AddAction(new DeleteCharsAction(lastGlyph.textNode->GetText(),
			                                        0, lastGlyph.EndOffset()));
			}
		if (hasNodes) {
			ElementDisplayNode* ancestorDisplayNode = dynamic_cast<ElementDisplayNode*>(ancestor);
			if (ancestorDisplayNode == NULL)
				throw InternalException("GlyphsSelection::AcceptKey: ancestor isn't an element.");
			Element* ancestorElement = ancestorDisplayNode->GetElement();
			Node* firstDeleteNode = firstGlyph.textNode->GetText();
			while (firstDeleteNode->ParentNode() != ancestorElement)
				firstDeleteNode = firstDeleteNode->ParentNode();
			if (hasFirstText)
				firstDeleteNode = firstDeleteNode->NextSibling();
			Node* lastDeleteNode = lastGlyph.textNode->GetText();
			while (lastDeleteNode->ParentNode() != ancestorElement)
				lastDeleteNode = lastDeleteNode->ParentNode();
			if (hasLastText)
				lastDeleteNode = lastDeleteNode->PreviousSibling();
			action->AddAction(new RemoveNodesAction(firstDeleteNode, lastDeleteNode));
			}
		}

	// if we're replacing it with nothing, just select the point
	if (newText.empty()) {
		// just select
		Text* selectText = NULL;
		unsigned long selectOffset = 0;
		if (oneText || hasFirstText) {
			selectText = firstGlyph.textNode->GetText();
			selectOffset = firstGlyph.StartOffset();
			}
		else if (hasLastText) {
			selectText = lastGlyph.textNode->GetText();
			selectOffset = 0;
			}
		else {
			// we don't handle this yet (point selection between two Elements)
			/***/
			}
		if (selectText)
			action->AddAction(new SelectPointAction(selectText, selectOffset));
		}

	// add in the new text
	else {
		Text* destText;
		unsigned long destOffset;
		if (oneText || hasFirstText) {
			destText = firstGlyph.textNode->GetText();
			destOffset = firstGlyph.StartOffset();
			}
		else if (hasLastText) {
			destText = lastGlyph.textNode->GetText();
			destOffset = 0;
			}
		else {
			NewTextAction* newTextAction =
				new NewTextAction(firstGlyph.textNode->GetText()->OwnerDocument());
			action->AddAction(newTextAction);
			destText = newTextAction->GetText();
			destOffset = 0;
			}
		action->AddAction(new AddCharsAction(newText, destText, destOffset));
			// this will do the selection also
		}

	// do it
	director->DoAction(action);
}
String GlyphsSelection::GetXMLCopy()
{
	// handle single-text case
	bool singleText = (firstGlyph.textNode == lastGlyph.textNode);
	if (singleText) {
		int startOffset = firstGlyph.StartOffset();
		int endOffset = lastGlyph.EndOffset();
		return firstGlyph.textNode->GetText()->SubstringData(startOffset, endOffset - startOffset);
		}

	// get info about the structure
	DisplayNode* ancestor = firstGlyph.CommonAncestorWith(lastGlyph);
	bool startsWithText = (firstGlyph.textNode->Parent() == ancestor);
	bool endsWithText = (lastGlyph.textNode->Parent() == ancestor);

	// find out where the first and last embedded elements are
	// first
	ElementDisplayNode* firstElementDisplayNode = NULL;
	if (!startsWithText) {
		// it's the element the first glyph is in
		DisplayNode* firstElementNode = firstGlyph.textNode;
		while (firstElementNode) {
			if (firstElementNode->Parent() == ancestor)
				break;
			firstElementNode = firstElementNode->Parent();
			}
		firstElementDisplayNode = dynamic_cast<ElementDisplayNode*>(firstElementNode);
		}
	else {
		firstElementDisplayNode =
			dynamic_cast<ElementDisplayNode*>(firstGlyph.textNode->NextSibling());
		}
	if (firstElementDisplayNode == NULL)
		throw InternalException("GlyphsSelection::GetXMLCopy: Couldn't find firstElementNode.");
	Node* firstElement = firstElementDisplayNode->GetElement();
	// last
	ElementDisplayNode* lastElementDisplayNode = NULL;
	if (!endsWithText) {
		// it's the element the last glyph is in
		DisplayNode* lastElementNode = lastGlyph.textNode;
		while (lastElementNode) {
			if (lastElementNode->Parent() == ancestor)
				break;
			lastElementNode = lastElementNode->Parent();
			}
		lastElementDisplayNode = dynamic_cast<ElementDisplayNode*>(lastElementNode);
		}
	else {
		lastElementDisplayNode =
			dynamic_cast<ElementDisplayNode*>(lastGlyph.textNode->PreviousSibling());
		}
	if (lastElementDisplayNode == NULL)
		throw InternalException("GlyphsSelection::GetXMLCopy: Couldn't find lastElementNode.");
	Node* lastElement = lastElementDisplayNode->GetElement();

	// write the selection
	XMLStringWriter writer(NULL);
	if (startsWithText) {
		Text* startText = firstGlyph.textNode->GetText();
		int startOffset = firstGlyph.StartOffset();
		String startData =
			startText->SubstringData(startOffset, startText->Length() - startOffset);
		writer.AppendString(startData);
		}
	for (Node* node = firstElement; ; node = node->NextSibling()) {
		writer.AppendNode(node);
		if (node == lastElement)
			break;
		}
	if (endsWithText) {
		Text* endText = lastGlyph.textNode->GetText();
		int endOffset = lastGlyph.EndOffset();
		String endData = endText->SubstringData(0, endOffset);
		writer.AppendString(endData);
		}
	return writer.GetString();
}