Code

Cleaned up logic of sp_te_delete to adhere to UI/logic layering.
authorgbanaszk <gbanaszk@users.sourceforge.net>
Wed, 18 Jul 2007 18:33:13 +0000 (18:33 +0000)
committergbanaszk <gbanaszk@users.sourceforge.net>
Wed, 18 Jul 2007 18:33:13 +0000 (18:33 +0000)
src/text-context.cpp
src/text-editing.cpp
src/text-editing.h

index f3f974c6f96356b8ecdb1b981dae53240b8ad621..0410ab3b4679a7eb830505b5d8924fc7cb562ede 100644 (file)
@@ -912,30 +912,51 @@ sp_text_context_root_handler(SPEventContext *const ec, GdkEvent *const event)
 
                             case GDK_Return:
                             case GDK_KP_Enter:
+                            {
                                 if (!tc->text) { // printable key; create text if none (i.e. if nascent_object)
                                     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, SP_TE_DELETE_OTHER);
+                                
+                                iterator_pair enter_pair;
+                                bool success = sp_te_delete(tc->text, tc->text_sel_start, tc->text_sel_end, enter_pair);
+                                tc->text_sel_start = tc->text_sel_end = enter_pair.first;
                                 
                                 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);
                                 sp_document_done(sp_desktop_document(ec->desktop), SP_VERB_CONTEXT_TEXT, 
                                                  _("New line"));
                                 return TRUE;
+                            }
                             case GDK_BackSpace:
                                 if (tc->text) { // if nascent_object, do nothing, but return TRUE; same for all other delete and move keys
-                                       sp_te_deletion_type deleteType = SP_TE_DELETE_OTHER;
-                                       
-                                    if (tc->text_sel_start == tc->text_sel_end) {
+                                    
+                                    bool noSelection = false;
+                                    
+                                       if (tc->text_sel_start == tc->text_sel_end) {
                                         tc->text_sel_start.prevCursorPosition();
-                                        deleteType = SP_TE_DELETE_SINGLE_BACKSPACE;
+                                        noSelection = true;
                                     }
+                                       
+                                       iterator_pair bspace_pair;
+                                       bool success = sp_te_delete(tc->text, tc->text_sel_start, tc->text_sel_end, bspace_pair);
                                     
-                                    tc->text_sel_start = tc->text_sel_end 
-                                                       = sp_te_delete(tc->text, tc->text_sel_start, tc->text_sel_end, deleteType);
+                                    if (noSelection) {
+                                        if (success) {
+                                            tc->text_sel_start = tc->text_sel_end = bspace_pair.first;
+                                        } else { // nothing deleted
+                                            tc->text_sel_start = tc->text_sel_end = bspace_pair.second;
+                                        }
+                                    } else {
+                                        if (success) {
+                                            tc->text_sel_start = tc->text_sel_end = bspace_pair.first;
+                                        } else { // nothing deleted
+                                            tc->text_sel_start = bspace_pair.first;
+                                            tc->text_sel_end = bspace_pair.second;
+                                        }
+                                    }
                                     
                                     sp_text_context_update_cursor(tc);
                                     sp_text_context_update_text_selection(tc);
@@ -946,15 +967,27 @@ sp_text_context_root_handler(SPEventContext *const ec, GdkEvent *const event)
                             case GDK_Delete:
                             case GDK_KP_Delete:
                                 if (tc->text) {
-                                       sp_te_deletion_type deleteType = SP_TE_DELETE_OTHER;
-                                       
+                                    bool noSelection = false;
+                                    
                                     if (tc->text_sel_start == tc->text_sel_end) {
                                         tc->text_sel_end.nextCursorPosition();
-                                        deleteType = SP_TE_SINGLE_DELETE;
+                                        noSelection = true;
+                                    }
+                                    
+                                    iterator_pair del_pair;
+                                    bool success = sp_te_delete(tc->text, tc->text_sel_start, tc->text_sel_end, del_pair);
+                                    
+                                    if (noSelection) {
+                                        tc->text_sel_start = tc->text_sel_end = del_pair.first;
+                                    } else {
+                                        if (success) {
+                                            tc->text_sel_start = tc->text_sel_end = del_pair.first;
+                                        } else { // nothing deleted
+                                            tc->text_sel_start = del_pair.first;
+                                            tc->text_sel_end = del_pair.second;
+                                        }
                                     }
                                     
-                                    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);
@@ -1307,9 +1340,21 @@ bool sp_text_delete_selection(SPEventContext *ec)
 
     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, SP_TE_DELETE_OTHER);
+    
+    iterator_pair pair;
+    bool success = sp_te_delete(tc->text, tc->text_sel_start, tc->text_sel_end, pair);
+    
+    
+    if (success) {
+        tc->text_sel_start = tc->text_sel_end = pair.first;
+    } else { // nothing deleted
+        tc->text_sel_start = pair.first;
+        tc->text_sel_end = pair.second;
+    }
+    
     sp_text_context_update_cursor(tc);
     sp_text_context_update_text_selection(tc);
+    
     return true;
 }
 
index 2ad894cc6122e2269e4046219711da96a7a81af6..02fec31d170f04495d7c8ae4ba753b85d815ba77 100644 (file)
@@ -138,8 +138,9 @@ char * dump_hexy(const gchar * 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 new_start = sp_te_delete(item, start, end, SP_TE_DELETE_OTHER);
-    return sp_te_insert(item, new_start, utf8);
+    iterator_pair pair;
+    sp_te_delete(item, start, end, pair);
+    return sp_te_insert(item, pair.first, utf8);
 }
 
 
@@ -678,20 +679,21 @@ static void erase_from_spstring(SPString *string_item, Glib::ustring::iterator i
 quite a complicated operation, partly due to the cleanup that is done if all
 the text in a subobject has been deleted, and partly due to the difficulty
 of figuring out what is a line break and how to delete one. Returns the
-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
+real start and ending iterators based on the situation. */
+bool
 sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start,
-              Inkscape::Text::Layout::iterator const &end, sp_te_deletion_type deletionType)
+              Inkscape::Text::Layout::iterator const &end, iterator_pair &iter_pair)
 {
-    if (start == end) return start;
-    Inkscape::Text::Layout::iterator first, last;
-    if (start < end) {
-        first = start;
-        last = end;
-    } else {
-        first = end;
-        last = start;
+    bool success = false;
+
+    iter_pair.first = start;
+    iter_pair.second = end;
+    
+    if (start == end) return success;
+    
+    if (start > end) {
+        iter_pair.first = end;
+        iter_pair.second = start;
     }
     
     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
@@ -700,12 +702,12 @@ sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start,
     SPObject *start_item = 0, *end_item = 0;
     void *rawptr = 0;
     Glib::ustring::iterator start_text_iter, end_text_iter;
-    layout->getSourceOfCharacter(first, &rawptr, &start_text_iter);
+    layout->getSourceOfCharacter(iter_pair.first, &rawptr, &start_text_iter);
     start_item = SP_OBJECT(rawptr);
-    layout->getSourceOfCharacter(last, &rawptr, &end_text_iter);
+    layout->getSourceOfCharacter(iter_pair.second, &rawptr, &end_text_iter);
     end_item = SP_OBJECT(rawptr);
     if (start_item == 0)
-        return first;   // start is at end of text
+        return success;   // start is at end of text
     if (is_line_break_object(start_item))
         move_to_end_of_paragraph(&start_item, &start_text_iter);
     if (end_item == 0) {
@@ -723,14 +725,9 @@ sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start,
             // 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);
-                
-                // 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);
+                success = true;
             }
         }
     } else {
@@ -742,15 +739,12 @@ sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start,
                     // 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);
-                        // 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;
                     erase_from_spstring(SP_STRING(sub_item), string->begin(), end_text_iter);
+                    success = true;
                 }
                 break;
             }
@@ -760,6 +754,7 @@ sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start,
                     erase_from_spstring(string, start_text_iter, string->string.end());
                 else
                     erase_from_spstring(string, string->string.begin(), string->string.end());
+                success = true;
             }
             // walk to the next item in the tree
             if (sub_item->hasChildren())
@@ -788,8 +783,9 @@ sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start,
     while (tidy_xml_tree_recursively(common_ancestor));
     te_update_layout_now(item);
     item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
-    layout->validateIterator(&first);
-    return first;
+    layout->validateIterator(&iter_pair.first);
+    layout->validateIterator(&iter_pair.second);
+    return success;
 }
 
 
index 8955d1e30507f0e470d8faacb0048b4e9fc95245..fb2f173652f09b1ab4e019f44f3020fd045e43ed 100644 (file)
@@ -18,6 +18,8 @@ struct SPItem;
 class SPCSSAttr;
 namespace NR { class Point; }
 
+typedef std::pair<Inkscape::Text::Layout::iterator, Inkscape::Text::Layout::iterator> iterator_pair; 
+
 
 Inkscape::Text::Layout const * te_get_layout (SPItem const *item);
 bool sp_te_output_is_empty (SPItem const *item);
@@ -35,9 +37,7 @@ SPStyle const * sp_te_style_at_position(SPItem const *text, Inkscape::Text::Layo
 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_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);
+bool sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, iterator_pair &iter_pair);
 
 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);