From 561261eff94ab93131c23859fb850e6dc36f87ab Mon Sep 17 00:00:00 2001 From: Thomas White Date: Mon, 18 Mar 2013 23:52:13 +0100 Subject: Cursor position stuff --- src/mainwindow.c | 5 ++++- src/storycode.c | 15 ++++++++++----- src/storycode.h | 2 ++ src/wrap.c | 55 ++++++++++++++++++++++++++++++++++++------------------- src/wrap.h | 2 ++ 5 files changed, 54 insertions(+), 25 deletions(-) diff --git a/src/mainwindow.c b/src/mainwindow.c index 05f5a3d..562a95b 100644 --- a/src/mainwindow.c +++ b/src/mainwindow.c @@ -37,6 +37,7 @@ #include "render.h" #include "frame.h" #include "slideshow.h" +#include "wrap.h" /* Update a slide, once it's been edited in some way. */ @@ -566,6 +567,7 @@ static gint add_furniture(GtkWidget *widget, struct presentation *p) fr->sc_len = 6; set_selection(p, fr); fr->pos = 0; + p->cursor_pos = 0; do_slide_update(p, p->pc); @@ -919,8 +921,9 @@ static void insert_text(struct frame *fr, char *t, struct presentation *p) free(tmp); rerender_slide(p, p->pc); - redraw_editor(p); fr->pos += tlen; + p->cursor_pos = fr->pos; + redraw_editor(p); fr->empty = 0; } diff --git a/src/storycode.c b/src/storycode.c index 45638b4..53dc650 100644 --- a/src/storycode.c +++ b/src/storycode.c @@ -123,7 +123,7 @@ struct scblock *sc_block_list_next(SCBlockList *bl, SCBlockListIterator *iter) } -static int sc_block_list_add(SCBlockList *bl, +static int sc_block_list_add(SCBlockList *bl, size_t offset, char *name, char *options, char *contents) { if ( bl->n_blocks == bl->max_blocks ) { @@ -134,6 +134,7 @@ static int sc_block_list_add(SCBlockList *bl, bl->blocks[bl->n_blocks].name = name; bl->blocks[bl->n_blocks].options = options; bl->blocks[bl->n_blocks].contents = contents; + bl->blocks[bl->n_blocks].offset = offset; bl->n_blocks++; return 0; @@ -254,7 +255,7 @@ SCBlockList *sc_find_blocks(const char *sc, const char *blockname) { SCBlockList *bl; char *tbuf; - size_t len, i, j; + size_t len, i, j, start; bl = sc_block_list_new(); if ( bl == NULL ) return NULL; @@ -278,7 +279,7 @@ SCBlockList *sc_find_blocks(const char *sc, const char *blockname) if ( (blockname == NULL) && (j != 0) ) { tbuf[j] = '\0'; - if ( sc_block_list_add(bl, NULL, NULL, + if ( sc_block_list_add(bl, i, NULL, NULL, strdup(tbuf)) ) { fprintf(stderr, @@ -302,7 +303,7 @@ SCBlockList *sc_find_blocks(const char *sc, const char *blockname) if ( (blockname == NULL) || ((blockname != NULL) && !strcmp(blockname, name)) ) { - if ( sc_block_list_add(bl, name, options, + if ( sc_block_list_add(bl, i, name, options, contents) ) { fprintf(stderr, @@ -313,6 +314,10 @@ SCBlockList *sc_find_blocks(const char *sc, const char *blockname) } } + /* Start of the next block */ + start = i; + + } else { tbuf[j++] = sc[i++]; @@ -322,7 +327,7 @@ SCBlockList *sc_find_blocks(const char *sc, const char *blockname) if ( (blockname == NULL) && (j != 0) ) { tbuf[j] = '\0'; - if ( sc_block_list_add(bl, NULL, NULL, tbuf) ) + if ( sc_block_list_add(bl, start, NULL, NULL, tbuf) ) { fprintf(stderr, "Failed to add block.\n"); diff --git a/src/storycode.h b/src/storycode.h index 39ff18b..fbdd53f 100644 --- a/src/storycode.h +++ b/src/storycode.h @@ -33,6 +33,8 @@ struct scblock char *name; char *options; char *contents; + + size_t offset; }; struct scblock *sc_block_list_first(SCBlockList *bl, diff --git a/src/wrap.c b/src/wrap.c index e040d25..ca841f5 100644 --- a/src/wrap.c +++ b/src/wrap.c @@ -83,28 +83,43 @@ static void initialise_line(struct wrap_line *l) void get_cursor_pos(struct frame *fr, size_t pos, double *xposd, double *yposd, double *line_height) { - signed int line; + int line, box; int i; + struct wrap_line *l; + struct wrap_box *b; + int p; *xposd = 0; *yposd = 0; line = 0; - for ( i=0; in_lines; i++ ) { + for ( i=0; in_lines-1; i++ ) { line = i; - if ( fr->lines[i].sc_offset > pos ) { - line = i-1; - break; - } + if ( fr->lines[i+1].sc_offset > pos ) break; *yposd += fr->lines[i].height; - *line_height = pango_units_to_double(fr->lines[i].height); } assert(line >= 0); - *xposd += fr->lop.pad_l; - + *line_height = pango_units_to_double(fr->lines[line].height); *yposd /= PANGO_SCALE; *yposd += fr->lop.pad_t; + + l = &fr->lines[line]; + box = 0; + for ( i=0; in_boxes-1; i++ ) { + box = i; + if ( l->boxes[i+1].sc_offset > pos ) break; + *xposd += l->boxes[i].width; + *xposd += l->boxes[i].sp; + } + + b = &l->boxes[box]; + pango_glyph_string_index_to_x(b->glyphs, b->text, strlen(b->text), + &b->item->analysis, pos - b->sc_offset, + FALSE, &p); + *xposd += p; + *xposd /= PANGO_SCALE; + *xposd += fr->lop.pad_l; } @@ -116,6 +131,7 @@ static void shape_and_measure(gpointer data, gpointer user_data) /* FIXME: Don't assume only one run per wrap box */ box->glyphs = pango_glyph_string_new(); + box->item = item; pango_shape(box->text+item->offset, item->length, &item->analysis, box->glyphs); @@ -129,8 +145,6 @@ static void shape_and_measure(gpointer data, gpointer user_data) if ( PANGO_ASCENT(rect) > box->ascent ) { box->ascent = PANGO_ASCENT(rect); } - - pango_item_free(item); } @@ -151,7 +165,7 @@ static void calc_line_geometry(struct wrap_line *line) /* Add "text", followed by a space of type "space", to "line" */ -static int add_wrap_box(struct wrap_line *line, char *text, +static int add_wrap_box(struct wrap_line *line, char *text, size_t offset, enum wrap_box_space space, PangoContext *pc, PangoFont *font, PangoFontDescription *fontdesc, double col[4]) @@ -168,6 +182,7 @@ static int add_wrap_box(struct wrap_line *line, char *text, } box = &line->boxes[line->n_boxes]; + box->sc_offset = offset; box->type = WRAP_BOX_PANGO; box->text = text; box->space = space; @@ -194,7 +209,7 @@ static int add_wrap_box(struct wrap_line *line, char *text, static int split_words(struct wrap_line *boxes, PangoContext *pc, char *sc, - PangoLanguage *lang, + size_t sc_offset, PangoLanguage *lang, PangoFont *font, PangoFontDescription *fontdesc, double col[4]) { @@ -245,8 +260,8 @@ static int split_words(struct wrap_line *boxes, PangoContext *pc, char *sc, return 1; } - if ( add_wrap_box(boxes, word, type, pc, font, fontdesc, - col) ) { + if ( add_wrap_box(boxes, word, start, type, pc, + font, fontdesc, col) ) { fprintf(stderr, "Failed to add wrap box.\n"); } start = i; @@ -264,8 +279,8 @@ static int split_words(struct wrap_line *boxes, PangoContext *pc, char *sc, return 1; } - add_wrap_box(boxes, word, WRAP_SPACE_NONE, pc, font, fontdesc, - col); + add_wrap_box(boxes, word, start, WRAP_SPACE_NONE, pc, + font, fontdesc, col); } @@ -322,8 +337,8 @@ static struct wrap_line *sc_to_wrap_boxes(const char *sc, PangoContext *pc) b = sc_block_list_next(bl, iter) ) { if ( b->name == NULL ) { - if ( split_words(boxes, pc, b->contents, lang, - font, fontdesc, col) ) { + if ( split_words(boxes, pc, b->contents, b->offset, + lang, font, fontdesc, col) ) { fprintf(stderr, "Splitting failed.\n"); } } @@ -507,6 +522,7 @@ static void output_line(int q, int s, struct frame *fr, struct wrap_line *boxes) l->max_boxes = s-q; alloc_boxes(l); + l->sc_offset = boxes->boxes[q].sc_offset; for ( j=q; jboxes[l->n_boxes++] = boxes->boxes[j]; } @@ -739,6 +755,7 @@ void wrap_line_free(struct wrap_line *l) case WRAP_BOX_PANGO : pango_glyph_string_free(l->boxes[i].glyphs); + pango_item_free(l->boxes[i].item); free(l->boxes[i].text); break; diff --git a/src/wrap.h b/src/wrap.h index 2dd81ce..2bdc8dc 100644 --- a/src/wrap.h +++ b/src/wrap.h @@ -57,6 +57,7 @@ enum wrap_box_space struct wrap_box { enum wrap_box_type type; + size_t sc_offset; /* How far into the SC for this frame */ /* Pango units */ int width; @@ -68,6 +69,7 @@ struct wrap_box /* For type == WRAP_BOX_PANGO */ PangoGlyphString *glyphs; + PangoItem *item; PangoFont *font; char *text; double col[4]; /* rgba colour */ -- cgit v1.2.3