diff options
author | Thomas White <taw@bitwiz.org.uk> | 2014-06-21 10:02:41 +0200 |
---|---|---|
committer | Thomas White <taw@bitwiz.org.uk> | 2014-06-21 10:02:41 +0200 |
commit | b36421467b4669dec503714bbf7be13fcfadc04e (patch) | |
tree | a14518cca12ff4bd78eb11ee5adb89ca9412b615 /src | |
parent | ceaa1b1f22ef86c5a592876c31e83cd04869b9ed (diff) |
Box offset logic
Diffstat (limited to 'src')
-rw-r--r-- | src/mainwindow.c | 17 | ||||
-rw-r--r-- | src/presentation.h | 2 | ||||
-rw-r--r-- | src/sc_parse.c | 50 | ||||
-rw-r--r-- | src/shape.c | 61 | ||||
-rw-r--r-- | src/wrap.c | 50 | ||||
-rw-r--r-- | src/wrap.h | 5 |
6 files changed, 105 insertions, 80 deletions
diff --git a/src/mainwindow.c b/src/mainwindow.c index ef89e8c..30f35e1 100644 --- a/src/mainwindow.c +++ b/src/mainwindow.c @@ -1132,22 +1132,18 @@ static void do_backspace(struct frame *fr, struct presentation *p) /* If this is, say, the top level frame, do nothing */ if ( fr->boxes == NULL ) return; - printf("Old: frame %p, line %i, box %i, pos %li\n", - p->cursor_frame, p->cursor_line, p->cursor_box, p->cursor_pos); sln = p->cursor_line; sbx = p->cursor_box; sps = p->cursor_pos; move_cursor_back(p); - printf("New: frame %p, line %i, box %i, pos %li\n", - p->cursor_frame, p->cursor_line, p->cursor_box, p->cursor_pos); - /* Delete may cross wrap boxes and maybe SCBlock boundaries */ struct wrap_box *sbox = &p->cursor_frame->lines[sln].boxes[sbx]; struct wrap_line *fline = &p->cursor_frame->lines[p->cursor_line]; struct wrap_box *fbox = &fline->boxes[p->cursor_box]; - sc_delete_text(fbox->scblock, p->cursor_pos, sbox->scblock, sps); + sc_delete_text(fbox->scblock, p->cursor_pos+fbox->offs_char, + sbox->scblock, sps+sbox->offs_char); rerender_slide(p); redraw_editor(p); @@ -1615,15 +1611,10 @@ static void move_cursor(struct presentation *p, signed int x, signed int y) if ( box->type == WRAP_BOX_PANGO ) { - char *np; - const char *box_text; - box_text = sc_block_contents(box->scblock) + box->offs; - np = g_utf8_offset_to_pointer(box_text, cp); - np = g_utf8_find_next_char(np, NULL); - if ( np > box_text+box->len_bytes ) { + if ( cp+1 > box->len_chars ) { advance = 1; } else { - cp = np - box_text; + cp++; } } else { diff --git a/src/presentation.h b/src/presentation.h index d66692e..8add695 100644 --- a/src/presentation.h +++ b/src/presentation.h @@ -144,7 +144,7 @@ struct presentation struct frame *cursor_frame; int cursor_line; int cursor_box; - size_t cursor_pos; + int cursor_pos; /* characters into box */ /* This is the "native" size of the slide. It only exists to give * font size some meaning in the context of a somewhat arbitrary DPI */ diff --git a/src/sc_parse.c b/src/sc_parse.c index 71dd449..fc6a40d 100644 --- a/src/sc_parse.c +++ b/src/sc_parse.c @@ -30,6 +30,7 @@ #include <string.h> #include <stdio.h> #include <ctype.h> +#include <glib.h> #include "sc_parse.h" @@ -378,7 +379,52 @@ SCBlock *sc_parse(const char *sc) } -void sc_delete_text(SCBlock *b1, int p1, SCBlock *b2, int p2) +static void delete_from_block(SCBlock *b, int o1, int o2) { - printf("Deleting from %p/%i to %p/%i\n", b1, p1, b2, p2); + assert(o2 > o1); + char *p1 = g_utf8_offset_to_pointer(b->contents, o1); + char *p2 = g_utf8_offset_to_pointer(b->contents, o2); + printf("'%s' (%p), chars %i to %i\n", b->contents, b->contents, o1, o2); + printf("moving %i bytes from %p to %p\n", strlen(p2)+1, p2, p1); + memmove(p1, p2, strlen(p2)+1); + printf("new: '%s'\n", b->contents); +} + + +static void delete_to_end(SCBlock *b, int offs) +{ + char *p = g_utf8_offset_to_pointer(b->contents, offs); + p[0] = '\0'; +} + + +static void delete_from_start(SCBlock *b, int offs) +{ + char *p = g_utf8_offset_to_pointer(b->contents, offs); + memmove(b->contents, p, strlen(p)+1); +} + + +/* Character offsets */ +void sc_delete_text(SCBlock *b1, int o1, SCBlock *b2, int o2) +{ + printf("Before:\n"); + show_sc_blocks(b1); + if ( b1 == b2 ) { + printf("--------> dfb\n"); + delete_from_block(b1, o1, o2); + } else if ( b2 == b1->next ) { + printf("--------> dte+dfs\n"); + delete_to_end(b1, o1); + delete_from_start(b2, o2); + } else { + printf("--------> dte+dfs+chain\n"); + delete_to_end(b1, o1); + delete_from_start(b2, o2); + while ( b1->next != b2 ) { + sc_block_free(b1->next); + } + } + printf("After:\n"); + show_sc_blocks(b1); } diff --git a/src/shape.c b/src/shape.c index 6078b55..e27db9a 100644 --- a/src/shape.c +++ b/src/shape.c @@ -40,7 +40,7 @@ struct box_adding_stuff struct wrap_line *line; SCInterpreter *scin; int editable; - char *text; + const char *text; enum wrap_box_space space; SCBlock *bl; size_t offs; @@ -70,8 +70,11 @@ static void add_wrap_box(gpointer vi, gpointer vb) box->ascent = sc_interp_get_ascent(bas->scin); box->height = sc_interp_get_height(bas->scin); box->scblock = bas->bl; - box->offs = bas->offs + item->offset; + box->offs_char = g_utf8_pointer_to_offset(bas->text, + bas->text+item->offset+bas->offs); box->len_bytes = item->length; + box->len_chars = g_utf8_strlen(bas->text+item->offset+bas->offs, + item->length); col = sc_interp_get_fgcol(bas->scin); box->col[0] = col[0]; /* Red */ box->col[1] = col[1]; /* Green */ @@ -80,8 +83,8 @@ static void add_wrap_box(gpointer vi, gpointer vb) box->glyphs = pango_glyph_string_new(); box->item = item; - pango_shape(bas->text+item->offset, item->length, &item->analysis, - box->glyphs); + pango_shape(bas->text+bas->offs+item->offset, item->length, + &item->analysis, box->glyphs); pango_glyph_string_extents(box->glyphs, box->font, NULL, &rect); @@ -98,10 +101,10 @@ static void add_wrap_box(gpointer vi, gpointer vb) /* Add "text", followed by a space of type "space", to "line" */ -static int add_wrap_boxes(struct wrap_line *line, char *text, +static int add_wrap_boxes(struct wrap_line *line, const char *text, enum wrap_box_space space, PangoContext *pc, SCInterpreter *scin, SCBlock *bl, size_t offs, - int editable) + size_t len, int editable) { GList *pango_items; PangoAttrList *attrs; @@ -111,7 +114,7 @@ static int add_wrap_boxes(struct wrap_line *line, char *text, attrs = pango_attr_list_new(); attr = pango_attr_font_desc_new(sc_interp_get_fontdesc(scin)); pango_attr_list_insert_before(attrs, attr); - pango_items = pango_itemize(pc, text, 0, strlen(text), attrs, NULL); + pango_items = pango_itemize(pc, text+offs, 0, len, attrs, NULL); bas.line = line; bas.scin = scin; @@ -137,7 +140,7 @@ void add_image_box(struct wrap_line *line, const char *filename, box = &line->boxes[line->n_boxes]; box->type = WRAP_BOX_IMAGE; box->scblock = NULL; - box->offs = 0; + box->offs_char = 0; box->space = WRAP_SPACE_NONE; box->width = pango_units_from_double(w); box->ascent = pango_units_from_double(h); @@ -175,7 +178,6 @@ int split_words(struct wrap_line *boxes, PangoContext *pc, SCBlock *bl, if ( log_attrs[i].is_line_break ) { - char *word; enum wrap_box_space type; size_t len; char *ptr; @@ -199,15 +201,8 @@ int split_words(struct wrap_line *boxes, PangoContext *pc, SCBlock *bl, type = WRAP_SPACE_NONE; } - word = strndup(text+start, len); - if ( word == NULL ) { - fprintf(stderr, "strndup() failed.\n"); - free(log_attrs); - return 1; - } - - if ( add_wrap_boxes(boxes, word, type, - pc, scin, bl, start, editable) ) { + if ( add_wrap_boxes(boxes, text, type, pc, scin, bl, + start, len, editable) ) { fprintf(stderr, "Failed to add wrap box.\n"); } start = offs; @@ -217,35 +212,23 @@ int split_words(struct wrap_line *boxes, PangoContext *pc, SCBlock *bl, } if ( i > start ) { - char *word; - size_t l; - - word = strdup(text+start); /* to the end */ - if ( word == NULL ) { - fprintf(stderr, "strndup() failed.\n"); - free(log_attrs); - return 1; - } - l = strlen(word); + size_t l = strlen(text+start); - if ( (word[l-1] == '\n') ) { + if ( (text[start+l-1] == '\n') ) { /* There is a newline at the end of the SC */ - char *word2; - - word2 = strndup(word, l-1); - add_wrap_boxes(boxes, word2, + add_wrap_boxes(boxes, text, WRAP_SPACE_EOP, pc, scin, bl, start, - editable); - add_wrap_boxes(boxes, strdup(""), - WRAP_SPACE_NONE, pc, scin, bl, start, - editable); + l-1, editable); + //add_wrap_boxes(boxes, "", + // WRAP_SPACE_NONE, pc, scin, bl, start+l, + // 1, editable); } else { - add_wrap_boxes(boxes, word, + add_wrap_boxes(boxes, text, WRAP_SPACE_NONE, pc, scin, bl, start, - editable); + l, editable); } @@ -123,6 +123,7 @@ void get_cursor_pos(struct wrap_box *box, size_t pos, double *xposd, double *yposd, double *line_height) { int p; + const char *block_text; const char *box_text; *xposd = 0.0; @@ -141,9 +142,10 @@ void get_cursor_pos(struct wrap_box *box, size_t pos, switch ( box->type ) { case WRAP_BOX_PANGO : - box_text = sc_block_contents(box->scblock) + box->offs; - pango_glyph_string_index_to_x(box->glyphs, - box_text, + block_text = sc_block_contents(box->scblock); + box_text = g_utf8_offset_to_pointer(block_text, box->offs_char); + /* cast because this function is not const-clean */ + pango_glyph_string_index_to_x(box->glyphs, (char *)box_text, box->len_bytes, &box->item->analysis, pos, FALSE, &p); @@ -173,15 +175,10 @@ void move_cursor_back(struct presentation *p) if ( box->type == WRAP_BOX_PANGO ) { - char *np; - const char *box_text; - box_text = sc_block_contents(box->scblock) + box->offs; - np = g_utf8_offset_to_pointer(box_text, cp); - np = g_utf8_find_prev_char(box_text, np); - if ( np == NULL ) { + if ( cp == 0 ) { retreat = 1; } else { - cp = np - box_text; + cp--; } } else { @@ -191,8 +188,6 @@ void move_cursor_back(struct presentation *p) if ( retreat ) { - const char *box_text; - do { cb--; @@ -211,10 +206,8 @@ void move_cursor_back(struct presentation *p) p->cursor_box = cb; box = &line->boxes[cb]; - box_text = sc_block_contents(box->scblock) + box->offs; if ( box->type == WRAP_BOX_PANGO ) { - cp = g_utf8_pointer_to_offset(box_text, - box_text+box->len_bytes); + cp = box->len_chars; } else { cp = 1; } @@ -269,7 +262,7 @@ static int find_cursor_box(struct frame *fr, struct wrap_line *l, void find_cursor(struct frame *fr, double xposd, double yposd, - int *line, int *box, size_t *pos) + int *line, int *box, int *pos) { struct wrap_line *l; struct wrap_box *b; @@ -279,6 +272,7 @@ void find_cursor(struct frame *fr, double xposd, double yposd, int x_pos_i; size_t offs; int ln, bn; + const char *block_text; const char *box_text; if ( fr->n_lines == 0 ) { @@ -313,12 +307,13 @@ void find_cursor(struct frame *fr, double xposd, double yposd, case WRAP_BOX_PANGO : x_pos_i = pango_units_from_double(x_pos); - box_text = sc_block_contents(b->scblock) + b->offs; - pango_glyph_string_x_to_index(b->glyphs, box_text, + block_text = sc_block_contents(b->scblock); + box_text = g_utf8_offset_to_pointer(block_text, b->offs_char); + /* cast because this function is not const-clean */ + pango_glyph_string_x_to_index(b->glyphs, (char *)box_text, b->len_bytes, &b->item->analysis, x_pos_i, &idx, &trail); - /* FIXME: Assumes 1 byte char */ offs = idx + trail; break; @@ -599,7 +594,7 @@ static void knuth_suboptimal_fit(struct wrap_line *boxes, double line_length, box->height = 0; box->editable = 1; box->scblock = NULL; - box->offs = 0; + box->offs_char = 0; boxes->n_boxes++; line_length *= PANGO_SCALE; @@ -821,10 +816,19 @@ void show_boxes(struct wrap_line *boxes) } for ( i=0; i<boxes->n_boxes; i++ ) { + struct wrap_box *box = &boxes->boxes[i]; + char *box_text; printf("%3i", i); - printf(" t=%i s=%i %i %5.2f\n", - boxes->boxes[i].type, boxes->boxes[i].space, - boxes->boxes[i].width, boxes->boxes[i].sp); + if ( box->scblock != NULL ) { + const char *block_text = sc_block_contents(box->scblock); + box_text = g_utf8_offset_to_pointer(block_text, + box->offs_char); + } else { + box_text = NULL; + } + printf(" t=%i s=%i %10i %5i %8.2f '%s'\n", + box->type, box->space, box->width, box->offs_char, + box->sp, box_text); } } @@ -62,7 +62,7 @@ struct wrap_box int editable; SCBlock *scblock; - size_t offs; /* offset into contents of scblock */ + int offs_char; /* offset (in characters, not bytes) into scblock */ /* Pango units */ int width; @@ -78,6 +78,7 @@ struct wrap_box PangoFont *font; double col[4]; /* rgba colour */ size_t len_bytes; /* number of bytes (not characters) of text */ + int len_chars; /* For type == WRAP_BOX_IMAGE */ char *filename; @@ -108,7 +109,7 @@ extern void get_cursor_pos(struct wrap_box *box, size_t pos, extern void move_cursor_back(struct presentation *p); extern void find_cursor(struct frame *fr, double xposd, double yposd, - int *line, int *box, size_t *pos); + int *line, int *box, int *pos); extern void alloc_boxes(struct wrap_line *l); extern void initialise_line(struct wrap_line *l); |