aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2017-10-17 21:03:39 +0200
committerThomas White <taw@physics.org>2017-10-17 21:03:39 +0200
commit9c929b373d0ffa3fbd8e0de670caaab95b58a101 (patch)
treebe1637d5c46b63473cca591951b16b1099413f1e /src
parent54adeb60b85641f6c1d968200eeb5e5d705c51ea (diff)
Track newlines at end of paragraphs
Diffstat (limited to 'src')
-rw-r--r--src/debugger.c4
-rw-r--r--src/frame.c107
-rw-r--r--src/frame.h4
-rw-r--r--src/sc_interp.c17
4 files changed, 109 insertions, 23 deletions
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; i<fr->n_paras; i++ ) {
+ int j;
+ int done = 0;
+ Paragraph *para = fr->paras[i];
+ if ( para->type != PARA_TYPE_TEXT ) continue;
+ for ( j=0; j<para->n_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; i<para->n_runs; i++ ) {
int j;
struct text_run *run;
+ size_t nl = 0;
run = &para->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; j<para->n_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; i<fr->n_paras; i++ ) {
- int j;
- int done = 0;
- Paragraph *para = fr->paras[i];
- if ( para->type != PARA_TYPE_TEXT ) continue;
- for ( j=0; j<para->n_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 );