Code

Avoid crash by uninitialized perspectives.
[inkscape.git] / src / text-editing.cpp
index 231d834cafc5c3d577d9359271a4fe4f8e37768d..e93ebdffada702e11ceb028c2c4a4f9c91b96bb9 100644 (file)
@@ -109,6 +109,14 @@ sp_te_get_cursor_coords (SPItem const *item, Inkscape::Text::Layout::iterator co
 }
 
 SPStyle const * sp_te_style_at_position(SPItem const *text, Inkscape::Text::Layout::iterator const &position)
+{
+    SPObject const *pos_obj = sp_te_object_at_position(text, position);
+    if (pos_obj)
+        return SP_OBJECT_STYLE(pos_obj);
+    return NULL;
+}
+
+SPObject const * sp_te_object_at_position(SPItem const *text, Inkscape::Text::Layout::iterator const &position)
 {
     Inkscape::Text::Layout const *layout = te_get_layout(text);
     if (layout == NULL)
@@ -119,8 +127,8 @@ SPStyle const * sp_te_style_at_position(SPItem const *text, Inkscape::Text::Layo
     pos_obj = SP_OBJECT(rawptr);
     if (pos_obj == 0) pos_obj = text;
     while (SP_OBJECT_STYLE(pos_obj) == NULL)
-        pos_obj = SP_OBJECT_PARENT(pos_obj);   // SPStrings don't have style
-    return SP_OBJECT_STYLE(pos_obj);
+        pos_obj = SP_OBJECT_PARENT(pos_obj);   // not interested in SPStrings 
+    return pos_obj;
 }
 
 /*
@@ -779,7 +787,7 @@ sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start,
         }
     }
 
-    while (tidy_xml_tree_recursively(common_ancestor));
+    while (tidy_xml_tree_recursively(common_ancestor)){};
     te_update_layout_now(item);
     item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
     layout->validateIterator(&iter_pair.first);
@@ -943,7 +951,7 @@ text_tag_attributes_at_position(SPItem *item, Inkscape::Text::Layout::iterator c
 }
 
 void
-sp_te_adjust_kerning_screen (SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, NR::Point by)
+sp_te_adjust_kerning_screen (SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, Geom::Point by)
 {
     // divide increment by zoom
     // divide increment by matrix expansion
@@ -1094,7 +1102,7 @@ sp_te_get_average_linespacing (SPItem *text)
         return 0;
 
     unsigned line_count = layout->lineIndex(layout->end());
-    double all_lines_height = layout->characterAnchorPoint(layout->end())[NR::Y] - layout->characterAnchorPoint(layout->begin())[NR::Y];
+    double all_lines_height = layout->characterAnchorPoint(layout->end())[Geom::Y] - layout->characterAnchorPoint(layout->begin())[Geom::Y];
     double average_line_height = all_lines_height / (line_count == 0 ? 1 : line_count);
     return average_line_height;
 }
@@ -1118,7 +1126,7 @@ sp_te_adjust_linespacing_screen (SPItem *text, Inkscape::Text::Layout::iterator
     }
 
     unsigned line_count = layout->lineIndex(layout->end());
-    double all_lines_height = layout->characterAnchorPoint(layout->end())[NR::Y] - layout->characterAnchorPoint(layout->begin())[NR::Y];
+    double all_lines_height = layout->characterAnchorPoint(layout->end())[Geom::Y] - layout->characterAnchorPoint(layout->begin())[Geom::Y];
     double average_line_height = all_lines_height / (line_count == 0 ? 1 : line_count);
     if (fabs(average_line_height) < 0.001) average_line_height = 0.001;
 
@@ -1539,8 +1547,9 @@ static bool redundant_double_nesting_processor(SPObject **item, SPObject *child,
     if (!objects_have_equal_style(SP_OBJECT_PARENT(*item), child)) return false;
 
     Inkscape::XML::Node *insert_after_repr;
-    if (prepend) insert_after_repr = SP_OBJECT_REPR(SP_OBJECT_PREV(*item));
-    else insert_after_repr = SP_OBJECT_REPR(*item);
+    if (!prepend) insert_after_repr = SP_OBJECT_REPR(*item);
+    else if (SP_OBJECT_PREV(*item)) insert_after_repr = SP_OBJECT_REPR(SP_OBJECT_PREV(*item));
+    else insert_after_repr = NULL;
     while (SP_OBJECT_REPR(child)->childCount()) {
         Inkscape::XML::Node *move_repr = SP_OBJECT_REPR(child)->firstChild();
         Inkscape::GC::anchor(move_repr);
@@ -1828,12 +1837,43 @@ void sp_te_apply_style(SPItem *text, Inkscape::Text::Layout::iterator const &sta
     and neither option can be made to work, a fallback could be to reduce
     everything to a single level of nesting and drop all pretence of
     roundtrippability. */
-    while (tidy_xml_tree_recursively(common_ancestor));
+    while (tidy_xml_tree_recursively(common_ancestor)){};
 
     // if we only modified subobjects this won't have been automatically sent
     text->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
 }
 
+bool is_part_of_text_subtree (SPObject *obj)
+{
+    return (SP_IS_TSPAN(obj) 
+            || SP_IS_TEXT(obj) 
+            || SP_IS_FLOWTEXT(obj)
+            || SP_IS_FLOWTSPAN(obj)
+            || SP_IS_FLOWDIV(obj)
+            || SP_IS_FLOWPARA(obj)
+            || SP_IS_FLOWLINE(obj)
+            || SP_IS_FLOWREGIONBREAK(obj));
+}
+
+bool is_top_level_text_object (SPObject *obj)
+{
+    return (SP_IS_TEXT(obj) 
+            || SP_IS_FLOWTEXT(obj));
+}
+
+bool has_visible_text (SPObject *obj)
+{
+    if (SP_IS_STRING(obj) && !SP_STRING(obj)->string.empty()) 
+        return true; // maybe we should also check that it's not all whitespace?
+
+    for (SPObject const *child = obj->firstChild() ; child ; child = SP_OBJECT_NEXT(child)) {
+        if (has_visible_text((SPObject *) child))
+            return true;
+    }
+
+    return false;
+}
+
 /*
   Local Variables:
   mode:c++