static VALUE rg_x_to_index(VALUE self, VALUE x_pos) { int index, trailing; gboolean ret = pango_layout_line_x_to_index(_SELF(self), NUM2INT(x_pos), &index, &trailing); return rb_ary_new3(CBOOL2RVAL(ret), INT2NUM(index), INT2NUM(trailing)); }
JNIEXPORT jboolean JNICALL Java_org_gnome_pango_PangoLayoutLine_pango_1layout_1line_1x_1to_1index ( JNIEnv* env, jclass cls, jlong _self, jint _xPos, jintArray _index, jintArray _trailing ) { gboolean result; jboolean _result; PangoLayoutLine* self; int xPos; int* index; int* trailing; // convert parameter self self = (PangoLayoutLine*) _self; // convert parameter xPos xPos = (int) _xPos; // convert parameter index index = (int*) (*env)->GetIntArrayElements(env, _index, NULL); if (index == NULL) { return JNI_FALSE; // Java Exception already thrown } // convert parameter trailing trailing = (int*) (*env)->GetIntArrayElements(env, _trailing, NULL); if (trailing == NULL) { return JNI_FALSE; // Java Exception already thrown } // call function result = pango_layout_line_x_to_index(self, xPos, index, trailing); // cleanup parameter self // cleanup parameter xPos // cleanup parameter index (*env)->ReleaseIntArrayElements(env, _index, (jint*)index, 0); // cleanup parameter trailing (*env)->ReleaseIntArrayElements(env, _trailing, (jint*)trailing, 0); // translate return value to JNI type _result = (jboolean) result; // and finally return _result; }
static void ellipsize_layout (PangoLayout *layout, gint width) { PangoLayoutLine *line; PangoLayout *ell; gint h, w, ell_w, x; GString *text; if (width <= 0) { pango_layout_set_text (layout, "", -1); return; } pango_layout_get_pixel_size (layout, &w, &h); if (w <= width) return; /* calculate ellipsis width */ ell = pango_layout_copy (layout); pango_layout_set_text (ell, ELLIPSIS, -1); pango_layout_get_pixel_size (ell, &ell_w, NULL); g_object_unref (ell); if (width < ell_w) { /* not even ellipsis fits, so hide the text */ pango_layout_set_text (layout, "", -1); return; } /* shrink total available width by the width of the ellipsis */ width -= ell_w; line = pango_layout_get_line (layout, 0); text = g_string_new (pango_layout_get_text (layout)); if (pango_layout_line_x_to_index (line, width * PANGO_SCALE, &x, NULL)) { g_string_set_size (text, x); g_string_append (text, ELLIPSIS); pango_layout_set_text (layout, text->str, -1); } g_string_free (text, TRUE); }
static void gimp_text_tool_move_cursor (GimpTextTool *text_tool, GtkMovementStep step, gint count, gboolean extend_selection) { GtkTextBuffer *buffer = GTK_TEXT_BUFFER (text_tool->buffer); GtkTextIter cursor; GtkTextIter selection; GtkTextIter *sel_start; gboolean cancel_selection = FALSE; gint x_pos = -1; GIMP_LOG (TEXT_EDITING, "%s count = %d, select = %s", g_enum_get_value (g_type_class_ref (GTK_TYPE_MOVEMENT_STEP), step)->value_name, count, extend_selection ? "TRUE" : "FALSE"); gtk_text_buffer_get_iter_at_mark (buffer, &cursor, gtk_text_buffer_get_insert (buffer)); gtk_text_buffer_get_iter_at_mark (buffer, &selection, gtk_text_buffer_get_selection_bound (buffer)); if (extend_selection) { sel_start = &selection; } else { /* when there is a selection, moving the cursor without * extending it should move the cursor to the end of the * selection that is in moving direction */ if (count > 0) gtk_text_iter_order (&selection, &cursor); else gtk_text_iter_order (&cursor, &selection); sel_start = &cursor; /* if we actually have a selection, just move *to* the beginning/end * of the selection and not *from* there on LOGICAL_POSITIONS * and VISUAL_POSITIONS movement */ if (! gtk_text_iter_equal (&cursor, &selection)) cancel_selection = TRUE; } switch (step) { case GTK_MOVEMENT_LOGICAL_POSITIONS: if (! cancel_selection) gtk_text_iter_forward_visible_cursor_positions (&cursor, count); break; case GTK_MOVEMENT_VISUAL_POSITIONS: if (! cancel_selection) { PangoLayout *layout; const gchar *text; if (! gimp_text_tool_ensure_layout (text_tool)) break; layout = gimp_text_layout_get_pango_layout (text_tool->layout); text = pango_layout_get_text (layout); while (count != 0) { const gunichar word_joiner = 8288; /*g_utf8_get_char(WORD_JOINER);*/ gint index; gint trailing = 0; gint new_index; index = gimp_text_buffer_get_iter_index (text_tool->buffer, &cursor, TRUE); if (count > 0) { if (g_utf8_get_char (text + index) == word_joiner) pango_layout_move_cursor_visually (layout, TRUE, index, 0, 1, &new_index, &trailing); else new_index = index; pango_layout_move_cursor_visually (layout, TRUE, new_index, trailing, 1, &new_index, &trailing); count--; } else { pango_layout_move_cursor_visually (layout, TRUE, index, 0, -1, &new_index, &trailing); if (new_index != -1 && new_index != G_MAXINT && g_utf8_get_char (text + new_index) == word_joiner) { pango_layout_move_cursor_visually (layout, TRUE, new_index, trailing, -1, &new_index, &trailing); } count++; } if (new_index != G_MAXINT && new_index != -1) index = new_index; else break; gimp_text_buffer_get_iter_at_index (text_tool->buffer, &cursor, index, TRUE); gtk_text_iter_forward_chars (&cursor, trailing); } } break; case GTK_MOVEMENT_WORDS: if (count < 0) { gtk_text_iter_backward_visible_word_starts (&cursor, -count); } else if (count > 0) { if (! gtk_text_iter_forward_visible_word_ends (&cursor, count)) gtk_text_iter_forward_to_line_end (&cursor); } break; case GTK_MOVEMENT_DISPLAY_LINES: { GtkTextIter start; GtkTextIter end; gint cursor_index; PangoLayout *layout; PangoLayoutLine *layout_line; PangoLayoutIter *layout_iter; PangoRectangle logical; gint line; gint trailing; gint i; gtk_text_buffer_get_bounds (buffer, &start, &end); cursor_index = gimp_text_buffer_get_iter_index (text_tool->buffer, &cursor, TRUE); if (! gimp_text_tool_ensure_layout (text_tool)) break; layout = gimp_text_layout_get_pango_layout (text_tool->layout); pango_layout_index_to_line_x (layout, cursor_index, FALSE, &line, &x_pos); layout_iter = pango_layout_get_iter (layout); for (i = 0; i < line; i++) pango_layout_iter_next_line (layout_iter); pango_layout_iter_get_line_extents (layout_iter, NULL, &logical); x_pos += logical.x; pango_layout_iter_free (layout_iter); /* try to go to the remembered x_pos if it exists *and* we are at * the beginning or at the end of the current line */ if (text_tool->x_pos != -1 && (x_pos <= logical.x || x_pos >= logical.x + logical.width)) x_pos = text_tool->x_pos; line += count; if (line < 0) { cursor = start; break; } else if (line >= pango_layout_get_line_count (layout)) { cursor = end; break; } layout_iter = pango_layout_get_iter (layout); for (i = 0; i < line; i++) pango_layout_iter_next_line (layout_iter); layout_line = pango_layout_iter_get_line_readonly (layout_iter); pango_layout_iter_get_line_extents (layout_iter, NULL, &logical); pango_layout_iter_free (layout_iter); pango_layout_line_x_to_index (layout_line, x_pos - logical.x, &cursor_index, &trailing); gimp_text_buffer_get_iter_at_index (text_tool->buffer, &cursor, cursor_index, TRUE); while (trailing--) gtk_text_iter_forward_char (&cursor); } break; case GTK_MOVEMENT_PAGES: /* well... */ case GTK_MOVEMENT_BUFFER_ENDS: if (count < 0) { gtk_text_buffer_get_start_iter (buffer, &cursor); } else if (count > 0) { gtk_text_buffer_get_end_iter (buffer, &cursor); } break; case GTK_MOVEMENT_PARAGRAPH_ENDS: if (count < 0) { gtk_text_iter_set_line_offset (&cursor, 0); } else if (count > 0) { if (! gtk_text_iter_ends_line (&cursor)) gtk_text_iter_forward_to_line_end (&cursor); } break; case GTK_MOVEMENT_DISPLAY_LINE_ENDS: if (count < 0) { gtk_text_iter_set_line_offset (&cursor, 0); } else if (count > 0) { if (! gtk_text_iter_ends_line (&cursor)) gtk_text_iter_forward_to_line_end (&cursor); } break; default: return; } text_tool->x_pos = x_pos; gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool)); gimp_text_tool_reset_im_context (text_tool); gtk_text_buffer_select_range (buffer, &cursor, sel_start); gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool)); }