diff --git a/src/text-context.cpp b/src/text-context.cpp
index ed0709aec2629f2e22d247d669012592d65d6332..6d26bee2b98422b0bbc92dc5330c91da7f0b893c 100644 (file)
--- a/src/text-context.cpp
+++ b/src/text-context.cpp
SP_CTRLRECT(tc->frame)->setColor(0x0000ff7f, false, 0);
sp_canvas_item_hide(tc->frame);
- tc->timeout = gtk_timeout_add(250, (GtkFunction) sp_text_context_timeout, ec);
+ tc->timeout = gtk_timeout_add(200, (GtkFunction) sp_text_context_timeout, ec);
tc->imc = gtk_im_multicontext_new();
if (tc->imc) {
@@ -437,7 +437,7 @@ sp_text_context_item_handler(SPEventContext *event_context, SPItem *item, GdkEve
item_ungrouped = desktop->item_at_point(NR::Point(event->button.x, event->button.y), TRUE);
if (SP_IS_TEXT(item_ungrouped) || SP_IS_FLOWTEXT(item_ungrouped)) {
sp_canvas_item_show(tc->indicator);
- NR::Maybe<NR::Rect> ibbox = sp_item_bbox_desktop(item_ungrouped);
+ boost::optional<NR::Rect> ibbox = sp_item_bbox_desktop(item_ungrouped);
if (ibbox) {
SP_CTRLRECT(tc->indicator)->setRectangle(*ibbox);
}
@@ -809,7 +809,17 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons
}
}
- bool (Inkscape::Text::Layout::iterator::*cursor_movement_operator)() = NULL;
+ Inkscape::Text::Layout::iterator old_start = tc->text_sel_start;
+ Inkscape::Text::Layout::iterator old_end = tc->text_sel_end;
+ bool cursor_moved = false;
+ int screenlines = 1;
+ if (tc->text) {
+ double spacing = sp_te_get_average_linespacing(tc->text);
+ NR::Rect const d = desktop->get_display_area();
+ screenlines = (int) floor(fabs(d.min()[NR::Y] - d.max()[NR::Y])/spacing) - 1;
+ if (screenlines <= 0)
+ screenlines = 1;
+ }
/* Neither unimode nor IM consumed key; process text tool shortcuts */
switch (group0_keyval) {
@@ -1010,8 +1020,11 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons
sp_document_maybe_done(sp_desktop_document(desktop), "kern:left", SP_VERB_CONTEXT_TEXT,
_("Kern to the left"));
} else {
- cursor_movement_operator = MOD__CTRL ? &Inkscape::Text::Layout::iterator::cursorLeftWithControl
- : &Inkscape::Text::Layout::iterator::cursorLeft;
+ if (MOD__CTRL)
+ tc->text_sel_end.cursorLeftWithControl();
+ else
+ tc->text_sel_end.cursorLeft();
+ cursor_moved = true;
break;
}
}
@@ -1032,8 +1045,11 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons
sp_document_maybe_done(sp_desktop_document(desktop), "kern:right", SP_VERB_CONTEXT_TEXT,
_("Kern to the right"));
} else {
- cursor_movement_operator = MOD__CTRL ? &Inkscape::Text::Layout::iterator::cursorRightWithControl
- : &Inkscape::Text::Layout::iterator::cursorRight;
+ if (MOD__CTRL)
+ tc->text_sel_end.cursorRightWithControl();
+ else
+ tc->text_sel_end.cursorRight();
+ cursor_moved = true;
break;
}
}
@@ -1055,8 +1071,11 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons
_("Kern up"));
} else {
- cursor_movement_operator = MOD__CTRL ? &Inkscape::Text::Layout::iterator::cursorUpWithControl
- : &Inkscape::Text::Layout::iterator::cursorUp;
+ if (MOD__CTRL)
+ tc->text_sel_end.cursorUpWithControl();
+ else
+ tc->text_sel_end.cursorUp();
+ cursor_moved = true;
break;
}
}
@@ -1078,8 +1097,11 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons
_("Kern down"));
} else {
- cursor_movement_operator = MOD__CTRL ? &Inkscape::Text::Layout::iterator::cursorDownWithControl
- : &Inkscape::Text::Layout::iterator::cursorDown;
+ if (MOD__CTRL)
+ tc->text_sel_end.cursorDownWithControl();
+ else
+ tc->text_sel_end.cursorDown();
+ cursor_moved = true;
break;
}
}
@@ -1088,9 +1110,10 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons
case GDK_KP_Home:
if (tc->text) {
if (MOD__CTRL)
- cursor_movement_operator = &Inkscape::Text::Layout::iterator::thisStartOfShape;
+ tc->text_sel_end.thisStartOfShape();
else
- cursor_movement_operator = &Inkscape::Text::Layout::iterator::thisStartOfLine;
+ tc->text_sel_end.thisStartOfLine();
+ cursor_moved = true;
break;
}
return TRUE;
@@ -1098,9 +1121,26 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons
case GDK_KP_End:
if (tc->text) {
if (MOD__CTRL)
- cursor_movement_operator = &Inkscape::Text::Layout::iterator::nextStartOfShape;
+ tc->text_sel_end.nextStartOfShape();
else
- cursor_movement_operator = &Inkscape::Text::Layout::iterator::thisEndOfLine;
+ tc->text_sel_end.thisEndOfLine();
+ cursor_moved = true;
+ break;
+ }
+ return TRUE;
+ case GDK_Page_Down:
+ case GDK_KP_Page_Down:
+ if (tc->text) {
+ tc->text_sel_end.cursorDown(screenlines);
+ cursor_moved = true;
+ break;
+ }
+ return TRUE;
+ case GDK_Page_Up:
+ case GDK_KP_Page_Up:
+ if (tc->text) {
+ tc->text_sel_end.cursorUp(screenlines);
+ cursor_moved = true;
break;
}
return TRUE;
@@ -1217,10 +1257,7 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons
break;
}
- if (cursor_movement_operator) {
- Inkscape::Text::Layout::iterator old_start = tc->text_sel_start;
- Inkscape::Text::Layout::iterator old_end = tc->text_sel_end;
- (tc->text_sel_end.*cursor_movement_operator)();
+ if (cursor_moved) {
if (!MOD__SHIFT)
tc->text_sel_start = tc->text_sel_end;
if (old_start != tc->text_sel_start || old_end != tc->text_sel_end) {
// there is an active text object in this context, or a new object was just created
Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get();
- Glib::ustring const text = refClipboard->wait_for_text();
-
- if (!text.empty()) {
-
+ Glib::ustring const clip_text = refClipboard->wait_for_text();
+
+ if (!clip_text.empty()) {
+ // Fix for 244940
+ // The XML standard defines the following as valid characters
+ // (Extensible Markup Language (XML) 1.0 (Fourth Edition) paragraph 2.2)
+ // char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
+ // Since what comes in off the paste buffer will go right into XML, clean
+ // the text here.
+ Glib::ustring text(clip_text);
+ Glib::ustring::iterator itr = text.begin();
+ gunichar paste_string_uchar;
+
+ while(itr != text.end())
+ {
+ paste_string_uchar = *itr;
+
+ // Make sure we don't have a control character. We should really check
+ // for the whole range above... Add the rest of the invalid cases from
+ // above if we find additional issues
+ if(paste_string_uchar >= 0x00000020 ||
+ paste_string_uchar == 0x00000009 ||
+ paste_string_uchar == 0x0000000A ||
+ paste_string_uchar == 0x0000000D) {
+ itr++;
+ } else {
+ itr = text.erase(itr);
+ }
+ }
+
if (!tc->text) { // 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>
// scroll to show cursor
if (scroll_to_see) {
- NR::Point const dm = (d0 + d1) / 2;
- // unlike mouse moves, here we must scroll all the way at first shot, so we override the autoscrollspeed
- SP_EVENT_CONTEXT(tc)->desktop->scroll_to_point(&dm, 1.0);
+ NR::Point const center = SP_EVENT_CONTEXT(tc)->desktop->get_display_area().midpoint();
+ if (NR::L2(d0 - center) > NR::L2(d1 - center))
+ // unlike mouse moves, here we must scroll all the way at first shot, so we override the autoscrollspeed
+ SP_EVENT_CONTEXT(tc)->desktop->scroll_to_point(&d0, 1.0);
+ else
+ SP_EVENT_CONTEXT(tc)->desktop->scroll_to_point(&d1, 1.0);
}
sp_canvas_item_show(tc->cursor);
SPItem *frame = SP_FLOWTEXT(tc->text)->get_frame (NULL); // first frame only
if (frame) {
sp_canvas_item_show(tc->frame);
- NR::Maybe<NR::Rect> frame_bbox = sp_item_bbox_desktop(frame);
+ boost::optional<NR::Rect> frame_bbox = sp_item_bbox_desktop(frame);
if (frame_bbox) {
SP_CTRLRECT(tc->frame)->setRectangle(*frame_bbox);
}
std::vector<NR::Point> quads;
if (tc->text != NULL)
- quads = sp_te_create_selection_quads(tc->text, tc->text_sel_start, tc->text_sel_end, from_2geom(sp_item_i2d_affine(tc->text)));
+ quads = sp_te_create_selection_quads(tc->text, tc->text_sel_start, tc->text_sel_end, sp_item_i2d_affine(tc->text));
for (unsigned i = 0 ; i < quads.size() ; i += 4) {
SPCanvasItem *quad_canvasitem;
quad_canvasitem = sp_canvas_item_new(sp_desktop_controls(tc->desktop), SP_TYPE_CTRLQUADR, NULL);