From 9c929b373d0ffa3fbd8e0de670caaab95b58a101 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 17 Oct 2017 21:03:39 +0200 Subject: Track newlines at end of paragraphs --- src/debugger.c | 4 +++ src/frame.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++---------- src/frame.h | 4 +++ src/sc_interp.c | 17 ++++++--- 4 files changed, 109 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/debugger.c b/src/debugger.c index 32cea14..15012e6 100644 --- a/src/debugger.c +++ b/src/debugger.c @@ -145,6 +145,10 @@ static void debug_text_para(Paragraph *para, cairo_t *cr, double *ypos, } } + + if ( get_newline_at_end(para) ) { + plot_text(cr, ypos, fontdesc, "Ends with newline"); + } } diff --git a/src/frame.c b/src/frame.c index 8c6acc6..8f1e3ec 100644 --- a/src/frame.c +++ b/src/frame.c @@ -51,6 +51,7 @@ struct _paragraph enum para_type type; double height; float space[4]; + int newline_at_end; /* For PARA_TYPE_TEXT */ int n_runs; @@ -351,6 +352,17 @@ void wrap_paragraph(Paragraph *para, PangoContext *pc, double w, para->height += para->space[2] + para->space[3]; } +int get_newline_at_end(Paragraph *para) +{ + return para->newline_at_end; +} + + +void set_newline_at_end(Paragraph *para) +{ + para->newline_at_end = 1; +} + void add_run(Paragraph *para, SCBlock *scblock, SCBlock *macro_real, size_t offs_bytes, size_t len_bytes, PangoFontDescription *fdesc, @@ -521,10 +533,25 @@ Paragraph *last_open_para(struct frame *fr) void close_last_paragraph(struct frame *fr) { if ( fr->paras == NULL ) return; + if ( fr->paras[fr->n_paras-1]->type != PARA_TYPE_TEXT ) { + printf("Closing a non-text paragraph!\n"); + } fr->paras[fr->n_paras-1]->open = 0; } +int last_para_available_for_text(struct frame *fr) +{ + Paragraph *last_para; + if ( fr->paras == NULL ) return 0; + last_para = fr->paras[fr->n_paras-1]; + if ( last_para->type == PARA_TYPE_TEXT ) { + if ( last_para->open ) return 1; + } + return 0; +} + + static void render_from_surf(cairo_surface_t *surf, cairo_t *cr, double w, double h, int border) { @@ -909,16 +936,39 @@ void insert_text_in_paragraph(Paragraph *para, size_t offs, const char *t) } -static void delete_paragraph(struct frame *fr, int p) +static void fixup_subsq(int first_para, struct frame *fr, SCBlock *scblock, + size_t del_len) +{ + int i; + + for ( i=first_para; in_paras; i++ ) { + int j; + int done = 0; + Paragraph *para = fr->paras[i]; + if ( para->type != PARA_TYPE_TEXT ) continue; + for ( j=0; jn_runs; j++ ) { + if ( para->runs[j].scblock != scblock) { + done = 1; + break; + } + printf("subsq para %p run %i del %i\n", para, i, (int)del_len); + para->runs[j].scblock_offs_bytes -= del_len; + } + if ( done ) break; + } +} + + +static void delete_text_paragraph(Paragraph *para, int p, struct frame *fr) { int i; - Paragraph *para = fr->paras[p]; /* Delete the corresponding SC */ for ( i=0; in_runs; i++ ) { int j; struct text_run *run; + size_t nl = 0; run = ¶->runs[i]; @@ -927,12 +977,22 @@ static void delete_paragraph(struct frame *fr, int p) continue; } + /* Find the newline at the end of the paragraph, if it + * exists */ + size_t toffs = run->scblock_offs_bytes + run->len_bytes; + if ( sc_block_contents(run->scblock)[toffs] == '\n' ) { + printf("Found newline when deleting paragraph\n"); + nl = 1; + } else { + printf("No newline when deleting paragraph\n"); + } + /* Delete from the corresponding SC block */ scblock_delete_text(run->scblock, run->scblock_offs_bytes, - run->scblock_offs_bytes + run->len_bytes); + run->scblock_offs_bytes + run->len_bytes+nl); /* Fix up the offsets of the subsequent text runs */ - size_t del_len = run->len_bytes; + size_t del_len = run->len_bytes + nl; run->len_bytes -= del_len; for ( j=i+1; jn_runs; j++ ) { if ( para->runs[j].scblock == run->scblock ) { @@ -940,6 +1000,28 @@ static void delete_paragraph(struct frame *fr, int p) } para->runs[j].para_offs_bytes -= del_len; } + + /* ... and in subsequent paragraphs, if they're from the same + * SCBlock */ + fixup_subsq(p+1, fr, run->scblock, del_len); + + } +} + + +static void delete_paragraph(struct frame *fr, int p) +{ + int i; + Paragraph *para = fr->paras[p]; + + if ( para->type != PARA_TYPE_TEXT ) { + if ( para->macro_real_scblock != NULL ) { + sc_block_delete(&fr->scblocks, para->macro_real_scblock); + } else { + sc_block_delete(&fr->scblocks, para->scblock); + } + } else { + delete_text_paragraph(para, p, fr); } /* Delete the paragraph from the frame */ @@ -1088,22 +1170,9 @@ size_t delete_text_in_paragraph(struct frame *fr, int npara, size_t offs1, ssize /* ... and in subsequent paragraphs, if they're from the same * SCBlock */ - for ( i=npara+1; in_paras; i++ ) { - int j; - int done = 0; - Paragraph *para = fr->paras[i]; - if ( para->type != PARA_TYPE_TEXT ) continue; - for ( j=0; jn_runs; j++ ) { - if ( para->runs[j].scblock != run->scblock) { - done = 1; - break; - } - printf("subsq para %p run %i del %i\n", para, i, (int)del_len); - para->runs[j].scblock_offs_bytes -= del_len; - } - if ( done ) break; - } + fixup_subsq(npara+1, fr, run->scblock, del_len); + offs1 -= del_len; offs2 -= del_len; } diff --git a/src/frame.h b/src/frame.h index c52df27..1e46239 100644 --- a/src/frame.h +++ b/src/frame.h @@ -123,6 +123,7 @@ extern double total_height(struct frame *fr); extern Paragraph *last_open_para(struct frame *fr); extern Paragraph *current_para(struct frame *fr); extern void close_last_paragraph(struct frame *fr); +extern int last_para_available_for_text(struct frame *fr); extern void show_para(Paragraph *p); extern void set_para_spacing(Paragraph *para, float space[4]); @@ -130,6 +131,9 @@ extern double paragraph_height(Paragraph *para); extern void render_paragraph(cairo_t *cr, Paragraph *para, ImageStore *is, enum is_size isz); +extern int get_newline_at_end(Paragraph *para); +extern void set_newline_at_end(Paragraph *para); + extern void add_run(Paragraph *para, SCBlock *scblock, SCBlock *macro_real, size_t offs_bytes, size_t len_bytes, PangoFontDescription *fdesc, double col[4]); diff --git a/src/sc_interp.c b/src/sc_interp.c index df00d5e..df559e1 100644 --- a/src/sc_interp.c +++ b/src/sc_interp.c @@ -887,6 +887,13 @@ static int in_macro(SCInterpreter *scin) } +static void set_newline_at_end_last_para(struct frame *fr) +{ + if ( fr->paras == NULL ) return; + set_newline_at_end(fr->paras[fr->n_paras-1]); +} + + /* Add the SCBlock to the text in 'frame', at the end */ static int add_text(struct frame *fr, PangoContext *pc, SCBlock *bl, PangoLanguage *lang, int editable, SCInterpreter *scin) @@ -895,7 +902,6 @@ static int add_text(struct frame *fr, PangoContext *pc, SCBlock *bl, size_t start, len_bytes; PangoFontDescription *fontdesc; double *col; - int just_closed = 0; struct sc_state *st = &scin->state[scin->j]; SCBlock *mrb; @@ -921,20 +927,23 @@ static int add_text(struct frame *fr, PangoContext *pc, SCBlock *bl, } if ( text[start] == '\n' ) { - if ( just_closed ) { + if ( !last_para_available_for_text(fr) ) { + /* Add an empty paragraph */ Paragraph *para = last_open_para(fr); add_run(para, bl, mrb, start, 0, fontdesc, col); set_para_spacing(para, st->paraspace); + set_newline_at_end(para); } + /* Close this paragraph */ + set_newline_at_end_last_para(fr); close_last_paragraph(fr); start += 1; - just_closed = 1; } else { + /* Just add some text */ Paragraph *para = last_open_para(fr); add_run(para, bl, mrb, start, len, fontdesc, col); set_para_spacing(para, st->paraspace); start += len; - just_closed = 0; } } while ( start < len_bytes ); -- cgit v1.2.3