Gwen::Rect Text::GetCharacterPosition( int iChar ) { if ( !m_Lines.empty() ) { TextLines::iterator it = m_Lines.begin(); TextLines::iterator itEnd = m_Lines.end(); int iChars = 0; while ( it != itEnd ) { Text* pLine = *it; ++it; iChars += pLine->Length(); if ( iChars <= iChar ) { continue; } iChars -= pLine->Length(); Gwen::Rect rect = pLine->GetCharacterPosition( iChar - iChars ); rect.x += pLine->X(); rect.y += pLine->Y(); return rect; } } if ( Length() == 0 || iChar == 0 ) { Gwen::Point p = GetSkin()->GetRender()->MeasureText( GetFont(), L" " ); return Gwen::Rect( 1, 0, 0, p.y ); } UnicodeString sub = m_String.GetUnicode().substr( 0, iChar ); Gwen::Point p = GetSkin()->GetRender()->MeasureText( GetFont(), sub ); return Rect( p.x, 0, 0, p.y ); }
/// Returns the size required by a call to RenderText if it were to be done now. Vector2f TextFont::CalculateRenderSizeUnits(Text & text) { if (text.Length() < 1) { return Vector2f(scale[0], scale[1]); } // Set starting variables. NewText(text); // Go up to and include the NULL-sign! for (int i = 0; i < text.ArraySize(); ++i) { currentCharIndex = i; currentChar = text.c_str()[i]; if (currentChar == '\0') { EndText(); break; } nextChar = text.c_str()[i + 1]; if (EvaluateSpecialChar()) continue; StartChar(); // RenderChar(); EndChar(); lastChar = currentChar; } return Vector2f (maxRowSizeX, AbsoluteValue(pivotPoint.y)); }
int Text::GetClosestCharacter( Gwen::Point p ) { if ( !m_Lines.empty() ) { TextLines::iterator it = m_Lines.begin(); TextLines::iterator itEnd = m_Lines.end(); int iChars = 0; while ( it != itEnd ) { Text* pLine = *it; ++it; iChars += pLine->Length(); if ( p.y < pLine->Y() ) continue; if ( p.y > pLine->Bottom() ) continue; iChars -= pLine->Length(); int iLinePos = pLine->GetClosestCharacter( Gwen::Point( p.x - pLine->X(), p.y - pLine->Y() ) ); //if ( iLinePos > 0 && iLinePos == pLine->Length() ) iLinePos--; iLinePos--; return iChars + iLinePos; } } int iDistance = 4096; int iChar = 0; for ( size_t i=0; i<m_String.GetUnicode().length()+1; i++ ) { Gwen::Rect cp = GetCharacterPosition( i ); int iDist = abs(cp.x - p.x) + abs(cp.y - p.y); // this isn't proper if ( iDist > iDistance ) continue; iDistance = iDist; iChar = i; } return iChar; }
int Text::GetEndCharFromLine( int i ) { int iStart = GetStartCharFromLine( i ); Text* iLine = GetLine( i ); if ( iLine ) { iStart += iLine->Length(); } return Gwen::Clamp( iStart, 0, Length() ); }
int Text::GetStartCharFromLine( int i ) { TextLines::iterator it = m_Lines.begin(); TextLines::iterator itEnd = m_Lines.end(); int iChars = 0; while ( it != itEnd ) { Text* pLine = *it; ++it; if ( i == 0 ) return Gwen::Clamp( iChars, 0, Length() ); iChars += pLine->Length(); i--; } return Gwen::Clamp( iChars, 0, Length() ); }
Text KeyCompositionManager::GetComposedKeySym(const Text &t, bool &continueComposing) { Text *tt = (Text *)&t; for (int i=0; i<paths->Count(); i++) { Text &pathComposition = (*paths)[i]->Composition(); if (pathComposition.StartsWith(t) && pathComposition.Length() > tt->Length()) { continueComposing = true; return ""; } else if (pathComposition == t) { continueComposing = false; return (*paths)[i]->Result(); } } continueComposing = false; return t; }
int Text::GetLineFromChar( int i ) { TextLines::iterator it = m_Lines.begin(); TextLines::iterator itEnd = m_Lines.end(); int iChars = 0; int iLine = 0; while ( it != itEnd ) { Text* pLine = *it; ++it; iChars += pLine->Length(); if ( iChars > i ) return iLine; iLine++; } return iLine; }
already_AddRefed<XPathResult> XPathExpression::EvaluateWithContext(nsINode& aContextNode, uint32_t aContextPosition, uint32_t aContextSize, uint16_t aType, XPathResult* aInResult, ErrorResult& aRv) { if (aContextPosition > aContextSize) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } if (aType > XPathResult_Binding::FIRST_ORDERED_NODE_TYPE) { aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return nullptr; } if (!nsContentUtils::LegacyIsCallerNativeCode() && !nsContentUtils::CanCallerAccess(&aContextNode)) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return nullptr; } if (mCheckDocument) { nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument); if (doc != aContextNode.OwnerDoc()) { aRv.Throw(NS_ERROR_DOM_WRONG_DOCUMENT_ERR); return nullptr; } } uint16_t nodeType = aContextNode.NodeType(); if (nodeType == nsINode::TEXT_NODE || nodeType == nsINode::CDATA_SECTION_NODE) { Text* textNode = aContextNode.GetAsText(); MOZ_ASSERT(textNode); uint32_t textLength = textNode->Length(); if (textLength == 0) { aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return nullptr; } // XXX Need to get logical XPath text node for CDATASection // and Text nodes. } else if (nodeType != nsINode::DOCUMENT_NODE && nodeType != nsINode::ELEMENT_NODE && nodeType != nsINode::ATTRIBUTE_NODE && nodeType != nsINode::COMMENT_NODE && nodeType != nsINode::PROCESSING_INSTRUCTION_NODE) { aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return nullptr; } nsAutoPtr<txXPathNode> contextNode(txXPathNativeNode::createXPathNode(&aContextNode)); if (!contextNode) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } EvalContextImpl eContext(*contextNode, aContextPosition, aContextSize, mRecycler); RefPtr<txAExprResult> exprResult; aRv = mExpression->evaluate(&eContext, getter_AddRefs(exprResult)); if (aRv.Failed()) { return nullptr; } uint16_t resultType = aType; if (aType == XPathResult::ANY_TYPE) { short exprResultType = exprResult->getResultType(); switch (exprResultType) { case txAExprResult::NUMBER: resultType = XPathResult::NUMBER_TYPE; break; case txAExprResult::STRING: resultType = XPathResult::STRING_TYPE; break; case txAExprResult::BOOLEAN: resultType = XPathResult::BOOLEAN_TYPE; break; case txAExprResult::NODESET: resultType = XPathResult::UNORDERED_NODE_ITERATOR_TYPE; break; case txAExprResult::RESULT_TREE_FRAGMENT: aRv.Throw(NS_ERROR_FAILURE); return nullptr; } } RefPtr<XPathResult> xpathResult = aInResult; if (!xpathResult) { xpathResult = new XPathResult(&aContextNode); } aRv = xpathResult->SetExprResult(exprResult, resultType, &aContextNode); return xpathResult.forget(); }
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(); }
/// Renders text ^^ void TextFont::RenderText(Text & text, GraphicsState & graphicsState) { // Set starting variables. NewText(text); /// One color for all text? this->SetColor(text.color); /// Save old shader! Shader * oldShader = ActiveShader(); // Load shader, set default uniform values, etc. if (!PrepareForRender()) return; /// Sort the carets in order to render selected text properly. int min, max; if (text.caretPosition < text.previousCaretPosition) { min = text.caretPosition; max = text.previousCaretPosition; } else { max = text.caretPosition; min = text.previousCaretPosition; } bool shouldRenderCaret = Timer::GetCurrentTimeMs() % 1000 > 500; if (text.Length() == 0 && shouldRenderCaret) RenderChar('|'); for (i = 0; i < text.Length(); ++i) { if (text.caretPosition == i && shouldRenderCaret) { RenderChar('|'); } currentCharIndex = i; currentChar = text.c_str()[i]; if (currentChar == 0) break; nextChar = text.c_str()[i + 1]; if (EvaluateSpecialChar()) continue; StartChar(); // Move in. RenderChar(currentChar); // Render /// If we are between the 2 active carets, render the region the char covers over with a white quad ? if (text.previousCaretPosition != -1 && i >= min && i < max) { RenderSelection(currentChar); } EndChar(); // Move out. lastChar = currentChar; } // Caret at the end? if (text.caretPosition >= text.Length() && shouldRenderCaret) { RenderChar('|'); } OnEndRender(graphicsState); /// Revert to old shader! ShadeMan.SetActiveShader(oldShader); }