From cd5b7c2b8905619e2c66959178c92fc41a712eb7 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 11 Mar 2014 23:15:34 +0100 Subject: New way of doing cursor position --- src/frame.h | 2 -- src/mainwindow.c | 54 +++++++++++++++++++----------- src/presentation.h | 5 +++ src/render.c | 9 ----- src/shape.c | 1 - src/wrap.c | 98 +++++++++++++++++++++++++----------------------------- src/wrap.h | 7 ++-- 7 files changed, 87 insertions(+), 89 deletions(-) diff --git a/src/frame.h b/src/frame.h index e1cfccd..beb8187 100644 --- a/src/frame.h +++ b/src/frame.h @@ -53,8 +53,6 @@ struct frame int max_lines; struct wrap_line *lines; - size_t pos; - /* The rectangle allocated to this frame, determined by the renderer */ double x; double y; diff --git a/src/mainwindow.c b/src/mainwindow.c index ab75cdc..7c850cd 100644 --- a/src/mainwindow.c +++ b/src/mainwindow.c @@ -905,19 +905,33 @@ static void draw_editing_box(cairo_t *cr, struct frame *fr) } -static void draw_caret(cairo_t *cr, struct frame *fr, int pos) +static void draw_caret(cairo_t *cr, struct frame *fr, + int cursor_line, int cursor_box, int cursor_pos) { double xposd, yposd, line_height; double cx, clow, chigh; const double t = 1.8; + struct wrap_box *box; + int i; + + if ( fr == NULL ) return; + if ( fr->n_lines == 0 ) return; + printf("Cursor at frame %p, line %i, box %i, pos %i\n", + fr, cursor_line, cursor_box, cursor_pos); + + /* Locate the cursor in a "logical" and "geographical" sense */ + box = &fr->lines[cursor_line].boxes[cursor_box]; + get_cursor_pos(box, cursor_pos, &xposd, &yposd, &line_height); - /* Fix up cursor position if necessary */ - if ( (fr->n_lines > 0) && (fr->pos < fr->lines[0].sc_offset) ) { - fr->pos = fr->lines[0].sc_offset; - pos = fr->pos; + for ( i=0; ilines[i].height); } - get_cursor_pos(fr, pos, &xposd, &yposd, &line_height); + for ( i=0; ilines[cursor_line].boxes[i].width; + w += fr->lines[cursor_line].boxes[i].sp; + xposd += pango_units_to_double(w); + } cx = fr->x + xposd; clow = fr->y + yposd; @@ -976,7 +990,8 @@ static void draw_overlay(cairo_t *cr, struct presentation *p) /* If only one frame is selected, draw the caret */ if ( p->n_selection == 1 ) { - draw_caret(cr, p->selection[0], p->cursor_pos); + draw_caret(cr, p->cursor_frame, p->cursor_line, p->cursor_box, + p->cursor_pos); } if ( (p->drag_status == DRAG_STATUS_DRAGGING) @@ -1381,9 +1396,10 @@ static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event, } else { - clicked->pos = find_cursor_pos(clicked, - x-fr->x, y-fr->y); - p->cursor_pos = clicked->pos; + p->cursor_frame = clicked; + find_cursor(clicked, x-fr->x, y-fr->y, + &p->cursor_line, &p->cursor_box, + &p->cursor_pos); p->start_corner_x = event->x - p->border_offs_x; p->start_corner_y = event->y - p->border_offs_y; @@ -1583,22 +1599,20 @@ static gboolean button_release_sig(GtkWidget *da, GdkEventButton *event, static void move_cursor(struct presentation *p, signed int x, signed int y) { -#warning Re-implement move_cursor() please -#if 0 - ssize_t pos = p->cursor_pos; + struct wrap_line *line = &p->cursor_frame->lines[p->cursor_line]; + struct wrap_box *box = &line->boxes[p->cursor_box]; /* FIXME: Advance past images etc */ - pos += x; - if ( pos < 0 ) pos = 0; + p->cursor_pos += x; - if ( pos > strlen(p->selection[0]->sc) ) { - pos = strlen(p->selection[0]->sc); + if ( p->cursor_pos < 0 ) { + p->cursor_pos = 0; } - p->selection[0]->pos = pos; - p->cursor_pos = pos; -#endif + if ( p->cursor_pos > g_utf8_strlen(box->text, -1) ) { + p->cursor_pos = 0; + } } diff --git a/src/presentation.h b/src/presentation.h index 09c6878..d66692e 100644 --- a/src/presentation.h +++ b/src/presentation.h @@ -139,6 +139,11 @@ struct presentation struct frame **selection; int n_selection; int max_selection; + + /* Location of the cursor */ + struct frame *cursor_frame; + int cursor_line; + int cursor_box; size_t cursor_pos; /* This is the "native" size of the slide. It only exists to give diff --git a/src/render.c b/src/render.c index 49ff5c3..2d45261 100644 --- a/src/render.c +++ b/src/render.c @@ -110,7 +110,6 @@ static void render_image_box(cairo_t *cr, struct wrap_box *box, ImageStore *is, static void draw_outline(cairo_t *cr, struct wrap_box *box) { - char tmp[32]; double asc, desc; if ( box->type == WRAP_BOX_SENTINEL ) return; @@ -128,14 +127,6 @@ static void draw_outline(cairo_t *cr, struct wrap_box *box) pango_units_to_double(box->sp), asc + desc); cairo_set_source_rgb(cr, 0.7, 0.4, 0.7); cairo_fill(cr); - - snprintf(tmp, 31, "%lli", (long long int)box->sc_offset); - cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_ITALIC, - CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_font_size(cr, 10.0); - cairo_move_to(cr, 0.0, desc); - cairo_set_source_rgb(cr, 0.0, 0.0, 0.7); - cairo_show_text(cr, tmp); } diff --git a/src/shape.c b/src/shape.c index e54de09..4edd57b 100644 --- a/src/shape.c +++ b/src/shape.c @@ -79,7 +79,6 @@ static int add_wrap_box(struct wrap_line *line, char *text, size_t offset, box = &line->boxes[line->n_boxes]; if ( !editable ) offset = 0; - box->sc_offset = offset; box->type = WRAP_BOX_PANGO; box->text = text; box->space = space; diff --git a/src/wrap.c b/src/wrap.c index a929ad0..d419a1b 100644 --- a/src/wrap.c +++ b/src/wrap.c @@ -83,7 +83,7 @@ void initialise_line(struct wrap_line *l) } - +#if 0 static struct wrap_line *get_cursor_line(struct frame *fr, size_t pos, double *yposd) { @@ -117,56 +117,32 @@ static struct wrap_line *get_cursor_line(struct frame *fr, size_t pos, return &fr->lines[line]; } +#endif - -void get_cursor_pos(struct frame *fr, size_t pos, +void get_cursor_pos(struct wrap_box *box, size_t pos, double *xposd, double *yposd, double *line_height) { - signed int i; - struct wrap_line *l; - struct wrap_box *b; int p; - int box; *xposd = 0.0; *yposd = 0.0; *line_height = 20.0; - if ( fr->n_lines == 0 ) return; - - l = get_cursor_line(fr, pos, yposd); - if ( l == NULL ) return; - - *line_height = pango_units_to_double(l->height); - - for ( box=1; boxn_boxes; box++ ) { - /* Was the cursor in the previous box? */ - if ( !l->boxes[box].editable ) continue; - if ( l->boxes[box].type == WRAP_BOX_SENTINEL ) break; - if ( l->boxes[box].sc_offset > pos ) break; - } - box--; - - *xposd = fr->pad_l; - for ( i=0; iboxes[i].width); - *xposd += pango_units_to_double(l->boxes[i].sp); - } + if ( box == NULL ) return; - b = &l->boxes[box]; + *line_height = pango_units_to_double(box->height); - if ( !b->editable ) { - *xposd += pango_units_to_double(b->width); + if ( !box->editable ) { + *xposd += pango_units_to_double(box->width); return; } - switch ( b->type ) { + switch ( box->type ) { case WRAP_BOX_PANGO : - pango_glyph_string_index_to_x(b->glyphs, b->text, - strlen(b->text), - &b->item->analysis, - pos - b->sc_offset, + pango_glyph_string_index_to_x(box->glyphs, box->text, + strlen(box->text), + &box->item->analysis, pos, FALSE, &p); *xposd += pango_units_to_double(p); break; @@ -178,8 +154,7 @@ void get_cursor_pos(struct frame *fr, size_t pos, } -static struct wrap_line *find_cursor_line(struct frame *fr, double yposd, - int *end) +static int find_cursor_line(struct frame *fr, double yposd, int *end) { int i; double y = fr->pad_t; @@ -189,18 +164,18 @@ static struct wrap_line *find_cursor_line(struct frame *fr, double yposd, for ( i=0; in_lines; i++ ) { double height = pango_units_to_double(fr->lines[i].height); if ( yposd < y + height ) { - return &fr->lines[i]; + return i; } y += height; } *end = 1; - return &fr->lines[fr->n_lines-1]; + return fr->n_lines-1; } -static struct wrap_box *find_cursor_box(struct frame *fr, struct wrap_line *l, - double xposd, double *x_pos, int *end) +static int find_cursor_box(struct frame *fr, struct wrap_line *l, + double xposd, double *x_pos, int *end) { int i; double x = fr->pad_l; @@ -212,18 +187,19 @@ static struct wrap_box *find_cursor_box(struct frame *fr, struct wrap_line *l, width += pango_units_to_double(l->boxes[i].sp); if ( xposd < x + width ) { *x_pos = xposd - x; - return &l->boxes[i]; + return i; } x += width; } *end = 1; *x_pos = xposd - x; - return &l->boxes[l->n_boxes-1]; + return l->n_boxes-1; } -size_t find_cursor_pos(struct frame *fr, double xposd, double yposd) +void find_cursor(struct frame *fr, double xposd, double yposd, + int *line, int *box, size_t *pos) { struct wrap_line *l; struct wrap_box *b; @@ -231,19 +207,31 @@ size_t find_cursor_pos(struct frame *fr, double xposd, double yposd) double x_pos = 0.0; int idx, trail; int x_pos_i; + size_t offs; + int ln, bn; - if ( fr->n_lines == 0 ) return 0; + if ( fr->n_lines == 0 ) { + *line = 0; + *box = 0; + *pos = 0; + return; + } - l = find_cursor_line(fr, yposd, &end); + ln = find_cursor_line(fr, yposd, &end); + l = &fr->lines[ln]; + *line = ln; if ( end ) { - b = &l->boxes[l->n_boxes - 1]; + bn = l->n_boxes-1; } else { - b = find_cursor_box(fr, l, xposd, &x_pos, &end); + bn = find_cursor_box(fr, l, xposd, &x_pos, &end); } + b = &l->boxes[bn]; + *box = bn; if ( !b->editable ) { - return 0; + *pos = 0; + return; } switch ( b->type ) { @@ -259,14 +247,19 @@ size_t find_cursor_pos(struct frame *fr, double xposd, double yposd) &b->item->analysis, x_pos_i, &idx, &trail); /* FIXME: Assumes 1 byte char */ - return b->sc_offset + idx + trail; + offs = idx + trail; case WRAP_BOX_SENTINEL : - return l->boxes[l->n_boxes-2].sc_offset; + offs = 0; + break; + + default : + offs = 0; + break; } - return b->sc_offset; + *pos = offs; } @@ -458,7 +451,6 @@ 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]; } diff --git a/src/wrap.h b/src/wrap.h index 8fc057a..a4064e6 100644 --- a/src/wrap.h +++ b/src/wrap.h @@ -59,7 +59,6 @@ enum wrap_box_space struct wrap_box { enum wrap_box_type type; - size_t sc_offset; /* How far into the SC for this frame */ int editable; /* Pango units */ @@ -95,16 +94,16 @@ struct wrap_line int overfull; int underfull; int last_line; - size_t sc_offset; }; extern int wrap_contents(struct frame *fr); -extern void get_cursor_pos(struct frame *fr, size_t pos, +extern void get_cursor_pos(struct wrap_box *box, size_t pos, double *xposd, double *yposd, double *line_height); -extern size_t find_cursor_pos(struct frame *fr, double xposd, double yposd); +extern void find_cursor(struct frame *fr, double xposd, double yposd, + int *line, int *box, size_t *pos); extern void alloc_boxes(struct wrap_line *l); extern void initialise_line(struct wrap_line *l); -- cgit v1.2.3