diff --git a/moo/mooedit/mooeditwindow.c b/moo/mooedit/mooeditwindow.c
index 20a1276d..e77b8634 100644
--- a/moo/mooedit/mooeditwindow.c
+++ b/moo/mooedit/mooeditwindow.c
@@ -196,6 +196,9 @@ static void moo_edit_window_next_tab (MooEditWindow *window);
static void moo_edit_window_toggle_bookmark (MooEditWindow *window);
static void moo_edit_window_next_bookmark (MooEditWindow *window);
static void moo_edit_window_prev_bookmark (MooEditWindow *window);
+static void moo_edit_window_next_ph (MooEditWindow *window);
+static void moo_edit_window_prev_ph (MooEditWindow *window);
+
#if GTK_CHECK_VERSION(2,10,0)
static void moo_edit_window_page_setup (MooEditWindow *window);
@@ -587,6 +590,24 @@ moo_edit_window_class_init (MooEditWindowClass *klass)
"condition::visible", "has-open-document",
NULL);
+ moo_window_class_new_action (window_class, "NextPlaceholder",
+ "name", "Next Placeholder",
+ "label", "Next Placeholder",
+ "tooltip", "Go to next placeholder",
+ "icon-stock-id", GTK_STOCK_GO_FORWARD,
+ "closure-callback", moo_edit_window_next_ph,
+ "condition::visible", "has-open-document",
+ NULL);
+
+ moo_window_class_new_action (window_class, "PrevPlaceholder",
+ "name", "Previous Placeholder",
+ "label", "Previous Placeholder",
+ "tooltip", "Go to previous placeholder",
+ "icon-stock-id", GTK_STOCK_GO_BACK,
+ "closure-callback", moo_edit_window_prev_ph,
+ "condition::visible", "has-open-document",
+ NULL);
+
moo_window_class_new_action (window_class, "QuickSearch",
"name", "Quick Search",
"label", "Quick Search",
@@ -1065,6 +1086,24 @@ moo_edit_window_prev_bookmark (MooEditWindow *window)
}
+static void
+moo_edit_window_next_ph (MooEditWindow *window)
+{
+ MooEdit *doc = moo_edit_window_get_active_doc (window);
+ g_return_if_fail (doc != NULL);
+ moo_text_view_next_placeholder (MOO_TEXT_VIEW (doc));
+}
+
+
+static void
+moo_edit_window_prev_ph (MooEditWindow *window)
+{
+ MooEdit *doc = moo_edit_window_get_active_doc (window);
+ g_return_if_fail (doc != NULL);
+ moo_text_view_prev_placeholder (MOO_TEXT_VIEW (doc));
+}
+
+
#if GTK_CHECK_VERSION(2,10,0)
static void
moo_edit_window_page_setup (MooEditWindow *window)
diff --git a/moo/mooedit/mooplaceholder.h b/moo/mooedit/mooplaceholder.h
index 7e8a1caf..7964c8c6 100644
--- a/moo/mooedit/mooplaceholder.h
+++ b/moo/mooedit/mooplaceholder.h
@@ -38,6 +38,9 @@ G_BEGIN_DECLS
#define MOO_IS_TEXT_ANCHOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOO_TYPE_TEXT_ANCHOR))
#define MOO_TEXT_ANCHOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOO_TYPE_TEXT_ANCHOR, MooTextAnchorClass))
+#define MOO_TEXT_UNKNOWN_CHAR 0xFFFC
+#define MOO_TEXT_UNKNOWN_CHAR_S "\xEF\xBF\xBC"
+
typedef struct _MooPlaceholder MooPlaceholder;
typedef struct _MooPlaceholderPrivate MooPlaceholderPrivate;
diff --git a/moo/mooedit/mootextview.c b/moo/mooedit/mootextview.c
index 3ddfc709..99f0a78c 100644
--- a/moo/mooedit/mootextview.c
+++ b/moo/mooedit/mootextview.c
@@ -1928,15 +1928,8 @@ moo_text_view_draw_placeholders (GtkTextView *text_view,
while (gtk_text_iter_compare (&iter, end) < 0)
{
- if (gtk_text_iter_get_char (&iter) == 0xFFFC)
- {
- GtkTextChildAnchor *anchor;
-
- anchor = gtk_text_iter_get_child_anchor (&iter);
-
- if (MOO_IS_TEXT_ANCHOR (anchor))
- draw_placeholder (text_view, event, &iter);
- }
+ if (moo_text_view_has_placeholder_at_iter (MOO_TEXT_VIEW (text_view), &iter))
+ draw_placeholder (text_view, event, &iter);
if (!gtk_text_iter_forward_char (&iter))
break;
@@ -4121,5 +4114,91 @@ has_placeholders (MooTextView *view)
}
-gboolean moo_text_view_next_placeholder (MooTextView *view);
-gboolean moo_text_view_prev_placeholder (MooTextView *view);
+gboolean
+moo_text_view_has_placeholder_at_iter (MooTextView *view,
+ GtkTextIter *iter)
+{
+ GtkTextChildAnchor *anchor;
+
+ g_return_val_if_fail (MOO_IS_TEXT_VIEW (view), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ if (gtk_text_iter_get_char (iter) != MOO_TEXT_UNKNOWN_CHAR)
+ return FALSE;
+
+ anchor = gtk_text_iter_get_child_anchor (iter);
+ return MOO_IS_TEXT_ANCHOR (anchor) &&
+ MOO_IS_PLACEHOLDER (MOO_TEXT_ANCHOR(anchor)->widget);
+}
+
+
+gboolean
+moo_text_view_next_placeholder (MooTextView *view)
+{
+ GtkTextIter start, end, match_start, match_end;
+ GtkTextBuffer *buffer;
+
+ g_return_val_if_fail (MOO_IS_TEXT_VIEW (view), FALSE);
+
+ buffer = get_buffer (view);
+
+ if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
+ {
+ if (moo_text_view_has_placeholder_at_iter (view, &start) &&
+ gtk_text_iter_get_line_offset (&end) == gtk_text_iter_get_line_offset (&start) + 1)
+ start = end;
+ else
+ moo_text_view_get_cursor (view, &start);
+ }
+
+ while (gtk_text_iter_forward_search (&start, MOO_TEXT_UNKNOWN_CHAR_S,
+ 0, &match_start, &match_end, NULL))
+ {
+ if (moo_text_view_has_placeholder_at_iter (view, &match_start))
+ {
+ gtk_text_buffer_select_range (buffer, &match_end, &match_start);
+ return TRUE;
+ }
+ else
+ {
+ start = match_end;
+ }
+ }
+
+ return FALSE;
+}
+
+
+gboolean
+moo_text_view_prev_placeholder (MooTextView *view)
+{
+ GtkTextIter start, end, match_start, match_end;
+ GtkTextBuffer *buffer;
+
+ g_return_val_if_fail (MOO_IS_TEXT_VIEW (view), FALSE);
+
+ buffer = get_buffer (view);
+
+ if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end) &&
+ !moo_text_view_has_placeholder_at_iter (view, &start) &&
+ gtk_text_iter_get_line_offset (&end) != gtk_text_iter_get_line_offset (&start) + 1)
+ {
+ moo_text_view_get_cursor (view, &start);
+ }
+
+ while (gtk_text_iter_backward_search (&start, MOO_TEXT_UNKNOWN_CHAR_S,
+ 0, &match_start, &match_end, NULL))
+ {
+ if (moo_text_view_has_placeholder_at_iter (view, &match_start))
+ {
+ gtk_text_buffer_select_range (buffer, &match_start, &match_end);
+ return TRUE;
+ }
+ else
+ {
+ start = match_start;
+ }
+ }
+
+ return FALSE;
+}
diff --git a/moo/mooedit/mootextview.h b/moo/mooedit/mootextview.h
index 258c22c6..9f9dd312 100644
--- a/moo/mooedit/mootextview.h
+++ b/moo/mooedit/mootextview.h
@@ -162,6 +162,8 @@ void moo_text_view_insert_placeholder (MooTextView *view,
GtkTextIter *iter);
gboolean moo_text_view_next_placeholder (MooTextView *view);
gboolean moo_text_view_prev_placeholder (MooTextView *view);
+gboolean moo_text_view_has_placeholder_at_iter (MooTextView *view,
+ GtkTextIter *iter);
void moo_text_view_start_quick_search (MooTextView *view);
void moo_text_view_stop_quick_search (MooTextView *view);
diff --git a/tests/medit-ui.xml b/tests/medit-ui.xml
index 1ca559d7..8023d88a 100644
--- a/tests/medit-ui.xml
+++ b/tests/medit-ui.xml
@@ -54,6 +54,9 @@
+
+
+
-