Пример #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");
}
Пример #2
0
void
TextSelection::ClearSelection ()
{
	// clear out the selection
	if (anchor.GetParent() == moving.GetParent()) {
		bool remove_element = false;

		if (anchor.GetLocation () != moving.GetLocation()) {

			if (anchor.GetParent()->Is (Type::RUN)) {
				Run *run = (Run*)anchor.GetParent();
				char *run_text = g_strdup (run->GetText());

				if (run_text) {
					int length_to_remove = moving.ResolveLocation() - anchor.ResolveLocation();
					
					memmove (run_text + anchor.ResolveLocation(), run_text + moving.ResolveLocation (), strlen (run_text + moving.ResolveLocation()));
					*(run_text + strlen(run_text) - length_to_remove) = 0;

					run->SetText (run_text);

					// we need to remove the run if we've cleared all the text in it
					remove_element = !*run_text;
				} 
				else {
					remove_element = true;
				}
				g_free (run_text);
			}
			else {
				IDocumentNode *node = anchor.GetParentNode();

				int length_to_remove = moving.ResolveLocation() - anchor.ResolveLocation();

				for (int i = 0; i < length_to_remove; i ++)
					node->GetDocumentChildren()->RemoveAt (anchor.ResolveLocation());

				// we need to remove the element if we've removed all the children
				remove_element = node->GetDocumentChildren()->GetCount() == 0;
			}
		}

		DependencyObject *el = anchor.GetParent();
		while (remove_element) {
			if (el->Is (Type::RICHTEXTBOX))
				break;

			DependencyObject* parent = el->GetParent() ? el->GetParent()->GetParent() : NULL;
			if (!parent) {
				g_warning ("shouldn't happen");
				return;
			}

			IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent);
			parent_node->GetDocumentChildren()->Remove (Value(el));

			el = parent;
			remove_element = parent_node->GetDocumentChildren()->GetCount() == 0;
		}
	}
	else {
		// harder case, anchor/moving are in different elements
		printf ("NIEX hard case TextSelection::ClearSelection\n");
	}

	g_free (text);
	text = NULL;

	g_free (xaml);
	xaml = NULL;
}
Пример #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;
}
Пример #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");
}
Пример #5
0
bool
PositionAtOffsetIterator::Step (int *offset)
{
	if (element == NULL)
		return false;

	if (*offset == 0) {
		// we're done stepping.  element/location should be valid.
		return false;
	}

	if (*offset < 0) {
		// we're stepping backward

		if (location == CONTENT_START) {
			// we're stepping backward but we're currently
			// at element's ContentStart.  we need to step
			// up into our parent
			DependencyObject *parent = GetElementParent();

			if (!parent) {
				// we can't back up anymore.  result is NULL.
				element = NULL;
				return true;
			}

			IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent);
			(*offset) ++;	
			location = parent_node->GetDocumentChildren()->IndexOf (Value (element));
			element = parent;
			return true;
		}

		if (element->Is (Type::RUN)) {
			const char *text = ((Run*)element)->GetText();
			guint32 textlen = strlen (text);

			if (location == CONTENT_END)
				location = textlen;

			if (location + *offset < CONTENT_START) {
				// bump up to the parent after adding the location to our offset
				*offset += location;
				location = CONTENT_START;
				return true;
			}
			else {
				// the operation can be satisfied completely inside this run
				location += *offset;
				*offset = 0;
				return false;
			}
		}
		else {
			IDocumentNode *node = IDocumentNode::CastToIDocumentNode (element);
			DependencyObjectCollection *doc_children = node->GetDocumentChildren();
			int children_count = doc_children ? doc_children->GetCount() : 0;
			if (children_count) {
				if (location == CONTENT_END)
					location = children_count;

				element = node->GetDocumentChildren()->GetValueAt(location-1)->AsTextElement();
				(*offset) ++;
				location = CONTENT_END;
				return true;
			}
			else {
				// not a Run, but also doesn't have children
				DependencyObject *parent = GetElementParent();

				if (!parent) {
					// we can't back up anymore.  result is NULL.
					element = NULL;
					return true;
				}

				IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent);
				(*offset) ++;
				location = parent_node->GetDocumentChildren()->IndexOf (Value (element));
				element = parent;
				return true;
			}
		}
	}
	else /* if offset > 0 */ {
		if (location == CONTENT_END) {
			// we're stepping forward but we're currently
			// at element's ContentEnd.  we need to step
			// up into our parent
			DependencyObject *parent = GetElementParent();

			if (!parent) {
				// we can't step forward anymore.  result is NULL.
				element = NULL;
				return true;
			}

			IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent);
			(*offset) --;
			location = parent_node->GetDocumentChildren()->IndexOf (Value (element));
			if ((int)location == parent_node->GetDocumentChildren()->GetCount() - 1)
				location = CONTENT_END;
			else
				location ++;

			element = parent;
			return true;
		}

		if (element->Is (Type::RUN)) {
			const char *text = ((Run*)element)->GetText();

			if (text == NULL) {
				(*offset) --;
				location = CONTENT_END;
				return true;
			}

			guint32 textlen = strlen (text);

			if (location + *offset >= textlen) {
				// bump up to the parent after subtracting the remaining length of the run from offset
				*offset = location + *offset - textlen;
				location = CONTENT_END;
				return true;
			}
			else {
				// the operation can be satisfied completely inside this run
				location += *offset;
				*offset = 0;
				return false;
			}
		}
		else {
			IDocumentNode *node = IDocumentNode::CastToIDocumentNode (element);
			DependencyObjectCollection *doc_children = node->GetDocumentChildren();
			int children_count = doc_children ? doc_children->GetCount() : 0;

			if (children_count > 0) {
				if ((int)location > children_count - 1) {
					DependencyObject *parent = GetElementParent();

					if (!parent) {
						// we can't step forward anymore.  result is NULL.
						element = NULL;
						return true;
					}

					IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent);
					(*offset) --;
					location = parent_node->GetDocumentChildren()->IndexOf (Value (element)) + 1;
					if ((int)location == children_count - 1)
						location = CONTENT_END;
					element = parent;
					return true;
				}
				else {
					element = node->GetDocumentChildren()->GetValueAt(location)->AsTextElement();
					(*offset) --;
					location = CONTENT_START;
					return true;
				}
			}
			else {
				// not a Run, but also doesn't have children
				DependencyObject *parent = GetElementParent();

				if (!parent) {
					// we can't step forward anymore.  result is NULL.
					element = NULL;
					return true;
				}

				IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent);
				(*offset) --;
				location = parent_node->GetDocumentChildren()->IndexOf (Value (element)) + 1;
				if ((int)location == children_count - 1)
					location = CONTENT_END;
				element = parent;
				return true;
			}
		}
	}
}