summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 2263ac1)
raw | patch | inline | side by side (parent: 2263ac1)
author | gbanaszk <gbanaszk@users.sourceforge.net> | |
Tue, 17 Jul 2007 17:39:06 +0000 (17:39 +0000) | ||
committer | gbanaszk <gbanaszk@users.sourceforge.net> | |
Tue, 17 Jul 2007 17:39:06 +0000 (17:39 +0000) |
index dd6ab6eb80a689d40350e9de84490c09a7ae51e6..188ace06bd49cc91115bec2e962df56b6e68bbb6 100644 (file)
{
SPItem *item = (SPItem *) items->data;
+ if (SP_IS_TEXT(item)) {
+ SPObject *tspan = sp_tref_convert_to_tspan(SP_OBJECT(item));
+
+ if (tspan) {
+ SP_OBJECT(item)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ }
+
+ // Set unlink to true, and fall into the next if which
+ // will include this text item in the new selection
+ unlinked = true;
+ }
+
if (!(SP_IS_USE(item) || SP_IS_TREF(item))) {
// keep the non-use item in the new selection
new_select = g_slist_prepend(new_select, item);
if (SP_IS_USE(item)) {
unlink = sp_use_unlink(SP_USE(item));
} else /*if (SP_IS_TREF(use))*/ {
- unlink = SP_ITEM(sp_tref_convert_to_tspan(SP_TREF(item)));
+ unlink = SP_ITEM(sp_tref_convert_to_tspan(SP_OBJECT(item)));
}
unlinked = true;
diff --git a/src/sp-tref.cpp b/src/sp-tref.cpp
index d5479b6cda02edc110f33c77bf4a809ab63de8aa..28db57990e25b32c7f43563c08e47395ba608765 100644 (file)
--- a/src/sp-tref.cpp
+++ b/src/sp-tref.cpp
* The code is based partially on sp_use_unlink
*/
SPObject *
-sp_tref_convert_to_tspan(SPTRef *tref)
+sp_tref_convert_to_tspan(SPObject *obj)
{
SPObject * new_tspan = NULL;
- if (tref && tref->stringChild) {
- Inkscape::XML::Node *tref_repr = SP_OBJECT_REPR(tref);
- Inkscape::XML::Node *tref_parent = sp_repr_parent(tref_repr);
+ ////////////////////
+ // BASE CASE
+ ////////////////////
+ if (SP_IS_TREF(obj)) {
- SPDocument *document = SP_OBJECT(tref)->document;
- Inkscape::XML::Document *xml_doc = sp_document_repr_doc(document);
-
- Inkscape::XML::Node *new_tspan_repr = xml_doc->createElement("svg:tspan");
-
- // Add the new tspan element just after the current tref
- tref_parent->addChild(new_tspan_repr, tref_repr);
- Inkscape::GC::release(new_tspan_repr);
-
- new_tspan = document->getObjectByRepr(new_tspan_repr);
-
- // Create a new string child for the tspan
- Inkscape::XML::Node *new_string_repr = SP_OBJECT_REPR(tref->stringChild)->duplicate(xml_doc);
- new_tspan_repr->addChild(new_string_repr, NULL);
-
- SPObject * new_string_child = document->getObjectByRepr(new_string_repr);
-
- // Merge style from the tref
- SPStyle *new_tspan_sty = SP_OBJECT_STYLE(new_tspan);
- SPStyle const *tref_sty = SP_OBJECT_STYLE(tref);
- sp_style_merge_from_dying_parent(new_tspan_sty, tref_sty);
- sp_style_merge_from_parent(new_tspan_sty, new_tspan->parent->style);
-
-
- SP_OBJECT(new_tspan)->updateRepr();
-
- // Hold onto our SPObject and repr for now.
- sp_object_ref(SP_OBJECT(tref), NULL);
- Inkscape::GC::anchor(tref_repr);
-
- // Remove ourselves, not propagating delete events to avoid a
- // chain-reaction with other elements that might reference us.
- SP_OBJECT(tref)->deleteObject(false);
-
- // Give the copy our old id and let go of our old repr.
- new_tspan_repr->setAttribute("id", tref_repr->attribute("id"));
- Inkscape::GC::release(tref_repr);
-
- // Establish the succession and let go of our object.
- SP_OBJECT(tref)->setSuccessor(new_tspan);
- sp_object_unref(SP_OBJECT(tref), NULL);
+ SPTRef *tref = SP_TREF(obj);
+
+ if (tref && tref->stringChild) {
+ Inkscape::XML::Node *tref_repr = SP_OBJECT_REPR(tref);
+ Inkscape::XML::Node *tref_parent = sp_repr_parent(tref_repr);
+
+ SPDocument *document = SP_OBJECT(tref)->document;
+ Inkscape::XML::Document *xml_doc = sp_document_repr_doc(document);
+
+ Inkscape::XML::Node *new_tspan_repr = xml_doc->createElement("svg:tspan");
+
+ // Add the new tspan element just after the current tref
+ tref_parent->addChild(new_tspan_repr, tref_repr);
+ Inkscape::GC::release(new_tspan_repr);
+
+ new_tspan = document->getObjectByRepr(new_tspan_repr);
+
+ // Create a new string child for the tspan
+ Inkscape::XML::Node *new_string_repr = SP_OBJECT_REPR(tref->stringChild)->duplicate(xml_doc);
+ new_tspan_repr->addChild(new_string_repr, NULL);
+
+ //SPObject * new_string_child = document->getObjectByRepr(new_string_repr);
+
+ // Merge style from the tref
+ SPStyle *new_tspan_sty = SP_OBJECT_STYLE(new_tspan);
+ SPStyle const *tref_sty = SP_OBJECT_STYLE(tref);
+ sp_style_merge_from_dying_parent(new_tspan_sty, tref_sty);
+ sp_style_merge_from_parent(new_tspan_sty, new_tspan->parent->style);
+
+
+ SP_OBJECT(new_tspan)->updateRepr();
+
+ // Hold onto our SPObject and repr for now.
+ sp_object_ref(SP_OBJECT(tref), NULL);
+ Inkscape::GC::anchor(tref_repr);
+
+ // Remove ourselves, not propagating delete events to avoid a
+ // chain-reaction with other elements that might reference us.
+ SP_OBJECT(tref)->deleteObject(false);
+
+ // Give the copy our old id and let go of our old repr.
+ new_tspan_repr->setAttribute("id", tref_repr->attribute("id"));
+ Inkscape::GC::release(tref_repr);
+
+ // Establish the succession and let go of our object.
+ SP_OBJECT(tref)->setSuccessor(new_tspan);
+ sp_object_unref(SP_OBJECT(tref), NULL);
+ }
+ }
+ ////////////////////
+ // RECURSIVE CASE
+ ////////////////////
+ else {
+ GSList *l = NULL;
+ for (SPObject *child = sp_object_first_child(obj) ; child != NULL ; child = SP_OBJECT_NEXT(child) ) {
+ sp_object_ref (SP_OBJECT (child), obj);
+ l = g_slist_prepend (l, child);
+ }
+ l = g_slist_reverse (l);
+ while (l) {
+ SPObject *child = SP_OBJECT (l->data);
+ l = g_slist_remove (l, child);
+
+ // Note that there may be more than one conversion happening here, so if it's not a
+ // tref being passed into this function, the returned value can't be specifically known
+ new_tspan = sp_tref_convert_to_tspan(child);
+
+ sp_object_unref (SP_OBJECT (child), obj);
+ }
}
return new_tspan;
diff --git a/src/sp-tref.h b/src/sp-tref.h
index eea8207e3c3b1dbdb5aac3a8b1824af8d58519b8..2e79a28c394f78a1e86042d2d2ebafed4a1b06eb 100644 (file)
--- a/src/sp-tref.h
+++ b/src/sp-tref.h
bool sp_tref_reference_allowed(SPTRef *tref, SPObject *possible_ref);
bool sp_tref_fully_contained(SPObject *start_item, Glib::ustring::iterator &start,
SPObject *end_item, Glib::ustring::iterator &end);
-SPObject * sp_tref_convert_to_tspan(SPTRef *item);
+SPObject * sp_tref_convert_to_tspan(SPObject *item);
#endif /* !SP_TREF_H */
diff --git a/src/text-context.cpp b/src/text-context.cpp
index b45cd6e58090af5155975ba251de874154852655..f3f974c6f96356b8ecdb1b981dae53240b8ad621 100644 (file)
--- a/src/text-context.cpp
+++ b/src/text-context.cpp
sp_text_context_setup_text(tc);
tc->nascent_object = 0; // we don't need it anymore, having created a real <text>
}
- tc->text_sel_start = tc->text_sel_end = sp_te_delete(tc->text, tc->text_sel_start, tc->text_sel_end);
+ tc->text_sel_start = tc->text_sel_end
+ = sp_te_delete(tc->text, tc->text_sel_start, tc->text_sel_end, SP_TE_DELETE_OTHER);
+
tc->text_sel_start = tc->text_sel_end = sp_te_insert_line(tc->text, tc->text_sel_start);
sp_text_context_update_cursor(tc);
sp_text_context_update_text_selection(tc);
return TRUE;
case GDK_BackSpace:
if (tc->text) { // if nascent_object, do nothing, but return TRUE; same for all other delete and move keys
- if (tc->text_sel_start == tc->text_sel_end)
+ sp_te_deletion_type deleteType = SP_TE_DELETE_OTHER;
+
+ if (tc->text_sel_start == tc->text_sel_end) {
tc->text_sel_start.prevCursorPosition();
- tc->text_sel_start = tc->text_sel_end = sp_te_delete(tc->text, tc->text_sel_start, tc->text_sel_end);
+ deleteType = SP_TE_DELETE_SINGLE_BACKSPACE;
+ }
+
+ tc->text_sel_start = tc->text_sel_end
+ = sp_te_delete(tc->text, tc->text_sel_start, tc->text_sel_end, deleteType);
+
sp_text_context_update_cursor(tc);
sp_text_context_update_text_selection(tc);
sp_document_done(sp_desktop_document(ec->desktop), SP_VERB_CONTEXT_TEXT,
case GDK_Delete:
case GDK_KP_Delete:
if (tc->text) {
- if (tc->text_sel_start == tc->text_sel_end)
+ sp_te_deletion_type deleteType = SP_TE_DELETE_OTHER;
+
+ if (tc->text_sel_start == tc->text_sel_end) {
tc->text_sel_end.nextCursorPosition();
- tc->text_sel_start = tc->text_sel_end = sp_te_delete(tc->text, tc->text_sel_start, tc->text_sel_end);
+ deleteType = SP_TE_SINGLE_DELETE;
+ }
+
+ tc->text_sel_start = tc->text_sel_end
+ = sp_te_delete(tc->text, tc->text_sel_start, tc->text_sel_end, deleteType);
+
sp_text_context_update_cursor(tc);
sp_text_context_update_text_selection(tc);
sp_document_done(sp_desktop_document(ec->desktop), SP_VERB_CONTEXT_TEXT,
if (tc->text_sel_start == tc->text_sel_end)
return false;
- tc->text_sel_start = tc->text_sel_end = sp_te_delete(tc->text, tc->text_sel_start, tc->text_sel_end);
+ tc->text_sel_start = tc->text_sel_end = sp_te_delete(tc->text, tc->text_sel_start, tc->text_sel_end, SP_TE_DELETE_OTHER);
sp_text_context_update_cursor(tc);
sp_text_context_update_text_selection(tc);
return true;
diff --git a/src/text-editing.cpp b/src/text-editing.cpp
index bed837cefabf2ff65903734a16ad15c3e5bd8e56..2ad894cc6122e2269e4046219711da96a7a81af6 100644 (file)
--- a/src/text-editing.cpp
+++ b/src/text-editing.cpp
Inkscape::Text::Layout::iterator sp_te_replace(SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, gchar const *utf8)
{
- Inkscape::Text::Layout::iterator new_start = sp_te_delete(item, start, end);
+ Inkscape::Text::Layout::iterator new_start = sp_te_delete(item, start, end, SP_TE_DELETE_OTHER);
return sp_te_insert(item, new_start, utf8);
}
@@ -148,13 +148,28 @@ Inkscape::Text::Layout::iterator sp_te_replace(SPItem *item, Inkscape::Text::Lay
static bool is_line_break_object(SPObject const *object)
{
- return SP_IS_TEXT(object)
- || (SP_IS_TSPAN(object) && SP_TSPAN(object)->role != SP_TSPAN_ROLE_UNSPECIFIED)
- || SP_IS_TEXTPATH(object)
- || SP_IS_FLOWDIV(object)
- || SP_IS_FLOWPARA(object)
- || SP_IS_FLOWLINE(object)
- || SP_IS_FLOWREGIONBREAK(object);
+ bool is_line_break = false;
+
+ if (object) {
+ if (SP_IS_TEXT(object)
+ || SP_IS_TEXTPATH(object)
+ || SP_IS_FLOWDIV(object)
+ || SP_IS_FLOWPARA(object)
+ || SP_IS_FLOWLINE(object)
+ || SP_IS_FLOWREGIONBREAK(object)) {
+
+ is_line_break = true;
+ }
+
+ if (SP_IS_TSPAN(object) && SP_TSPAN(object)->role != SP_TSPAN_ROLE_UNSPECIFIED) {
+ SPObject *prev_object = SP_OBJECT_PREV(object);
+ if (prev_object && SP_IS_TSPAN(prev_object)) {
+ is_line_break = true;
+ }
+ }
+ }
+
+ return is_line_break;
}
/** returns the attributes for an object, or NULL if it isn't a text,
@@ -334,7 +349,7 @@ Inkscape::Text::Layout::iterator sp_te_insert_line (SPItem *item, Inkscape::Text
{
// Disable newlines in a textpath; TODO: maybe on Enter in a textpath, separate it into two
// texpaths attached to the same path, with a vertical shift
- if (SP_IS_TEXT_TEXTPATH (item))
+ if (SP_IS_TEXT_TEXTPATH (item) || SP_IS_TREF(item))
return position;
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
@@ -350,6 +365,12 @@ Inkscape::Text::Layout::iterator sp_te_insert_line (SPItem *item, Inkscape::Text
if (split_obj == 0 || is_line_break_object(split_obj)) {
if (split_obj == 0) split_obj = item->lastChild();
+
+ if (SP_IS_TREF(split_obj)) {
+ desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, tref_edit_message);
+ return position;
+ }
+
if (split_obj) {
Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(split_obj));
Inkscape::XML::Node *new_node = duplicate_node_without_children(xml_doc, SP_OBJECT_REPR(split_obj));
lesser of \a start and \a end, because that is where the cursor should be
put after the deletion is done. */
Inkscape::Text::Layout::iterator
-sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end)
+sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start,
+ Inkscape::Text::Layout::iterator const &end, sp_te_deletion_type deletionType)
{
if (start == end) return start;
Inkscape::Text::Layout::iterator first, last;
@@ -701,10 +723,15 @@ sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start, Inksc
// If the parent is a tref, editing on this particular string is disallowed.
if (SP_IS_TREF(SP_OBJECT_PARENT(start_item))) {
desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, tref_edit_message);
- return end;
+
+ // Compensate so the cursor doesn't move when hitting backspace
+ if (deletionType == SP_TE_DELETE_SINGLE_BACKSPACE) {
+ first = last;
+ }
+
+ } else {
+ erase_from_spstring(SP_STRING(start_item), start_text_iter, end_text_iter);
}
-
- erase_from_spstring(SP_STRING(start_item), start_text_iter, end_text_iter);
}
} else {
SPObject *sub_item = start_item;
@@ -715,7 +742,11 @@ sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start, Inksc
// If the parent is a tref, editing on this particular string is disallowed.
if (SP_IS_TREF(SP_OBJECT_PARENT(sub_item))) {
desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, tref_edit_message);
- return end;
+ // Compensate so the cursor doesn't move when hitting backspace
+ if (deletionType == SP_TE_DELETE_SINGLE_BACKSPACE) {
+ //first = last;
+ }
+ break;
}
Glib::ustring *string = &SP_STRING(sub_item)->string;
bool changes = false;
for (SPObject *child = root->firstChild() ; child != NULL ; ) {
- if (SP_IS_FLOWREGION(child) || SP_IS_FLOWREGIONEXCLUDE(child)) {
+ if (SP_IS_FLOWREGION(child) || SP_IS_FLOWREGIONEXCLUDE(child) || SP_IS_TREF(child)) {
child = SP_OBJECT_NEXT(child);
continue;
}
diff --git a/src/text-editing.h b/src/text-editing.h
index dba763f75e7c0c5d8fe3f294252874f445aa159d..8955d1e30507f0e470d8faacb0048b4e9fc95245 100644 (file)
--- a/src/text-editing.h
+++ b/src/text-editing.h
Inkscape::Text::Layout::iterator sp_te_insert(SPItem *item, Inkscape::Text::Layout::iterator const &position, gchar const *utf8);
Inkscape::Text::Layout::iterator sp_te_replace(SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, gchar const *utf8);
-Inkscape::Text::Layout::iterator sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end);
Inkscape::Text::Layout::iterator sp_te_insert_line (SPItem *text, Inkscape::Text::Layout::iterator const &position);
+enum sp_te_deletion_type { SP_TE_DELETE_SINGLE_BACKSPACE, SP_TE_SINGLE_DELETE, SP_TE_DELETE_OTHER };
+Inkscape::Text::Layout::iterator sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, sp_te_deletion_type deletionType);
+
gchar *sp_te_get_string_multiline(SPItem const *text);
Glib::ustring sp_te_get_string_multiline(SPItem const *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end);
void sp_te_set_repr_text_multiline(SPItem *text, gchar const *str);