From 8d69fd3d476179768d9e13d79261c5a1a7cacda4 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Mon, 14 Mar 2016 23:24:00 +0100 Subject: Fix frame creation --- src/frame.c | 15 ++++++++++++ src/frame.h | 5 ++++ src/sc_editor.c | 21 ++++++++++------- src/sc_interp.c | 2 ++ src/sc_parse.c | 4 ++++ src/shape.c | 71 +++++++++++++++++++++++++++++++++++++++------------------ src/shape.h | 2 ++ src/wrap.h | 1 + 8 files changed, 91 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/frame.c b/src/frame.c index c1dfd39..5b932e6 100644 --- a/src/frame.c +++ b/src/frame.c @@ -195,3 +195,18 @@ void delete_subframe(struct frame *top, struct frame *fr) parent->num_children--; } + +struct frame *find_frame_with_scblocks(struct frame *fr, SCBlock *scblocks) +{ + int i; + + if ( fr->scblocks == scblocks ) return fr; + + for ( i=0; inum_children; i++ ) { + struct frame *tt; + tt = find_frame_with_scblocks(fr->children[i], scblocks); + if ( tt != NULL ) return tt; + } + + return NULL; +} diff --git a/src/frame.h b/src/frame.h index 11ad36b..cd1bfa4 100644 --- a/src/frame.h +++ b/src/frame.h @@ -66,6 +66,9 @@ struct frame int max_lines; struct wrap_line *lines; + /* The font which will be used by default for this frame */ + PangoFontDescription *fontdesc; + /* The rectangle allocated to this frame, determined by the renderer */ double x; double y; @@ -101,5 +104,7 @@ extern void frame_free(struct frame *fr); extern struct frame *add_subframe(struct frame *fr); extern void show_hierarchy(struct frame *fr, const char *t); extern void delete_subframe(struct frame *top, struct frame *fr); +extern struct frame *find_frame_with_scblocks(struct frame *top, + SCBlock *scblocks); #endif /* FRAME_H */ diff --git a/src/sc_editor.c b/src/sc_editor.c index ce467f7..c2942f9 100644 --- a/src/sc_editor.c +++ b/src/sc_editor.c @@ -876,6 +876,7 @@ static void insert_text(char *t, SCEditor *e) sbox->col[1] = 0.0; sbox->col[2] = 0.0; sbox->col[3] = 0.0; + sbox->fontdesc = fr->fontdesc; sbox->n_segs = 1; sbox->segs = malloc(sizeof(struct text_seg)); sbox->len_chars = 0; @@ -896,6 +897,10 @@ static void insert_text(char *t, SCEditor *e) sc_insert_text(sbox->scblock, sps+sbox->offs_char, t); + /* The box must be analysed by Pango again, because the segments + * might have changed */ + itemize_and_shape(sbox, e->pc); + text = sc_block_contents(sbox->scblock); len_bytes = strlen(text); len_chars = g_utf8_strlen(text, -1); @@ -907,7 +912,7 @@ static void insert_text(char *t, SCEditor *e) offs = sbox->offs_char + e->cursor_pos; - if ( (len_chars > 0) && log_attrs[offs+1].is_line_break ) { + if ( (len_chars > 1) && log_attrs[offs+1].is_line_break ) { struct wrap_box *nbox; @@ -1360,6 +1365,7 @@ static struct frame *create_frame(SCEditor *e, double x, double y, { struct frame *parent; struct frame *fr; + SCBlock *scblocks; parent = e->top; @@ -1373,12 +1379,13 @@ static struct frame *create_frame(SCEditor *e, double x, double y, h = -h; } + /* Add to frame structure */ fr = add_subframe(parent); /* Add to SC */ - fr->scblocks = sc_block_append_end(e->scblocks, - "f", NULL, NULL); - sc_block_append_inside(fr->scblocks, NULL, NULL, strdup("")); + scblocks = sc_block_append_end(e->scblocks, "f", NULL, NULL); + fr->scblocks = scblocks; + sc_block_append_inside(scblocks, NULL, NULL, strdup("")); fr->x = x; fr->y = y; @@ -1388,12 +1395,10 @@ static struct frame *create_frame(SCEditor *e, double x, double y, fr->empty = 1; fr->resizable = 1; - fr->n_lines = 0; - fr->lines = NULL; - update_geom(fr); - return fr; + full_rerender(e); + return find_frame_with_scblocks(e->top, scblocks); } diff --git a/src/sc_interp.c b/src/sc_interp.c index 50a582b..9226c76 100644 --- a/src/sc_interp.c +++ b/src/sc_interp.c @@ -834,6 +834,8 @@ static int check_outputs(SCBlock *bl, SCInterpreter *scin) return 1; } + fr->fontdesc = sc_interp_get_fontdesc(scin); + parse_frame_options(fr, sc_interp_get_frame(scin), options); diff --git a/src/sc_parse.c b/src/sc_parse.c index ef9f3da..60a03ff 100644 --- a/src/sc_parse.c +++ b/src/sc_parse.c @@ -556,6 +556,10 @@ SCBlock *find_last_child(SCBlock *bl) void sc_insert_text(SCBlock *b1, int o1, const char *t) { + if ( b1->contents == NULL ) { + b1->contents = strdup(t); + return; + } size_t len = strlen(b1->contents)+1+strlen(t); char *cnew = realloc(b1->contents, len); char *tmp = malloc(len); diff --git a/src/shape.c b/src/shape.c index 2b6bc7a..bbbea87 100644 --- a/src/shape.c +++ b/src/shape.c @@ -42,6 +42,11 @@ static void shape_segment(struct wrap_box *box, struct text_seg *seg) const char *tp; const char *ep; + if ( seg->len_chars == 0 ) { + fprintf(stderr, "Shaping a zero-length segment\n"); + return; + } + tp = g_utf8_offset_to_pointer(sc_block_contents(box->scblock), box->offs_char + seg->offs_char); ep = g_utf8_offset_to_pointer(sc_block_contents(box->scblock), @@ -184,19 +189,52 @@ static void add_seg(gpointer vi, gpointer vb) } +int itemize_and_shape(struct wrap_box *box, PangoContext *pc) +{ + GList *pango_items; + PangoAttrList *attrs; + PangoAttribute *attr; + char *tptr; + char *eptr; + const char *text; + int nseg; + + text = sc_block_contents(box->scblock); + tptr = g_utf8_offset_to_pointer(text, box->offs_char); + eptr = g_utf8_offset_to_pointer(tptr, box->len_chars); + + /* Fill in the font, needed later for rendering */ + box->font = pango_font_map_load_font(pango_context_get_font_map(pc), + pc, box->fontdesc); + + attrs = pango_attr_list_new(); + attr = pango_attr_font_desc_new(box->fontdesc); + pango_attr_list_insert_before(attrs, attr); + pango_items = pango_itemize(pc, tptr, 0, eptr-tptr, attrs, NULL); + nseg = g_list_length(pango_items); + box->segs = malloc(nseg * sizeof(struct text_seg)); + if ( box->segs == NULL ) return 1; + + box->n_segs = 0; + g_list_foreach(pango_items, add_seg, box); + g_list_free(pango_items); + pango_attr_list_unref(attrs); + + calc_box_geometry(box); + + return 0; +} + + /* Add "text", followed by a space of type "space", to "line" */ static int add_text_box(struct boxvec *boxes, enum wrap_box_space space, PangoContext *pc, SCInterpreter *scin, SCBlock *bl, size_t offs, size_t len, int editable) { - GList *pango_items; struct wrap_box *box; - PangoAttrList *attrs; - PangoAttribute *attr; const char *tp; double *col; - int nseg; while ( len==0 ) { add_nothing_box(boxes, bl, editable, space, scin, offs); @@ -212,7 +250,7 @@ static int add_text_box(struct boxvec *boxes, box->type = WRAP_BOX_PANGO; box->space = space; - box->font = sc_interp_get_font(scin); + box->fontdesc = pango_font_description_copy(sc_interp_get_fontdesc(scin)); box->width = 0; box->editable = editable; box->ascent = sc_interp_get_ascent(scin); @@ -230,23 +268,12 @@ static int add_text_box(struct boxvec *boxes, box->col[2] = col[2]; /* Blue */ box->col[3] = col[3]; /* Alpha */ - 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, sc_block_contents(bl)+offs, - 0, len, attrs, NULL); - nseg = g_list_length(pango_items); - box->segs = malloc(nseg * sizeof(struct text_seg)); - if ( box->segs == NULL ) return 1; - - box->n_segs = 0; - g_list_foreach(pango_items, add_seg, box); - g_list_free(pango_items); - pango_attr_list_unref(attrs); - - calc_box_geometry(box); - - bv_add(boxes, box); + if ( itemize_and_shape(box, pc) == 0 ) { + bv_add(boxes, box); + } else { + fprintf(stderr, "Shaping error!\n"); + return 1; + } return 0; } diff --git a/src/shape.h b/src/shape.h index 43775a3..f9e1758 100644 --- a/src/shape.h +++ b/src/shape.h @@ -37,6 +37,8 @@ extern int split_words(struct boxvec *boxes, PangoContext *pc, SCBlock *bl, PangoLanguage *lang, int editable, SCInterpreter *scin); +extern int itemize_and_shape(struct wrap_box *box, PangoContext *pc); + extern void add_image_box(struct boxvec *line, const char *filename, int w, int h, int editable); diff --git a/src/wrap.h b/src/wrap.h index 0dcc190..f3df4e4 100644 --- a/src/wrap.h +++ b/src/wrap.h @@ -92,6 +92,7 @@ struct wrap_box /* For type == WRAP_BOX_PANGO */ PangoFont *font; + PangoFontDescription *fontdesc; double col[4]; /* rgba colour */ int len_chars; int n_segs; -- cgit v1.2.3