aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2017-10-19 21:42:48 +0200
committerThomas White <taw@physics.org>2017-10-19 22:33:48 +0200
commit7f2d0abd61d9d25c7c07ad1de1de2e6067c22b3e (patch)
tree1109d2a96d55d156eb70989686e39895980d96e7 /src
parent74be5482424aef26ea081aca0ccd0e5b6a5bcdcb (diff)
Track the newlines at ends of paragraphs directly
No more messing around searching for \n characters
Diffstat (limited to 'src')
-rw-r--r--src/frame.c97
-rw-r--r--src/frame.h5
-rw-r--r--src/sc_interp.c48
-rw-r--r--src/sc_parse.c47
-rw-r--r--src/sc_parse.h1
5 files changed, 101 insertions, 97 deletions
diff --git a/src/frame.c b/src/frame.c
index 8f1e3ec..010394f 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -51,7 +51,7 @@ struct _paragraph
enum para_type type;
double height;
float space[4];
- int newline_at_end;
+ SCBlock *newline_at_end;
/* For PARA_TYPE_TEXT */
int n_runs;
@@ -352,15 +352,15 @@ void wrap_paragraph(Paragraph *para, PangoContext *pc, double w,
para->height += para->space[2] + para->space[3];
}
-int get_newline_at_end(Paragraph *para)
+SCBlock *get_newline_at_end(Paragraph *para)
{
return para->newline_at_end;
}
-void set_newline_at_end(Paragraph *para)
+void set_newline_at_end(Paragraph *para, SCBlock *bl)
{
- para->newline_at_end = 1;
+ para->newline_at_end = bl;
}
@@ -917,6 +917,27 @@ void insert_text_in_paragraph(Paragraph *para, size_t offs, const char *t)
return;
}
+ if ( (sc_block_name(run->scblock) != NULL)
+ && (strcmp(sc_block_name(run->scblock), "newpara") == 0) )
+ {
+
+ SCBlock *nnp;
+ printf("Inserting into newpara block...\n");
+
+ /* Add a new \newpara block after this one */
+ nnp = sc_block_append(run->scblock, "newpara",
+ NULL, NULL, NULL);
+
+ /* The first \newpara block becomes a normal anonymous block */
+ sc_block_set_name(run->scblock, NULL);
+
+ if ( para->newline_at_end == run->scblock ) {
+ para->newline_at_end = nnp;
+ printf("Replaced the newpara block\n");
+ }
+
+ }
+
/* Translate paragraph offset for insertion into SCBlock offset */
run_offs = offs - run->para_offs_bytes;
scblock_offs = run_offs + run->scblock_offs_bytes;
@@ -1214,9 +1235,7 @@ void merge_paragraphs(struct frame *fr, int para)
{
Paragraph *p1, *p2;
struct text_run *runs_new;
- int i, j;
- size_t offs;
- SCBlock *scblock;
+ int i;
SCBlock *n;
if ( para >= fr->n_paras-1 ) {
@@ -1241,49 +1260,14 @@ void merge_paragraphs(struct frame *fr, int para)
}
p1->runs = runs_new;
- /* Locate the newline which we have just deleted. */
- scblock = p1->runs[p1->n_runs-1].scblock;
- n = sc_block_next(scblock);
- offs = p1->runs[p1->n_runs-1].scblock_offs_bytes;
- offs += p1->runs[p1->n_runs-1].len_bytes;
-
- if ( sc_block_contents(scblock)[offs] == '\n' ) {
-
- scblock_delete_text(scblock, offs, offs+1);
-
- /* Update the SC offset of any run from this SCBlock */
- for ( i=para+1; i<fr->n_paras; i++ ) {
- int done = 0;
- if ( fr->paras[i]->type != PARA_TYPE_TEXT ) break;
- for ( j=0; j<fr->paras[i]->n_runs; j++ ) {
- struct text_run *run = &fr->paras[i]->runs[j];
- if ( run->scblock == scblock ) {
- run->scblock_offs_bytes -= 1;
- } else {
- done = 1;
- break;
- }
- }
- if ( done ) break;
- }
-
- } else if ( (n!=NULL) && (sc_block_contents(n)[0] == '\n') ) {
-
- /* It's in the following SCBlock instead */
-
- const char *c = sc_block_contents(n);
- if ( strlen(c) == 1 ) {
- SCBlock *ss = scblock;
- sc_block_delete(&scblock, n);
- assert(ss == scblock);
- } else {
- scblock_delete_text(n, 0, 1);
- }
+ /* Delete the \newpara block to unite the paragraphs */
+ n = get_newline_at_end(p1);
+ assert(n != NULL);
+ sc_block_delete(&fr->scblocks, n);
- } else {
- printf("Couldn't find newline!\n");
- printf("Have '%s'\n", sc_block_contents(scblock)+offs);
- }
+ /* The end of the united paragraph should now be the end of the
+ * second one */
+ set_newline_at_end(p1, get_newline_at_end(p2));
for ( i=0; i<p2->n_runs; i++ ) {
@@ -1308,13 +1292,6 @@ void merge_paragraphs(struct frame *fr, int para)
}
-static char *s_strdup(const char *a)
-{
- if ( a == NULL ) return NULL;
- return strdup(a);
-}
-
-
static SCBlock *split_text_paragraph(struct frame *fr, int pn, size_t pos,
PangoContext *pc)
{
@@ -1425,10 +1402,10 @@ static SCBlock *split_text_paragraph(struct frame *fr, int pn, size_t pos,
pnew->runs[0].scblock_offs_bytes = 0;
}
- /* Add a newline after the end of the first paragraph's SC */
- sc_block_append(rr->scblock, s_strdup(sc_block_name(rr->scblock)),
- s_strdup(sc_block_options(rr->scblock)),
- strdup("\n"), NULL);
+ /* Add a \newpara after the end of the first paragraph's SC */
+ set_newline_at_end(para,
+ sc_block_append(rr->scblock, strdup("newpara"),
+ NULL, NULL, NULL));
pnew->open = para->open;
para->open = 0;
diff --git a/src/frame.h b/src/frame.h
index 1e46239..dbe79ef 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -131,8 +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 SCBlock *get_newline_at_end(Paragraph *para);
+extern void set_newline_at_end(Paragraph *para, SCBlock *bl);
+extern void check_run(struct frame *fr, int pn);
extern void add_run(Paragraph *para, SCBlock *scblock, SCBlock *macro_real,
size_t offs_bytes, size_t len_bytes,
diff --git a/src/sc_interp.c b/src/sc_interp.c
index df559e1..255fe91 100644
--- a/src/sc_interp.c
+++ b/src/sc_interp.c
@@ -887,13 +887,6 @@ 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)
@@ -916,35 +909,12 @@ static int add_text(struct frame *fr, PangoContext *pc, SCBlock *bl,
start = 0;
do {
- char *para_end;
- size_t len;
-
- para_end = strchr(text+start, '\n');
- if ( para_end == NULL ) {
- len = strlen(text+start);
- } else {
- len = para_end - (text+start);
- }
+ size_t len = strlen(text+start);
- if ( text[start] == '\n' ) {
- 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;
- } 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;
- }
+ Paragraph *para = last_open_para(fr);
+ add_run(para, bl, mrb, start, len, fontdesc, col);
+ set_para_spacing(para, st->paraspace);
+ start += len;
} while ( start < len_bytes );
@@ -1001,6 +971,14 @@ static int check_outputs(SCBlock *bl, SCInterpreter *scin)
set_frame(scin, fr);
maybe_recurse_after(scin, child);
+ } else if ( strcmp(name, "newpara")==0 ) {
+ struct frame *fr = sc_interp_get_frame(scin);
+ Paragraph *para = last_open_para(fr);
+ /* Add a dummy run which we can type into */
+ add_run(para, bl, NULL, 0, 0, fr->fontdesc, fr->col);
+ set_newline_at_end(para, bl);
+ close_last_paragraph(fr);
+
} else {
return 0;
}
diff --git a/src/sc_parse.c b/src/sc_parse.c
index 56ebcaf..79e59a0 100644
--- a/src/sc_parse.c
+++ b/src/sc_parse.c
@@ -296,6 +296,9 @@ char *serialise_sc_block(const SCBlock *bl)
if ( bl->name == NULL ) {
strcat(a, bl->contents);
+ } else if ( strcmp(bl->name, "newpara") == 0 ) {
+ strcat(a, "\n");
+
} else {
strcat(a, "\\");
@@ -503,6 +506,41 @@ static size_t read_block(const char *sc, char **pname, char **options,
}
+static void separate_newlines(SCBlock *bl)
+{
+ while ( bl != NULL ) {
+
+ char *npos;
+ const char *contents = sc_block_contents(bl);
+
+ if ( contents != NULL ) {
+ npos = strchr(contents, '\n');
+ if ( npos != NULL ) {
+ SCBlock *nb = NULL;
+ if ( npos == contents ) {
+ bl->name = strdup("newpara");
+ bl->contents = NULL;
+ nb = bl;
+ } else {
+ sc_block_append(bl, strdup("newpara"), NULL, NULL, &nb);
+ }
+ if ( strlen(npos+1) > 0 ) {
+ sc_block_append(nb, NULL, NULL, strdup(npos+1), &nb);
+ }
+ npos[0] = '\0';
+ }
+ }
+
+ if ( sc_block_child(bl) != NULL ) {
+ separate_newlines(sc_block_child(bl));
+ }
+
+ bl = sc_block_next(bl);
+
+ }
+}
+
+
SCBlock *sc_parse(const char *sc)
{
SCBlock *bl;
@@ -601,10 +639,19 @@ SCBlock *sc_parse(const char *sc)
j = 0;
}
+ separate_newlines(blf);
+
return blf;
}
+void sc_block_set_name(SCBlock *bl, char *nam)
+{
+ free(bl->name);
+ bl->name = nam;
+}
+
+
void sc_block_set_options(SCBlock *bl, char *opt)
{
free(bl->options);
diff --git a/src/sc_parse.h b/src/sc_parse.h
index 4775996..41a1112 100644
--- a/src/sc_parse.h
+++ b/src/sc_parse.h
@@ -65,6 +65,7 @@ extern void sc_block_unlink(SCBlock **top, SCBlock *deleteme);
extern SCBlock *find_last_child(SCBlock *bl);
+extern void sc_block_set_name(SCBlock *bl, char *nam);
extern void sc_block_set_options(SCBlock *bl, char *opt);
extern void sc_block_set_contents(SCBlock *bl, char *con);
extern void sc_insert_text(SCBlock *b1, size_t o1, const char *t);