Example #1
0
void
TextSelection::Insert (TextElement *element)
{
    if (anchor.GetParent() == NULL || moving.GetParent() == NULL)
        // if either are null we're going nowhere fast...
        return;

    // refactor out the "clear out selection" from SetText
    ClearSelection ();

    // at this point both anchor and moving are the same location

    // depending on what the anchor's parent is,
    // and what @element is, we might need to
    // split the tree higher up
    DependencyObject *el = anchor.GetParent ();
    int loc = anchor.ResolveLocation();

    while (el) {
        DependencyObject *el_parent = el->GetParent();
        if (el_parent)
            el_parent = el_parent->GetParent();

        IDocumentNode *node = IDocumentNode::CastToIDocumentNode (el);

        DependencyObjectCollection *children = node->GetDocumentChildren ();
        if (children && element->Is (children->GetElementType())) {
            // we can insert the element here, so let's do it and be done with things
            children->Insert (loc, element);
            return;
        }

        if (!el_parent) {
            g_warning ("new element cannot fit inside element, and we can't split it");
            return;
        }

        // we need to split the current element at
        // @loc, add the new element to el's parent
        // after el, and walk back up to el's parent
        // with new_el's index as @loc.
        IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (el_parent);
        DependencyObjectCollection *parents_children = parent_node ? parent_node->GetDocumentChildren () : NULL;
        DependencyObject *new_el = node ? node->Split (loc) : NULL;

        if (!new_el) {
            g_warning ("split failed");
            return;
        }

        int new_el_loc = parents_children->IndexOf (el) + 1;
        parents_children->Insert (new_el_loc, new_el);
        el = el_parent;
        loc = new_el_loc;
        new_el->unref ();
    }


    printf ("TextSelection::Insert\n");
}
Example #2
0
DocumentWalker::StepType
DocumentWalker::Step (IDocumentNode **node_return)
{
	DependencyObjectCollection *children = node->GetDocumentChildren();
	if (direction == DocumentWalker::Forward) {
		if (children && children->GetCount() > child_index) {
			// 1) if node is a container, step into the child
			node = IDocumentNode::CastToIDocumentNode (children->GetValueAt (child_index)->AsTextElement());
			child_index = 0;
			if (node_return)
				*node_return = node;
			return Enter;
		}
		else {
			// 2) if it's not a container, then we walk up a level, step out of this node
			IDocumentNode *parent_node = node->GetParentDocumentNode();
			if (parent_node == NULL)
				return Done;

			DependencyObjectCollection *parent_children= parent_node->GetDocumentChildren();
			int i = parent_children->IndexOf (node->AsDependencyObject());

			if (node_return)
				*node_return = node;

			child_index = i + 1;
			node = parent_node;
			return Leave;
		}
	}
	else {
		if (children && children->GetCount() > child_index && child_index >= 0) {
			// 1) if node is a container, step into the child
			node = IDocumentNode::CastToIDocumentNode (children->GetValueAt (child_index)->AsTextElement());
			children = node->GetDocumentChildren ();
			child_index = children ? children->GetCount() - 1 : 0;
			if (node_return)
				*node_return = node;
			return Enter;
		}
		else {
			// 2) if it's not a container, then we walk up a level, step out of this node
			IDocumentNode *parent_node = node->GetParentDocumentNode();
			if (parent_node == NULL)
				return Done;

			DependencyObjectCollection *parent_children= parent_node->GetDocumentChildren();
			int i = parent_children->IndexOf (node->AsDependencyObject());

			if (node_return)
				*node_return = node;

			child_index = i - 1;
			node = parent_node;
			return Leave;
		}
	}
}
Example #3
0
void
TextSelection::SetText (const char *text)
{
#define CONTENT_START (0)
#define CONTENT_END ((guint32)-1)

	if (anchor.GetParent() == NULL || moving.GetParent() == NULL)
		// if either are null we're going nowhere fast...
		return;

	ClearSelection ();

	// at this point the selection is empty and anchor == moving
	if (text && *text) {
		if (anchor.GetParent()->Is (Type::RUN)) {
			const char *run_text = ((Run*)anchor.GetParent())->GetText();
			if (run_text == NULL)
				run_text = "\0";

			char *new_text = (char*)g_malloc0 (strlen (run_text) + strlen (text) + 1);

			if (strlen (text) < (size_t) anchor.ResolveLocation ()){
				// #339RT enters here
				g_free (new_text);
				new_text = g_strdup ("BUGBUGBUG");
			} else {
				strncpy (new_text, run_text, anchor.ResolveLocation());
				strcpy (new_text + anchor.ResolveLocation(), text);
				strncpy (new_text + anchor.ResolveLocation() + strlen(text), run_text + anchor.ResolveLocation(), strlen (run_text) - anchor.ResolveLocation());
			}

			((Run*)anchor.GetParent())->SetText (new_text);

			if (moving.GetLocation() > strlen (new_text)) {
				anchor = TextPointer (anchor.GetParent(), CONTENT_END, anchor.GetLogicalDirection());
				moving = TextPointer (anchor.GetParent(), CONTENT_END, anchor.GetLogicalDirection());
			}
			else {
				TextPointer new_anchor (anchor.GetParent(), anchor.ResolveLocation () + strlen (text), anchor.GetLogicalDirection());
				moving = TextPointer (anchor.GetParent(), anchor.ResolveLocation () + strlen (text), anchor.GetLogicalDirection());
				anchor = new_anchor;
			}

			g_free (new_text);

			if (anchor.CompareTo_np (moving) < 0) {
				start = anchor;
				end = moving;
			}
			else {
				start = moving;
				end = anchor;
			}
		}
		else {
			IDocumentNode *node = anchor.GetParentNode();
			DependencyObjectCollection *children = node->GetDocumentChildren();

			if (!children) {
				// this can happen when anchor is in an InlineUIContainer.
				printf ("NIEX TextSelection.SetText for anchor == InlineUIContainer.\n");
				return;
			}

			Run *r = MoonUnmanagedFactory::CreateRun ();
			r->SetText (text);

			if (children->Is(Type::BLOCK_COLLECTION)) {
				// the node takes Blocks as children, so we need to create a Paragraph first.
				Paragraph *p = MoonUnmanagedFactory::CreateParagraph();
				children->Insert (anchor.GetLocation(), Value (p));
				children = p->GetInlines();
				children->Add (Value (r));
				p->unref ();
			}
			else {
				children->Insert (anchor.GetLocation(), Value (r));
			}

			anchor = TextPointer (r, CONTENT_END, anchor.GetLogicalDirection());
			moving = TextPointer (r, CONTENT_END, anchor.GetLogicalDirection());
			r->unref ();

			if (anchor.CompareTo_np (moving) < 0) {
				start = anchor;
				end = moving;
			}
			else {
				start = moving;
				end = anchor;
			}
		}
	}

	g_free (this->text);
	this->text = NULL;
}
Example #4
0
void
TextSelection::Insert (TextElement *element)
{
	if (anchor.GetParent() == NULL || moving.GetParent() == NULL)
		// if either are null we're going nowhere fast...
		return;

	ClearSelection ();

	// at this point both anchor and moving are the same location

	// depending on what the anchor's parent is,
	// and what @element is, we might need to
	// split the tree higher up
	DependencyObject *el = anchor.GetParent ();
	int loc = anchor.ResolveLocation();

	while (el) {
		DependencyObject *el_parent = el->GetParent();
		if (el_parent)
			el_parent = el_parent->GetParent();

		IDocumentNode *node = IDocumentNode::CastToIDocumentNode (el);

		DependencyObjectCollection *children = node->GetDocumentChildren ();
		if (children && element->Is (children->GetElementType())) {
			// we can insert the element here, so let's do it and be done with things
			children->Insert (loc, element);
			return;
		}

		if (!el_parent) {
			g_warning ("new element cannot fit inside element, and we can't split it");
			return;
		}
				
		// we need to split the current element at
		// @loc, add the new element to el's parent
		// after el, and walk back up to el's parent
		// with new_el's index as @loc.
		IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (el_parent);
		DependencyObjectCollection *parents_children = parent_node ? parent_node->GetDocumentChildren () : NULL;

		if (parents_children == NULL)
			return; /* #rtx24 */

		DependencyObject *new_el;
		if (element->Is (el->GetObjectType()) /* a more precise check perhaps?  instead of subclass? */) {
			// we don't need to split the node.  we just
			// need to reach in and reparent children
			// after @loc into element.
			new_el = node ? node->Split (loc, element) : NULL;
		}
		else {
			new_el = node ? node->Split (loc) : NULL;
		}

		int new_el_loc = parents_children->IndexOf (el) + 1;

		if (new_el)
			parents_children->Insert (new_el_loc, new_el);

		el = el_parent;
		loc = new_el_loc;
		if (new_el && new_el != element)
			new_el->unref ();

		if (new_el == element) {
			// we've already inserted the element as part of the split.
			return;
		}
	}

	printf ("NIEX TextSelection::Insert\n");
}
Example #5
0
int
TextPointer::CompareToWithError (const TextPointer *pointer, MoonError *error) const
{
	if (!verify_textpointer_in_document (this, error) ||
	    !verify_textpointer_in_document (pointer, error))
		return -1;

	if (this->GetParent() == pointer->GetParent()) {
		DependencyObjectCollection *children = this->GetParentNode()->GetDocumentChildren();
		if (children && children->GetCount() > 0)
			return compare_locations (this->GetLocation(), pointer->GetLocation());
		else
			return this->ResolveLocation() - pointer->ResolveLocation();
	}
	else {
		GPtrArray *this_array = g_ptr_array_new();
		GPtrArray *pointer_array = g_ptr_array_new();

		DependencyObject *el = GetParent();
		while (el) {
			g_ptr_array_insert (this_array, 0, el);
			if (el->Is (Type::RICHTEXTBOX))
				break;
			el = el->GetParent() ? el->GetParent()->GetParent() : NULL;
			if (!el)
				break;
		}

		el = pointer->GetParent();
		while (el) {
			g_ptr_array_insert (pointer_array, 0, el);
			if (el->Is (Type::RICHTEXTBOX))
				break;
			el = el->GetParent() ? el->GetParent()->GetParent() : NULL;
			if (!el)
				break;
		}

		guint32 count_to_compare = MIN (this_array->len, pointer_array->len);

		for (guint32 i = 0; i < count_to_compare; i ++) {
			DependencyObject *this_el = (DependencyObject*)g_ptr_array_index (this_array, i);
			DependencyObject *pointer_el = (DependencyObject*)g_ptr_array_index (pointer_array, i);

			if (this_el == pointer_el)
				continue;

			if (i == 0) {
				// this shouldn't happen... there shouldn't be a difference between two paths on the first element, since that should always be a RTB
				int rv = this_array->len < pointer_array->len ? -1 : 1;
				g_ptr_array_free (this_array, TRUE);
				g_ptr_array_free (pointer_array, TRUE);
				return rv;
			}

			/* at this point this_el and pointer_el are
			   different.  check index i-1's idea of their
			   positions */
			DependencyObject *common_parent = (DependencyObject*)g_ptr_array_index (this_array, i-1);
			IDocumentNode *common_parent_node = IDocumentNode::CastToIDocumentNode (common_parent);
			int this_index = common_parent_node->GetDocumentChildren()->IndexOf (Value (this_el));
			int pointer_index = common_parent_node->GetDocumentChildren()->IndexOf (Value (pointer_el));
			g_ptr_array_free (this_array, TRUE);
			g_ptr_array_free (pointer_array, TRUE);
			return this_index < pointer_index ? -1 : 1;
		}

		// if we make it here, it means we've run through
		// "count_to_compare" items that were identical, and
		// one of the paths is longer (so represents a child
		// of items[count_to_compare].

		// so we need to figure out which array has more
		// elements, then compare that against the other
		// TextPointer's location

		if (count_to_compare < this_array->len) {
			// @this's parent is a child of pointer_array[count_to_compare-1]
			DependencyObject *parent = (DependencyObject*)g_ptr_array_index(pointer_array, count_to_compare - 1);
			IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent);
			guint32 child_index = parent_node->GetDocumentChildren()->IndexOf (Value ((DependencyObject*)g_ptr_array_index(this_array, count_to_compare)));

			return pointer->GetLocation() > child_index ? -1 : 1;
		}
		else if (count_to_compare < pointer_array->len) {
			// @pointer's parent is a child of this_array[count_to_compare-1]
			DependencyObject *parent = (DependencyObject*)g_ptr_array_index(this_array, count_to_compare - 1);
			IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent);
			guint32 child_index = parent_node->GetDocumentChildren()->IndexOf (Value ((DependencyObject*)g_ptr_array_index(pointer_array, count_to_compare)));

			return child_index >= this->GetLocation () ? -1 : 1;
		}
	}
	return -1;
}