diff options
author | Thomas White <taw@bitwiz.org.uk> | 2011-05-26 23:01:13 +0200 |
---|---|---|
committer | Thomas White <taw@bitwiz.org.uk> | 2011-05-26 23:01:13 +0200 |
commit | 91c2dcb3509f13c2f8aed925ebcec2381af692da (patch) | |
tree | 16a0355fcb3c43db8f9d5f9fa44af031a2d1f508 /src | |
parent | 8bcb4aa14d5e02b8c7ccab0ceb03f8876bb61e5b (diff) |
Add caret and basic keyboard editing
Diffstat (limited to 'src')
-rw-r--r-- | src/mainwindow.c | 23 | ||||
-rw-r--r-- | src/objects.c | 75 | ||||
-rw-r--r-- | src/objects.h | 4 | ||||
-rw-r--r-- | src/slide_render.c | 38 | ||||
-rw-r--r-- | src/slide_render.h | 2 |
5 files changed, 113 insertions, 29 deletions
diff --git a/src/mainwindow.c b/src/mainwindow.c index df5fd59..63b78f7 100644 --- a/src/mainwindow.c +++ b/src/mainwindow.c @@ -168,10 +168,23 @@ static gboolean key_press_sig(GtkWidget *da, GdkEventKey *event, if ( r ) return FALSE; /* IM ate it */ - if ( event->keyval == GDK_KEY_BackSpace ) { - if ( (p->editing_object != NULL) - && (p->editing_object->type == TEXT) ) { + if ( (p->editing_object != NULL) + && (p->editing_object->type == TEXT) ) + { + switch ( event->keyval ) { + + case GDK_KEY_BackSpace : handle_text_backspace(p->editing_object); + break; + + case GDK_KEY_Left : + move_cursor_left(p->editing_object); + break; + + case GDK_KEY_Right : + move_cursor_right(p->editing_object); + break; + } } @@ -231,11 +244,13 @@ static void draw_editing_box(cairo_t *cr, double xmin, double ymin, static void draw_editing_bits(cairo_t *cr, struct object *o) { + draw_editing_box(cr, o->x, o->y, o->bb_width, o->bb_height); + switch ( o->type ) { case TEXT : - draw_editing_box(cr, o->x, o->y, o->bb_width, o->bb_height); + draw_caret(cr, o); break; } diff --git a/src/objects.c b/src/objects.c index 372fac1..a66c3f5 100644 --- a/src/objects.c +++ b/src/objects.c @@ -37,19 +37,24 @@ static struct object *new_object(enum objtype t) { struct object *new; - new = malloc(sizeof(struct object)); + new = calloc(1, sizeof(struct object)); if ( new == NULL ) return NULL; new->type = t; new->empty = 1; new->parent = NULL; + new->layout = NULL; + new->fontdesc = NULL; + return new; } static void free_object(struct object *o) { + if ( o->layout != NULL ) g_object_unref(o->layout); + if ( o->fontdesc != NULL ) pango_font_description_free(o->fontdesc); free(o); } @@ -122,30 +127,60 @@ void insert_text(struct object *o, char *t) } -void handle_text_backspace(struct object *o) +static int find_prev_index(const char *t, int p) { - size_t ndel; - int i; + int i, nback; - assert(o->type == TEXT); + if ( p == 0 ) return 0; - if ( o->insertion_point == 0 ) return; /* Nothing to delete */ + if ( !(t[p-1] & 0x80) ) { + nback = 1; + } else { + nback = 0; + for ( i=1; i<=6; i++ ) { + if ( p-i == 0 ) return 0; + if ( !(t[p-i] & 0xC0) ) nback++; + } + } - if ( !(o->text[o->insertion_point-1] & 0x80) ) { - /* Simple (ASCII-style) backspace */ - ndel = 1; + return p - nback; +} + + +static int find_next_index(const char *t, int p) +{ + int i, nfor; + + if ( t[p] == '\0' ) return p; + + if ( !(t[p+1] & 0x80) ) { + nfor = 1; } else { - ndel = 0; + nfor = 0; for ( i=1; i<=6; i++ ) { - if ( !(o->text[o->insertion_point-i] & 0xC0) ) ndel++; + if ( t[p+i] == '\0' ) return p+i; + if ( !(t[p+i] & 0xC0) ) nfor++; } } - memmove(o->text+o->insertion_point-ndel, - o->text+o->insertion_point, + return p + nfor; +} + + +void handle_text_backspace(struct object *o) +{ + int prev_index; + + assert(o->type == TEXT); + + if ( o->insertion_point == 0 ) return; /* Nothing to delete */ + + prev_index = find_prev_index(o->text, o->insertion_point); + + memmove(o->text+prev_index, o->text+o->insertion_point, o->text_len-o->insertion_point); - o->insertion_point -= ndel; + o->insertion_point = prev_index; if ( strlen(o->text) == 0 ) o->empty = 1; @@ -153,6 +188,18 @@ void handle_text_backspace(struct object *o) } +void move_cursor_left(struct object *o) +{ + o->insertion_point = find_prev_index(o->text, o->insertion_point); +} + + +void move_cursor_right(struct object *o) +{ + o->insertion_point = find_next_index(o->text, o->insertion_point); +} + + void delete_object(struct object *o) { remove_object_from_slide(o->parent, o); diff --git a/src/objects.h b/src/objects.h index 7f4d39b..4decfea 100644 --- a/src/objects.h +++ b/src/objects.h @@ -53,12 +53,16 @@ struct object char *text; size_t text_len; int insertion_point; + PangoLayout *layout; + PangoFontDescription *fontdesc; }; extern struct object *add_text_object(struct slide *s, double x, double y); extern void insert_text(struct object *o, char *t); extern void handle_text_backspace(struct object *o); +extern void move_cursor_left(struct object *o); +extern void move_cursor_right(struct object *o); extern void delete_object(struct object *o); diff --git a/src/slide_render.c b/src/slide_render.c index cabf916..d0e5a5e 100644 --- a/src/slide_render.c +++ b/src/slide_render.c @@ -27,6 +27,7 @@ #include <cairo.h> #include <pango/pangocairo.h> +#include <assert.h> #include "slide_render.h" #include "presentation.h" @@ -35,18 +36,15 @@ static void render_text_object(cairo_t *cr, struct object *o) { - PangoLayout *l; - PangoFontDescription *d; int width, height; - l = pango_cairo_create_layout(cr); - pango_layout_set_text(l, o->text, -1); - d = pango_font_description_from_string("Sans 30"); - pango_layout_set_font_description(l, d); - pango_font_description_free(d); + o->layout = pango_cairo_create_layout(cr); + pango_layout_set_text(o->layout, o->text, -1); + o->fontdesc = pango_font_description_from_string("Sans 30"); + pango_layout_set_font_description(o->layout, o->fontdesc); - pango_cairo_update_layout(cr, l); - pango_layout_get_size(l, &width, &height); + pango_cairo_update_layout(cr, o->layout); + pango_layout_get_size(o->layout, &width, &height); o->bb_width = width/PANGO_SCALE; o->bb_height = height/PANGO_SCALE; @@ -54,7 +52,27 @@ static void render_text_object(cairo_t *cr, struct object *o) cairo_move_to(cr, o->x, o->y); cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); - pango_cairo_show_layout(cr, l); + pango_cairo_show_layout(cr, o->layout); +} + + +void draw_caret(cairo_t *cr, struct object *o) +{ + int line, xpos; + double xposd; + + assert(o->type == TEXT); + + pango_layout_index_to_line_x(o->layout, o->insertion_point, + 0, &line, &xpos); + + xposd = xpos/PANGO_SCALE; + + cairo_move_to(cr, o->x+xposd, o->y); + cairo_line_to(cr, o->x+xposd, o->y+o->bb_height); + cairo_set_source_rgb(cr, 1.0, 0.5, 0.0); + cairo_set_line_width(cr, 2.0); + cairo_stroke(cr); } diff --git a/src/slide_render.h b/src/slide_render.h index 500a3ed..5beb353 100644 --- a/src/slide_render.h +++ b/src/slide_render.h @@ -31,6 +31,6 @@ #include "presentation.h" extern int render_slide(struct slide *s); - +extern void draw_caret(cairo_t *cr, struct object *o); #endif /* SLIDE_RENDER_H */ |