/* Used for the GtkTextView::extend-selection signal. */ void _gtk_source_iter_extend_selection_word (const GtkTextIter *location, GtkTextIter *start, GtkTextIter *end) { /* Exactly the same algorithm as in GTK+, but with our custom word * boundaries. */ *start = *location; *end = *location; if (_gtk_source_iter_inside_word (start)) { if (!_gtk_source_iter_starts_word (start)) { _gtk_source_iter_backward_visible_word_start (start); } if (!_gtk_source_iter_ends_word (end)) { _gtk_source_iter_forward_visible_word_end (end); } } else { GtkTextIter tmp; tmp = *start; if (_gtk_source_iter_backward_visible_word_start (&tmp)) { _gtk_source_iter_forward_visible_word_end (&tmp); } if (gtk_text_iter_get_line (&tmp) == gtk_text_iter_get_line (start)) { *start = tmp; } else { gtk_text_iter_set_line_offset (start, 0); } tmp = *end; if (!_gtk_source_iter_forward_visible_word_end (&tmp)) { gtk_text_iter_forward_to_end (&tmp); } if (_gtk_source_iter_ends_word (&tmp)) { _gtk_source_iter_backward_visible_word_start (&tmp); } if (gtk_text_iter_get_line (&tmp) == gtk_text_iter_get_line (end)) { *end = tmp; } else { gtk_text_iter_forward_to_line_end (end); } } }
/** @brief scan forwards from @a start for text which matches @a lines This performs line-by-line case-insensitive comparisons It may be re-entrant, when @a lines has > 1 member @param start pointer to textiter in buffer where the search is to commence @param lines array of \n-trailing line-strings, together comprising the search string @param visible_only TRUE to ignore hidden chars in the text @param slice TRUE to include "unknown" (0xFFFC) chars in the text @param match_start textiter to store the start of a matching string, or NULL when re-entering to process line(s) after 1st @param match_end textiter store the start of a matching string, or NULL @return TRUE if a match was found */ static gboolean _e2_textiter_forward_lines_match ( const GtkTextIter *start, const gchar **lines, gboolean visible_only, gboolean slice, GtkTextIter *match_start, GtkTextIter *match_end) { GtkTextIter next; gchar *line_text; const gchar *found; gint offset; if (*lines == NULL || **lines == '\0') { //nothing to match, so everything matches if (match_start) *match_start = *start; if (match_end) *match_end = *start; return TRUE; } //CHECKME why break search into lines ? next = *start; if (!gtk_text_iter_forward_line (&next)) { if (gtk_text_iter_is_end (start)) return FALSE; else { next = *start; gtk_text_iter_forward_to_end (&next); //CHECKME } } else if (gtk_text_iter_equal (start, &next)) //no more text in buffer return FALSE; if (slice) { if (visible_only) line_text = gtk_text_iter_get_visible_slice (start, &next); else line_text = gtk_text_iter_get_slice (start, &next); } else { if (visible_only) line_text = gtk_text_iter_get_visible_text (start, &next); else line_text = gtk_text_iter_get_text (start, &next); } if (match_start != NULL) //if this is the first line we're matching { found = e2_utf8_strcasestr (line_text, *lines); } else { //not the first line, we have to match from the start of the line if (e2_utf8_caseless_match (line_text, *lines, -1, -1)) found = line_text; else found = NULL; } if (found == NULL) { g_free (line_text); return FALSE; } //get offset to start of search string offset = g_utf8_strlen (line_text, found - line_text); next = *start; /* If match start needs to be returned, set it to the start of the search string */ _e2_textiter_forward_chars_with_skipping (&next, offset, visible_only, !slice, FALSE); if (match_start != NULL) { *match_start = next; } //go to end of search string _e2_textiter_forward_chars_with_skipping (&next, g_utf8_strlen (*lines, -1), visible_only, !slice, TRUE); g_free (line_text); ++lines; if (match_end != NULL) *match_end = next; /* try to match the rest of the lines forward, passing NULL for match_start so lines_match will try to match the entire line */ return _e2_textiter_forward_lines_match (&next, lines, visible_only, slice, NULL, match_end); }
static VALUE rg_forward_to_end(VALUE self) { gtk_text_iter_forward_to_end(_SELF(self)); return self; }
/*-------------------------------textview------------------------------*/ static gboolean textview2_key_press_event_cb(GtkWidget *winParent, GdkEvent *event, gpointer userdata) { gboolean setFalseG = TRUE; /*Receive input in search mode*/ if (inSearch == TRUE) { unsigned int c = event->key.keyval; /*get keyval as char*/ if( c != GDK_KEY_KP_Enter && c != GDK_Return ) { if(isascii(c))/*can not input cjk thus not accounted*/ strOper++[0] = c; else if(c == GDK_BackSpace && strOper > searchStr) strOper--; else { ;/*skip*/ } strOper[0] = '\0'; } else { /*highlight and try moving forward to target on Enter*/ if(strlen(searchStr) != 0) { my_text_buffer_highlight(text2, searchStr, 4); myre_move_to_string(text2, searchStr, 1); } inSearch = FALSE; } if(inSearch) gtk_statusbar_push(status, gtk_statusbar_get_context_id(status,"status"), searchStr); else gtk_statusbar_push(status, gtk_statusbar_get_context_id(status, "status"), "End Search"); return TRUE; } switch(event->key.keyval) { case GDK_i: gtk_widget_grab_focus(entry); break; case GDK_I: gtk_widget_grab_focus(entry); gtk_editable_set_position((GtkEditable *)entry, 0); break; case GDK_a: case GDK_A: gtk_widget_grab_focus(entry); gtk_editable_set_position((GtkEditable *)entry, -1); break; case GDK_x: case GDK_X: button2_clicked_cb(); return TRUE; case GDK_j: case GDK_KEY_Down: g_signal_emit_by_name(textview2, "move-cursor", GTK_MOVEMENT_DISPLAY_LINES, 1, inSelect && inCursor, NULL); break; case GDK_k: case GDK_KEY_Up: g_signal_emit_by_name(textview2, "move-cursor", GTK_MOVEMENT_DISPLAY_LINES, -1, inSelect && inCursor, NULL); break; case GDK_h: case GDK_KEY_Left: g_signal_emit_by_name(textview2, "move-cursor", GTK_MOVEMENT_VISUAL_POSITIONS, -1, inSelect && inCursor, NULL); break; case GDK_l: case GDK_KEY_Right: g_signal_emit_by_name(textview2, "move-cursor", GTK_MOVEMENT_VISUAL_POSITIONS, 1, inSelect && inCursor, NULL); break; case GDK_w: case GDK_e: g_signal_emit_by_name(textview2, "move-cursor", GTK_MOVEMENT_WORDS, 1, inSelect && inCursor, NULL); break; case GDK_b: g_signal_emit_by_name(textview2, "move-cursor", GTK_MOVEMENT_WORDS, -1, inSelect && inCursor, NULL); break; case GDK_n: myre_move_to_string(text2, searchStr, 1); break; case GDK_N: myre_move_to_string(text2, searchStr, 0); break; case GDK_g: if(inVimG) { gtk_text_buffer_get_iter_at_offset(text2, ¤t, 0); gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(textview2), ¤t, 0, /* 0.0-0.5 screen */ TRUE, /* use xy align */ 0, /* x */ 0 /* y */ ); gtk_text_buffer_place_cursor(text2, ¤t); } inVimG = !inVimG; setFalseG = FALSE; break; case GDK_G: gtk_text_iter_forward_to_end (¤t); gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(textview2), ¤t, 0, TRUE, 0, 0 ); gtk_text_buffer_place_cursor(text2, ¤t); break; case GDK_KEY_slash: /* toggle search */ inSearch = !inSearch; if(NULL == searchStr) { searchStr = malloc(MAX_LENGTH); } /* try unmarking last search */ if (strlen(searchStr) != 0) { my_text_buffer_highlight(text2, searchStr, 5); } memset(searchStr, '\0', MAX_LENGTH); strOper = searchStr; gtk_statusbar_push(status, gtk_statusbar_get_context_id(status, "status"), "--Search--"); break; case GDK_KEY_KP_Enter: case GDK_Return: /*end search string input*/ inSearch = FALSE; break; case GDK_p: /* put selection to entry */ gtk_widget_grab_focus(entry); g_signal_emit_by_name(entry, "paste-clipboard", entry, NULL); break; case GDK_y: /* copy to clipboard */ if(gtk_text_buffer_get_has_selection(text2)) { g_signal_emit_by_name(textview2, "copy-clipboard", GTK_TEXT_VIEW(textview2), NULL); g_signal_emit_by_name(textview2, "move-cursor", GTK_MOVEMENT_VISUAL_POSITIONS, 0, FALSE, NULL); gtk_statusbar_push(status, gtk_statusbar_get_context_id(status, "status"), "Selection copied to clipboard."); /* cursor off after yank */ inCursor = FALSE; gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(textview2), inCursor); /* selection off */ inSelect = FALSE; } else /* vacant yank attempts */ gtk_statusbar_push(status, gtk_statusbar_get_context_id(status, "status"), "--Search--Empty Yank Ignored"); break; case GDK_v: /* toggle select mode */ if(!inCursor) /* make sure cursor is shown */ { inCursor = TRUE; vCursor = TRUE; gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(textview2), inCursor); } if (inSelect) { /* clear selection */ if(gtk_text_buffer_get_has_selection(text2)) g_signal_emit_by_name(textview2, "move-cursor", GTK_MOVEMENT_VISUAL_POSITIONS, 0, FALSE, NULL); gtk_statusbar_push(status, gtk_statusbar_get_context_id(status, "status"), ""); /* exit vCursor after move-cursor dependency */ if (inCursor && vCursor) { gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(textview2), FALSE); inCursor = FALSE; vCursor = FALSE; } } else { gtk_statusbar_push(status, gtk_statusbar_get_context_id(status, "status"), "--Selection--"); } inSelect = !inSelect; break; case GDK_c: /* always expire select mode */ inSelect = FALSE; /* clear selection, should be inCursor */ if(gtk_text_buffer_get_has_selection(text2)) g_signal_emit_by_name(textview2, "move-cursor", GTK_MOVEMENT_VISUAL_POSITIONS, 0, FALSE, NULL); gtk_statusbar_push(status, gtk_statusbar_get_context_id(status, "status"), ""); /* show cursor for selection */ inCursor = !inCursor; gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(textview2), inCursor); break; default: return FALSE; } if(setFalseG) inVimG = FALSE; if( !(inSearch || inSelect) ) { gtk_text_view_place_cursor_onscreen(GTK_TEXT_VIEW(textview2)); } return TRUE; }