summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Davenport <qball@gmpclient.org>2016-08-15 08:58:48 +0200
committerDave Davenport <qball@gmpclient.org>2016-08-15 09:01:56 +0200
commit26d1e64b22f728c512923c2c5b2fb0235addefd7 (patch)
tree2788fc308e6e0119f1fc8acd124e77269ff4f583
parentacdd8ddb5ae7c264d8dd29085368453e6f82cbce (diff)
Make textbox use character position instead of byte index for cursor.
-rw-r--r--source/textbox.c68
-rw-r--r--source/view.c2
-rw-r--r--source/x11-helper.c2
3 files changed, 38 insertions, 34 deletions
diff --git a/source/textbox.c b/source/textbox.c
index 6b78b7aa..0422b940 100644
--- a/source/textbox.c
+++ b/source/textbox.c
@@ -201,7 +201,7 @@ void textbox_text ( textbox *tb, const char *text )
textbox_moveresize ( tb, tb->widget.x, tb->widget.y, tb->widget.w, tb->widget.h );
}
- tb->cursor = MAX ( 0, MIN ( ( int ) strlen ( text ), tb->cursor ) );
+ tb->cursor = MAX ( 0, MIN ( ( int ) g_utf8_strlen ( tb->text, -1 ), tb->cursor ) );
}
// within the parent handled auto width/height modes
@@ -284,26 +284,24 @@ static void texbox_update ( textbox *tb )
cairo_set_operator ( tb->main_draw, CAIRO_OPERATOR_SOURCE );
pango_cairo_update_layout ( tb->main_draw, tb->layout );
- char *text = tb->text ? tb->text : "";
- int text_len = strlen ( text );
- int font_height = textbox_get_font_height ( tb );
+ int font_height = textbox_get_font_height ( tb );
- int cursor_x = 0;
- int cursor_width = MAX ( 2, font_height / 10 );
+ int cursor_x = 0;
+ int cursor_width = MAX ( 2, font_height / 10 );
if ( tb->changed ) {
__textbox_update_pango_text ( tb );
}
if ( tb->flags & TB_EDITABLE ) {
+ // We want to place the cursor based on the text shown.
+ const char *text = pango_layout_get_text ( tb->layout );
+ // Clamp the position, should not be needed, but we are paranoid.
+ int cursor_offset = MIN ( tb->cursor, g_utf8_strlen ( text, -1 ) );
PangoRectangle pos;
- int cursor_offset = 0;
- cursor_offset = MIN ( tb->cursor, text_len );
- if ( (tb->flags&TB_PASSWORD) == TB_PASSWORD ){
- cursor_offset = g_utf8_pointer_to_offset ( tb->text, tb->text+cursor_offset );
- }
- pango_layout_get_cursor_pos ( tb->layout, cursor_offset, &pos, NULL );
- // Add a small 4px offset between cursor and last glyph.
+ // convert to byte location.
+ char *offset = g_utf8_offset_to_pointer ( text, cursor_offset );
+ pango_layout_get_cursor_pos ( tb->layout, offset - text, &pos, NULL );
cursor_x = pos.x / PANGO_SCALE;
}
@@ -374,7 +372,7 @@ void textbox_draw ( textbox *tb, cairo_t *draw )
// cursor handling for edit mode
void textbox_cursor ( textbox *tb, int pos )
{
- int length = ( tb->text == NULL ) ? 0 : strlen ( tb->text );
+ int length = ( tb->text == NULL ) ? 0 : g_utf8_strlen ( tb->text, -1 );
tb->cursor = MAX ( 0, MIN ( length, pos ) );
tb->update = TRUE;
}
@@ -382,15 +380,13 @@ void textbox_cursor ( textbox *tb, int pos )
// move right
void textbox_cursor_inc ( textbox *tb )
{
- int index = g_utf8_next_char ( &( tb->text[tb->cursor] ) ) - tb->text;
- textbox_cursor ( tb, index );
+ textbox_cursor ( tb, tb->cursor + 1 );
}
// move left
void textbox_cursor_dec ( textbox *tb )
{
- int index = g_utf8_prev_char ( &( tb->text[tb->cursor] ) ) - tb->text;
- textbox_cursor ( tb, index );
+ textbox_cursor ( tb, tb->cursor - 1 );
}
// Move word right
@@ -400,7 +396,7 @@ static void textbox_cursor_inc_word ( textbox *tb )
return;
}
// Find word boundaries, with pango_Break?
- gchar *c = &( tb->text[tb->cursor] );
+ gchar *c = g_utf8_offset_to_pointer ( tb->text, tb->cursor );
while ( ( c = g_utf8_next_char ( c ) ) ) {
gunichar uc = g_utf8_get_char ( c );
GUnicodeBreakType bt = g_unichar_break_type ( uc );
@@ -420,7 +416,7 @@ static void textbox_cursor_inc_word ( textbox *tb )
break;
}
}
- int index = c - tb->text;
+ int index = g_utf8_pointer_to_offset ( tb->text, c );
textbox_cursor ( tb, index );
}
// move word left
@@ -428,7 +424,7 @@ static void textbox_cursor_dec_word ( textbox *tb )
{
// Find word boundaries, with pango_Break?
gchar *n;
- gchar *c = &( tb->text[tb->cursor] );
+ gchar *c = g_utf8_offset_to_pointer ( tb->text, tb->cursor );
while ( ( c = g_utf8_prev_char ( c ) ) && c != tb->text ) {
gunichar uc = g_utf8_get_char ( c );
GUnicodeBreakType bt = g_unichar_break_type ( uc );
@@ -451,7 +447,7 @@ static void textbox_cursor_dec_word ( textbox *tb )
}
}
}
- int index = c - tb->text;
+ int index = g_utf8_pointer_to_offset ( tb->text, c );
textbox_cursor ( tb, index );
}
@@ -463,14 +459,16 @@ void textbox_cursor_end ( textbox *tb )
tb->update = TRUE;
return;
}
- tb->cursor = ( int ) strlen ( tb->text );
+ tb->cursor = ( int ) g_utf8_strlen ( tb->text, -1 );
tb->update = TRUE;
}
// insert text
-void textbox_insert ( textbox *tb, int pos, char *str, int slen )
+void textbox_insert ( textbox *tb, int char_pos, char *str, int slen )
{
- int len = ( int ) strlen ( tb->text );
+ char *c = g_utf8_offset_to_pointer ( tb->text, char_pos );
+ int pos = c - tb->text;
+ int len = ( int ) strlen ( tb->text );
pos = MAX ( 0, MIN ( len, pos ) );
// expand buffer
tb->text = g_realloc ( tb->text, len + slen + 1 );
@@ -488,12 +486,19 @@ void textbox_insert ( textbox *tb, int pos, char *str, int slen )
// remove text
void textbox_delete ( textbox *tb, int pos, int dlen )
{
- int len = strlen ( tb->text );
+ int len = g_utf8_strlen ( tb->text, -1 );
+ if ( len == pos ) {
+ return;
+ }
pos = MAX ( 0, MIN ( len, pos ) );
+ if ( ( pos + dlen ) > len ) {
+ dlen = len - dlen;
+ }
// move everything after pos+dlen down
- char *at = tb->text + pos;
+ char *start = g_utf8_offset_to_pointer ( tb->text, pos );
+ char *end = g_utf8_offset_to_pointer ( tb->text, pos + dlen );
// Move remainder + closing \0
- memmove ( at, at + dlen, len - pos - dlen + 1 );
+ memmove ( start, end, ( tb->text + strlen ( tb->text ) ) - end + 1 );
if ( tb->cursor >= pos && tb->cursor < ( pos + dlen ) ) {
tb->cursor = pos;
}
@@ -511,8 +516,7 @@ void textbox_cursor_del ( textbox *tb )
if ( tb->text == NULL ) {
return;
}
- int index = g_utf8_next_char ( &( tb->text[tb->cursor] ) ) - tb->text;
- textbox_delete ( tb, tb->cursor, index - tb->cursor );
+ textbox_delete ( tb, tb->cursor, 1 );
}
// back up and delete one character
@@ -536,7 +540,7 @@ static void textbox_cursor_bkspc_word ( textbox *tb )
static void textbox_cursor_del_eol ( textbox *tb )
{
if ( tb->cursor >= 0 ) {
- int length = strlen ( tb->text ) - tb->cursor;
+ int length = g_utf8_strlen ( tb->text, -1 ) - tb->cursor;
if ( length >= 0 ) {
textbox_delete ( tb, tb->cursor, length );
}
@@ -640,7 +644,7 @@ gboolean textbox_append_char ( textbox *tb, char *pad, int pad_len )
if ( !g_unichar_iscntrl ( g_utf8_get_char ( pad ) ) ) {
tb->blink = 2;
textbox_insert ( tb, tb->cursor, pad, pad_len );
- textbox_cursor ( tb, tb->cursor + pad_len );
+ textbox_cursor ( tb, tb->cursor + 1 );
return TRUE;
}
return FALSE;
diff --git a/source/view.c b/source/view.c
index c8043186..21c0123a 100644
--- a/source/view.c
+++ b/source/view.c
@@ -1152,7 +1152,7 @@ static void rofi_view_paste ( RofiViewState *state, xcb_selection_notify_event_t
}
// Insert string move cursor.
textbox_insert ( state->text, state->text->cursor, text, dl );
- textbox_cursor ( state->text, state->text->cursor + dl );
+ textbox_cursor ( state->text, state->text->cursor + g_utf8_strlen(text, -1) );
// Force a redraw and refiltering of the text.
state->update = TRUE;
state->refilter = TRUE;
diff --git a/source/x11-helper.c b/source/x11-helper.c
index 689cd753..2bb46cdd 100644
--- a/source/x11-helper.c
+++ b/source/x11-helper.c
@@ -617,7 +617,7 @@ void x11_create_visual_and_colormap ( void )
xcb_visualtype_iterator_t visual_iter;
for ( visual_iter = xcb_depth_visuals_iterator ( d ); visual_iter.rem; xcb_visualtype_next ( &visual_iter ) ) {
xcb_visualtype_t *v = visual_iter.data;
- if ( (v->bits_per_rgb_value == 8) && ( d->depth == 32 ) && ( v->_class == XCB_VISUAL_CLASS_TRUE_COLOR ) ) {
+ if ( ( v->bits_per_rgb_value == 8 ) && ( d->depth == 32 ) && ( v->_class == XCB_VISUAL_CLASS_TRUE_COLOR ) ) {
depth = d;
visual = v;
}