aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.org.uk>2016-02-14 21:21:14 +0100
committerThomas White <taw@bitwiz.org.uk>2016-02-14 21:21:14 +0100
commit8ebf31b8a43e4f8fbc2bffd45013ffb50a51440e (patch)
tree7fe6b8d25b74bf77c463b47a51cb3da929863e5c /src
parent86f4ccb39fd02d25c98201e56dfdc2f105ee0c75 (diff)
Rationalise box handling (needs debugging)
Diffstat (limited to 'src')
-rw-r--r--src/boxvec.c98
-rw-r--r--src/boxvec.h63
-rw-r--r--src/frame.c9
-rw-r--r--src/frame.h10
-rw-r--r--src/render.c13
-rw-r--r--src/sc_editor.c88
-rw-r--r--src/shape.c59
-rw-r--r--src/shape.h6
-rw-r--r--src/wrap.c244
-rw-r--r--src/wrap.h13
10 files changed, 313 insertions, 290 deletions
diff --git a/src/boxvec.c b/src/boxvec.c
new file mode 100644
index 0000000..06754e6
--- /dev/null
+++ b/src/boxvec.c
@@ -0,0 +1,98 @@
+/*
+ * boxvec.c
+ *
+ * Copyright © 2016 Thomas White <taw@bitwiz.org.uk>
+ *
+ * This file is part of Colloquium.
+ *
+ * Colloquium is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "boxvec.h"
+
+
+int bv_len(struct boxvec *vec)
+{
+ return vec->n_boxes;
+}
+
+
+extern struct boxvec *bv_new()
+{
+ struct boxvec *n = malloc(sizeof(struct boxvec));
+ if ( n == NULL ) return NULL;
+
+ n->n_boxes = 0;
+ n->max_boxes = 0;
+ n->boxes = NULL;
+
+ return NULL;
+}
+
+
+int bv_ensure_space(struct boxvec *vec, int n)
+{
+ struct wrap_box **t;
+ if ( vec == NULL ) return 1;
+ if ( vec->max_boxes > n ) return 0;
+
+ n = (n/32)*32 + 32;
+ t = realloc(vec->boxes, n*sizeof(struct wrap_box *));
+ if ( t == NULL ) return 1;
+
+ vec->boxes = t;
+ return 0;
+}
+
+
+int bv_add(struct boxvec *vec, struct wrap_box *bx)
+{
+ if ( vec == NULL ) return 1;
+ if ( bv_ensure_space(vec, vec->n_boxes+1) ) return 1;
+ vec->boxes[vec->n_boxes++] = bx;
+ return 0;
+}
+
+
+struct wrap_box *bv_box(struct boxvec *vec, int i)
+{
+ assert(vec != NULL);
+ if ( i >= vec->n_boxes ) return NULL;
+ return vec->boxes[i];
+}
+
+
+struct wrap_box *bv_last(struct boxvec *vec)
+{
+ return vec->boxes[vec->n_boxes-1];
+}
+
+
+void bv_free(struct boxvec *vec)
+{
+ if ( vec == NULL ) return;
+ free(vec->boxes);
+ free(vec);
+}
+
diff --git a/src/boxvec.h b/src/boxvec.h
new file mode 100644
index 0000000..e830837
--- /dev/null
+++ b/src/boxvec.h
@@ -0,0 +1,63 @@
+/*
+ * boxvec.h
+ *
+ * Copyright © 2016 Thomas White <taw@bitwiz.org.uk>
+ *
+ * This file is part of Colloquium.
+ *
+ * Colloquium is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef BOXVEC_H
+#define BOXVEC_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+
+/* A vector of boxes */
+struct boxvec
+{
+ int n_boxes;
+ int max_boxes;
+ struct wrap_box **boxes;
+};
+
+
+/* Length of a boxvec */
+extern int bv_len(struct boxvec *vec);
+
+/* Create a bxvec or boxvec */
+extern struct boxvec *bv_new(void);
+
+/* Ensure space in a bxvec or boxvec */
+extern int bv_ensure_space(struct boxvec *vec, int n);
+
+/* Add to a bxvec or boxvec */
+extern int bv_add(struct boxvec *vec, struct wrap_box *bx);
+
+/* Get a box from a boxvec or bxvec */
+extern struct wrap_box *bv_box(struct boxvec *vec, int i);
+extern struct wrap_box *bv_last(struct boxvec *vec);
+
+/* Free a bxvec or boxvec */
+extern void bv_free(struct boxvec *vec);
+
+#endif /* BOXVEC_H */
diff --git a/src/frame.c b/src/frame.c
index 5b16f32..c1dfd39 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -32,6 +32,7 @@
#include "sc_parse.h"
#include "frame.h"
#include "wrap.h"
+#include "boxvec.h"
static int alloc_ro(struct frame *fr)
@@ -66,13 +67,7 @@ struct frame *frame_new()
n->scblocks = NULL;
- n->boxes = malloc(sizeof(struct wrap_line));
- if ( n->boxes == NULL ) {
- fprintf(stderr, "Failed to allocate boxes.\n");
- free(n);
- return NULL;
- }
- initialise_line(n->boxes);
+ n->boxes = bv_new();
return n;
}
diff --git a/src/frame.h b/src/frame.h
index f22f5f8..11ad36b 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -55,17 +55,17 @@ struct frame
int max_children;
SCBlock *scblocks;
- struct wrap_line *boxes; /* The unwrapped boxes */
+ struct boxvec *boxes; /* The unwrapped boxes */
int visited;
+ int n_paragraphs;
+ struct boxvec **paragraphs;
+ int *paragraph_start_lines;
+
int n_lines;
int max_lines;
struct wrap_line *lines;
- int n_paragraphs;
- struct wrap_line **paragraphs;
- int *paragraph_start_lines;
-
/* The rectangle allocated to this frame, determined by the renderer */
double x;
double y;
diff --git a/src/render.c b/src/render.c
index cdf3b0a..1d5656b 100644
--- a/src/render.c
+++ b/src/render.c
@@ -1,7 +1,7 @@
/*
* render.c
*
- * Copyright © 2013-2015 Thomas White <taw@bitwiz.org.uk>
+ * Copyright © 2013-2016 Thomas White <taw@bitwiz.org.uk>
*
* This file is part of Colloquium.
*
@@ -42,6 +42,7 @@
#include "render.h"
#include "wrap.h"
#include "imagestore.h"
+#include "boxvec.h"
static void render_glyph_box(cairo_t *cr, struct wrap_box *box)
@@ -197,18 +198,18 @@ static void render_boxes(struct wrap_line *line, cairo_t *cr, ImageStore *is,
int j;
double x_pos = 0.0;
- for ( j=0; j<line->n_boxes; j++ ) {
+ for ( j=0; j<bv_len(line->boxes); j++ ) {
struct wrap_box *box;
cairo_save(cr);
- box = &line->boxes[j];
+ box = bv_box(line->boxes, j);
cairo_translate(cr, x_pos, 0.0);
//draw_outline(cr, box);
- switch ( line->boxes[j].type ) {
+ switch ( box->type ) {
case WRAP_BOX_PANGO :
render_glyph_box(cr, box);
@@ -231,8 +232,8 @@ static void render_boxes(struct wrap_line *line, cairo_t *cr, ImageStore *is,
}
- x_pos += pango_units_to_double(line->boxes[j].width);
- x_pos += pango_units_to_double(line->boxes[j].sp);
+ x_pos += pango_units_to_double(box->width);
+ x_pos += pango_units_to_double(box->sp);
cairo_restore(cr);
diff --git a/src/sc_editor.c b/src/sc_editor.c
index 48235c2..e5946ed 100644
--- a/src/sc_editor.c
+++ b/src/sc_editor.c
@@ -1,7 +1,7 @@
/*
* sc_editor.c
*
- * Copyright © 2013-2015 Thomas White <taw@bitwiz.org.uk>
+ * Copyright © 2013-2016 Thomas White <taw@bitwiz.org.uk>
*
* This file is part of Colloquium.
*
@@ -44,6 +44,7 @@
#include "sc_editor.h"
#include "slideshow.h"
#include "shape.h"
+#include "boxvec.h"
static void scroll_interface_init(GtkScrollable *iface)
@@ -364,7 +365,7 @@ static void move_cursor_back(SCEditor *e)
cl = e->cursor_line;
line = &e->cursor_frame->lines[e->cursor_line];
- box = &line->boxes[e->cursor_box];
+ box = bv_box(line->boxes, e->cursor_box);
if ( box->type == WRAP_BOX_PANGO ) {
if ( cp == 0 ) {
@@ -389,13 +390,13 @@ static void move_cursor_back(SCEditor *e)
if ( cl < 0 ) return;
e->cursor_line = cl;
line = &e->cursor_frame->lines[cl];
- cb = line->n_boxes - 1;
+ cb = bv_len(line->boxes) - 1;
}
- } while ( !line->boxes[cb].editable );
+ } while ( !bv_box(line->boxes, cb)->editable );
e->cursor_box = cb;
- box = &line->boxes[cb];
+ box = bv_box(line->boxes, cb);
if ( box->type == WRAP_BOX_PANGO ) {
cp = box->len_chars;
if ( box->space == WRAP_SPACE_NONE ) {
@@ -420,11 +421,10 @@ void cur_box_diag(SCEditor *e)
sbx = e->cursor_box;
sps = e->cursor_pos;
- struct wrap_box *sbox = &fr->lines[sln].boxes[sbx];
+ struct wrap_box *sbox = bv_box(fr->lines[sln].boxes, sbx);
printf("line/box/pos: [%i of %i]/[%i of %i]/[%i of %i]\n",
- sln, fr->n_lines,
- sbx, e->cursor_frame->lines[sln].n_boxes,
+ sln, fr->n_lines, sbx, bv_len(e->cursor_frame->lines[sln].boxes),
sps, sbox->len_chars);
printf("box type is %i, space type is %i\n", sbox->type, sbox->space);
if ( sbox->type == WRAP_BOX_NOTHING ) {
@@ -433,10 +433,10 @@ void cur_box_diag(SCEditor *e)
struct wrap_line *ln = &fr->lines[sln];
int i;
- for ( i=0; i<ln->n_boxes; i++ ) {
+ for ( i=0; i<bv_len(ln->boxes); i++ ) {
char pp = '[';
char pq = ']';
- struct wrap_box *bx = &ln->boxes[i];
+ struct wrap_box *bx = bv_box(ln->boxes, i);
if ( i == sbx ) { pp = '<'; pq = '>'; }
printf("%c%i %i %i%c", pp, bx->offs_char, bx->len_chars,
bx->n_segs, pq);
@@ -450,7 +450,7 @@ void advance_cursor(SCEditor *e)
int advance = 0;
signed int cp, cb, cl;
struct wrap_line *line = &e->cursor_frame->lines[e->cursor_line];
- struct wrap_box *box = &line->boxes[e->cursor_box];
+ struct wrap_box *box = bv_box(line->boxes, e->cursor_box);
cp = e->cursor_pos;
cb = e->cursor_box;
@@ -493,7 +493,7 @@ void advance_cursor(SCEditor *e)
cp = 1;
}
- if ( cb >= line->n_boxes ) {
+ if ( cb >= bv_len(line->boxes) ) {
cl++;
if ( cl >= e->cursor_frame->n_lines ) {
/* Give up - could not move */
@@ -504,7 +504,7 @@ void advance_cursor(SCEditor *e)
cp = 0;
}
- } while ( !line->boxes[cb].editable );
+ } while ( !bv_box(line->boxes, cb)->editable );
e->cursor_line = cl;
e->cursor_box = cb;
@@ -564,7 +564,7 @@ static void draw_caret(cairo_t *cr, struct frame *fr,
if ( fr->n_lines == 0 ) return;
/* Locate the cursor in a "logical" and "geographical" sense */
- box = &fr->lines[cursor_line].boxes[cursor_box];
+ box = bv_box(fr->lines[cursor_line].boxes, cursor_box);
get_cursor_pos(box, cursor_pos, &xposd, &yposd, &line_height);
xposd += fr->pad_l;
yposd += fr->pad_t;
@@ -574,8 +574,8 @@ static void draw_caret(cairo_t *cr, struct frame *fr,
}
for ( i=0; i<cursor_box; i++ ) {
- int w = fr->lines[cursor_line].boxes[i].width;
- w += fr->lines[cursor_line].boxes[i].sp;
+ int w = bv_box(fr->lines[cursor_line].boxes, i)->width;
+ w += bv_box(fr->lines[cursor_line].boxes, i)->sp;
xposd += pango_units_to_double(w);
}
@@ -717,12 +717,12 @@ static void fixup_cursor(SCEditor *e)
if ( e->cursor_line >= fr->n_lines ) {
/* We find ourselves on a line which doesn't exist */
e->cursor_line = fr->n_lines-1;
- e->cursor_box = fr->lines[fr->n_lines-1].n_boxes-1;
+ e->cursor_box = bv_len(fr->lines[fr->n_lines-1].boxes)-1;
}
sline = &fr->lines[e->cursor_line];
- if ( e->cursor_box >= sline->n_boxes ) {
+ if ( e->cursor_box >= bv_len(sline->boxes) ) {
/* We find ourselves in a box which doesn't exist */
@@ -736,12 +736,12 @@ static void fixup_cursor(SCEditor *e)
/* There are no more lines, so just go to the end */
e->cursor_line = fr->n_lines-1;
sline = &e->cursor_frame->lines[e->cursor_line];
- e->cursor_box = sline->n_boxes-1;
+ e->cursor_box = bv_len(sline->boxes)-1;
}
}
- assert(e->cursor_box < sline->n_boxes);
- sbox = &sline->boxes[e->cursor_box];
+ assert(e->cursor_box < bv_len(sline->boxes));
+ sbox = bv_box(sline->boxes, e->cursor_box);
if ( e->cursor_pos > sbox->len_chars ) {
advance_cursor(e);
@@ -773,7 +773,7 @@ void insert_scblock(SCBlock *scblock, SCEditor *e)
sln = e->cursor_line;
sbx = e->cursor_box;
sps = e->cursor_pos;
- sbox = &e->cursor_frame->lines[sln].boxes[sbx];
+ sbox = bv_box(e->cursor_frame->lines[sln].boxes, sbx);
sc_insert_block(sbox->scblock, sps+sbox->offs_char, scblock);
@@ -791,17 +791,11 @@ void insert_scblock(SCBlock *scblock, SCEditor *e)
* Update the boxes from the StoryCode */
static void update_local(SCEditor *e, struct frame *fr, int line, int bn)
{
- struct wrap_box *box = &fr->lines[line].boxes[bn];
+ struct wrap_box *box = bv_box(fr->lines[line].boxes, bn);
/* Shape the box again
* FIXME: Number of segments could change, need to PangoAnalyse again */
- shape_box(box->cf->cf);
-
- /* Update the segments */
- box->segs = box->cf->cf->segs;
- box->n_segs = box->cf->cf->n_segs;
- box->cf->segs = box->cf->cf->segs;
- box->cf->n_segs = box->cf->cf->n_segs;
+ shape_box(box);
/* Wrap the paragraph again */
wrap_contents(fr); /* FIXME: Only the current paragraph */
@@ -817,7 +811,7 @@ static void shift_box_offsets(struct frame *fr, struct wrap_box *box, int n)
int sn = 0;
for ( i=0; i<fr->boxes->n_boxes; i++ ) {
- if ( &fr->boxes->boxes[i] == box ) {
+ if ( bv_box(fr->boxes, i) == box ) {
sn = i+1;
break;
}
@@ -826,7 +820,7 @@ static void shift_box_offsets(struct frame *fr, struct wrap_box *box, int n)
assert(sn > 0); /* Lowest it can possibly be is 1 */
for ( i=sn; i<fr->boxes->n_boxes; i++ ) {
- fr->boxes->boxes[i].offs_char += n;
+ bv_box(fr->boxes, i)->offs_char += n;
}
}
@@ -851,10 +845,10 @@ static void insert_text(char *t, SCEditor *e)
sln = e->cursor_line;
sbx = e->cursor_box;
sps = e->cursor_pos;
- sbox = &e->cursor_frame->lines[sln].boxes[sbx];
+ sbox = bv_box(e->cursor_frame->lines[sln].boxes, sbx);
if ( sbox->type == WRAP_BOX_NOTHING ) {
- printf("Upgrading nothing box to Pango box\n");
+ printf("Upgrading nothing box %p to Pango box\n", sbox);
sbox->type = WRAP_BOX_PANGO;
sbox->col[0] = 0.0;
sbox->col[1] = 0.0;
@@ -899,7 +893,7 @@ static void insert_text(char *t, SCEditor *e)
/* Add a new box containing the text after the break */
insert_box(&e->cursor_frame->lines[sln], sbx);
- nbox = &e->cursor_frame->lines[sln].boxes[sbx];
+ nbox = bv_box(e->cursor_frame->lines[sln].boxes, sbx);
nbox->type = WRAP_BOX_PANGO;
nbox->space = WRAP_SPACE_INTERWORD;
nbox->len_chars = e->cursor_pos;
@@ -916,15 +910,8 @@ static void insert_text(char *t, SCEditor *e)
sbox->segs[sseg].len_chars += 1;
- /* Update the length of the box in the unwrapped and un-paragraph-split
- * string of wrap boxes */
- sbox->cf->cf->len_chars += 1;
-
- /* ... and also in the paragraph split but unwrapped box */
- sbox->cf->len_chars += 1;
-
/* Tweak the offsets of all the subsequent boxes */
- shift_box_offsets(fr, sbox->cf->cf, 1);
+ shift_box_offsets(fr, sbox, 1);
fr->empty = 0;
@@ -949,7 +936,7 @@ static void do_backspace(struct frame *fr, SCEditor *e)
sln = e->cursor_line;
sbx = e->cursor_box;
sps = e->cursor_pos;
- struct wrap_box *sbox = &e->cursor_frame->lines[sln].boxes[sbx];
+ struct wrap_box *sbox = bv_box(e->cursor_frame->lines[sln].boxes, sbx);
cur_box_diag(e);
@@ -957,7 +944,7 @@ static void do_backspace(struct frame *fr, SCEditor *e)
/* Delete may cross wrap boxes and maybe SCBlock boundaries */
struct wrap_line *fline = &e->cursor_frame->lines[e->cursor_line];
- struct wrap_box *fbox = &fline->boxes[e->cursor_box];
+ struct wrap_box *fbox = bv_box(fline->boxes, e->cursor_box);
// SCBlock *scbl = sbox->scblock;
// do {
@@ -975,15 +962,8 @@ static void do_backspace(struct frame *fr, SCEditor *e)
// scbl = sc_block_next(scbl);
// } while ( (scbl != fbox->scblock) && (scbl != NULL) );
- /* Update the length of the box in the unwrapped and un-paragraph-split
- * string of wrap boxes */
- sbox->cf->cf->len_chars -= 1;
-
- /* ... and also in the paragraph split but unwrapped box */
- sbox->cf->len_chars -= 1;
-
/* Tweak the offsets of all the subsequent boxes */
- shift_box_offsets(fr, sbox->cf->cf, -1);
+ shift_box_offsets(fr, sbox, -1);
update_local(e, fr, sln, sbx);
@@ -1186,7 +1166,7 @@ static void calculate_box_size(struct frame *fr, SCEditor *e,
static struct wrap_box *cbox(struct frame *fr, int ln, int bn)
{
- return &fr->lines[ln].boxes[bn];
+ return bv_box(fr->lines[ln].boxes, bn);;
}
diff --git a/src/shape.c b/src/shape.c
index 3664780..59ec024 100644
--- a/src/shape.c
+++ b/src/shape.c
@@ -33,6 +33,7 @@
#include "wrap.h"
#include "sc_interp.h"
#include "shape.h"
+#include "boxvec.h"
static void shape_segment(struct wrap_box *box, struct text_seg *seg)
@@ -93,19 +94,17 @@ void shape_box(struct wrap_box *box)
}
-static void add_nothing_box(struct wrap_line *line, SCBlock *scblock,
+static void add_nothing_box(struct boxvec *boxes, SCBlock *scblock,
int editable, enum wrap_box_space sp,
SCInterpreter *scin, size_t offs)
{
struct wrap_box *box;
- if ( line->n_boxes == line->max_boxes ) {
- line->max_boxes += 32;
- alloc_boxes(line);
- if ( line->n_boxes == line->max_boxes ) return;
+ box = calloc(1, sizeof(struct wrap_box));
+ if ( box == NULL ) {
+ fprintf(stderr, "Failed to allocate a nothing box.\n");
+ return;
}
-
- box = &line->boxes[line->n_boxes];
box->type = WRAP_BOX_NOTHING;
box->scblock = scblock;
box->offs_char = offs;
@@ -118,7 +117,7 @@ static void add_nothing_box(struct wrap_line *line, SCBlock *scblock,
box->editable = editable;
box->segs = NULL;
box->n_segs = 0;
- line->n_boxes++;
+ bv_add(boxes, box);
}
@@ -185,7 +184,7 @@ static void add_seg(gpointer vi, gpointer vb)
/* Add "text", followed by a space of type "space", to "line" */
-static int add_text_box(struct wrap_line *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)
@@ -199,17 +198,16 @@ static int add_text_box(struct wrap_line *line,
int nseg;
while ( len==0 ) {
- add_nothing_box(line, bl, editable, space, scin, offs);
+ add_nothing_box(boxes, bl, editable, space, scin, offs);
return 0;
}
/* Create the box */
- if ( line->n_boxes == line->max_boxes ) {
- line->max_boxes += 32;
- alloc_boxes(line);
- if ( line->n_boxes == line->max_boxes ) return 1;
+ box = calloc(1, sizeof(struct wrap_box));
+ if ( box == NULL ) {
+ fprintf(stderr, "Failed to allocate a text box.\n");
+ return 1;
}
- box = &line->boxes[line->n_boxes];
box->type = WRAP_BOX_PANGO;
box->space = space;
@@ -218,7 +216,6 @@ static int add_text_box(struct wrap_line *line,
box->editable = editable;
box->ascent = sc_interp_get_ascent(scin);
box->height = sc_interp_get_height(scin);
- box->cf = NULL;
/* Link to the actual text */
box->scblock = bl;
@@ -248,24 +245,23 @@ static int add_text_box(struct wrap_line *line,
calc_box_geometry(box);
- line->n_boxes++;
+ bv_add(boxes, box);
return 0;
}
-void add_callback_box(struct wrap_line *line, double w, double h,
+void add_callback_box(struct boxvec *boxes, double w, double h,
SCCallbackDrawFunc draw_func,
SCCallbackClickFunc click_func, void *bvp, void *vp)
{
struct wrap_box *box;
- if ( line->n_boxes == line->max_boxes ) {
- line->max_boxes += 32;
- alloc_boxes(line);
- if ( line->n_boxes == line->max_boxes ) return;
+ box = calloc(1, sizeof(struct wrap_box));
+ if ( box == NULL ) {
+ fprintf(stderr, "Failed to allocate a callback box.\n");
+ return;
}
- box = &line->boxes[line->n_boxes];
box->type = WRAP_BOX_CALLBACK;
box->scblock = NULL;
@@ -279,22 +275,21 @@ void add_callback_box(struct wrap_line *line, double w, double h,
box->bvp = bvp;
box->vp = vp;
box->editable = 0;
- line->n_boxes++;
+ bv_add(boxes, box);
}
-void add_image_box(struct wrap_line *line, const char *filename,
+void add_image_box(struct boxvec *boxes, const char *filename,
int w, int h, int editable)
{
struct wrap_box *box;
- if ( line->n_boxes == line->max_boxes ) {
- line->max_boxes += 32;
- alloc_boxes(line);
- if ( line->n_boxes == line->max_boxes ) return;
+ box = calloc(1, sizeof(struct wrap_box));
+ if ( box == NULL ) {
+ fprintf(stderr, "Failed to allocate a callback box.\n");
+ return;
}
- box = &line->boxes[line->n_boxes];
box->type = WRAP_BOX_IMAGE;
box->scblock = NULL;
box->offs_char = 0;
@@ -304,11 +299,11 @@ void add_image_box(struct wrap_line *line, const char *filename,
box->height = pango_units_from_double(h);
box->filename = strdup(filename);
box->editable = editable;
- line->n_boxes++;
+ bv_add(boxes, box);
}
-int split_words(struct wrap_line *boxes, PangoContext *pc, SCBlock *bl,
+int split_words(struct boxvec *boxes, PangoContext *pc, SCBlock *bl,
PangoLanguage *lang, int editable, SCInterpreter *scin)
{
PangoLogAttr *log_attrs;
diff --git a/src/shape.h b/src/shape.h
index b9a5191..43775a3 100644
--- a/src/shape.h
+++ b/src/shape.h
@@ -33,14 +33,14 @@
extern void shape_box(struct wrap_box *box);
-extern int split_words(struct wrap_line *boxes, PangoContext *pc,
+extern int split_words(struct boxvec *boxes, PangoContext *pc,
SCBlock *bl, PangoLanguage *lang,
int editable, SCInterpreter *scin);
-extern void add_image_box(struct wrap_line *line, const char *filename,
+extern void add_image_box(struct boxvec *line, const char *filename,
int w, int h, int editable);
-extern void add_callback_box(struct wrap_line *line, double w, double h,
+extern void add_callback_box(struct boxvec *boxes, double w, double h,
SCCallbackDrawFunc draw_func,
SCCallbackClickFunc click_func,
void *bvp, void *vp);
diff --git a/src/wrap.c b/src/wrap.c
index fa383b3..9fc233f 100644
--- a/src/wrap.c
+++ b/src/wrap.c
@@ -3,7 +3,7 @@
*
* Text wrapping, hyphenation, justification etc
*
- * Copyright © 2013-2015 Thomas White <taw@bitwiz.org.uk>
+ * Copyright © 2013-2016 Thomas White <taw@bitwiz.org.uk>
*
* This file is part of Colloquium.
*
@@ -39,6 +39,7 @@
#include "wrap.h"
#include "frame.h"
#include "presentation.h"
+#include "boxvec.h"
static void alloc_lines(struct frame *fr)
@@ -55,32 +56,14 @@ static void alloc_lines(struct frame *fr)
}
-int alloc_boxes(struct wrap_line *l)
-{
- struct wrap_box *boxes_new;
-
- boxes_new = realloc(l->boxes, l->max_boxes * sizeof(struct wrap_box));
- if ( boxes_new == NULL ) {
- fprintf(stderr, "Couldn't allocate memory for boxes!\n");
- return 1;
- }
-
- l->boxes = boxes_new;
- return 0;
-}
-
-
void initialise_line(struct wrap_line *l)
{
- l->n_boxes = 0;
- l->max_boxes = 32;
- l->boxes = NULL;
l->width = 0;
l->height = 0;
l->ascent = 0;
l->last_line = 0;
l->overfull = 0;
- alloc_boxes(l);
+ l->boxes = bv_new();
}
@@ -255,9 +238,9 @@ static int find_cursor_box(struct frame *fr, struct wrap_line *l,
*end = 0;
- for ( i=0; i<l->n_boxes; i++ ) {
- double width = pango_units_to_double(l->boxes[i].width);
- width += pango_units_to_double(l->boxes[i].sp);
+ for ( i=0; i<l->boxes->n_boxes; i++ ) {
+ double width = pango_units_to_double(bv_box(l->boxes, i)->width);
+ width += pango_units_to_double(bv_box(l->boxes, i)->sp);
if ( xposd < x + width ) {
*x_pos = xposd - x;
return i;
@@ -267,7 +250,7 @@ static int find_cursor_box(struct frame *fr, struct wrap_line *l,
*end = 1;
*x_pos = x;
- return l->n_boxes-1;
+ return bv_len(l->boxes)-1;
}
@@ -297,11 +280,11 @@ void find_cursor(struct frame *fr, double xposd, double yposd,
*line = ln;
if ( end ) {
- bn = l->n_boxes-1;
+ bn = l->boxes->n_boxes-1;
} else {
bn = find_cursor_box(fr, l, xposd, &x_pos, &end);
}
- b = &l->boxes[bn];
+ b = bv_box(l->boxes, bn);
*box = bn;
if ( end ) {
*pos = b->len_chars;
@@ -363,9 +346,9 @@ static void calc_line_geometry(struct wrap_line *line)
line->ascent = 0;
line->height = 0;
- for ( i=0; i<line->n_boxes; i++ ) {
+ for ( i=0; i<line->boxes->n_boxes; i++ ) {
- struct wrap_box *box = &line->boxes[i];
+ struct wrap_box *box = bv_box(line->boxes, i);
line->width += box->width;
if ( box->space == WRAP_SPACE_EOP ) box->sp = 0.0;
@@ -476,19 +459,19 @@ static void consider_break(double sigma_prime, double sigma_prime_max,
}
-static double width(struct wrap_line *boxes, int i)
+static double width(struct boxvec *boxes, int i)
{
/* Indices in Knuth paper go from 1...n. Indices in array go
* from 0...n-1 */
- return boxes->boxes[i-1].width;
+ return bv_box(boxes, i-1)->width;
}
-static enum wrap_box_space space(struct wrap_line *boxes, int i)
+static enum wrap_box_space space(struct boxvec *boxes, int i)
{
/* Indices in Knuth paper go from 1...n. Indices in array go
* from 0...n-1 */
- return boxes->boxes[i-1].space;
+ return bv_box(boxes, i-1)->space;
}
@@ -503,13 +486,13 @@ static void UNUSED distribute_spaces(struct wrap_line *line, double l,
l = pango_units_from_double(l);
L = 0.0; Y = 0.0; Z = 0.0;
- for ( i=0; i<line->n_boxes-1; i++ ) {
- L += line->boxes[i].width;
- L += sp_x(line->boxes[i].space);
- Y += sp_y(line->boxes[i].space);
- Z += sp_z(line->boxes[i].space);
+ for ( i=0; i<bv_len(line->boxes); i++ ) {
+ L += bv_box(line->boxes, i)->width;
+ L += sp_x(bv_box(line->boxes, i)->space);
+ Y += sp_y(bv_box(line->boxes, i)->space);
+ Z += sp_z(bv_box(line->boxes, i)->space);
}
- L += line->boxes[line->n_boxes-1].width;
+ L += bv_last(line->boxes)->width;
if ( L < l ) {
r = (l - L)/Y;
@@ -520,24 +503,24 @@ static void UNUSED distribute_spaces(struct wrap_line *line, double l,
}
if ( r >= 0.0 ) {
- for ( i=0; i<line->n_boxes-1; i++ ) {
- line->boxes[i].sp = sp_x(line->boxes[i].space);
- line->boxes[i].sp += r*sp_y(line->boxes[i].space);
+ for ( i=0; i<bv_len(line->boxes)-1; i++ ) {
+ bv_box(line->boxes, i)->sp = sp_x(bv_box(line->boxes, i)->space);
+ bv_box(line->boxes, i)->sp += r*sp_y(bv_box(line->boxes, i)->space);
}
} else {
- for ( i=0; i<line->n_boxes-1; i++ ) {
- line->boxes[i].sp = sp_x(line->boxes[i].space);
- line->boxes[i].sp += r*sp_z(line->boxes[i].space);
+ for ( i=0; bv_len(line->boxes)-1; i++ ) {
+ bv_box(line->boxes, i)->sp = sp_x(bv_box(line->boxes, i)->space);
+ bv_box(line->boxes, i)->sp += r*sp_z(bv_box(line->boxes, i)->space);
}
}
- line->boxes[line->n_boxes-1].sp = 0.0;
+ bv_box(line->boxes, bv_len(line->boxes)-1)->sp = 0.0;
line->overfull = overfull;
line->underfull = underfull;
}
-static void output_line(int q, int s, struct frame *fr, struct wrap_line *boxes)
+static void output_line(int q, int s, struct frame *fr, struct boxvec *boxes)
{
struct wrap_line *l;
int j;
@@ -546,16 +529,14 @@ static void output_line(int q, int s, struct frame *fr, struct wrap_line *boxes)
fr->n_lines++;
initialise_line(l);
- l->max_boxes = s-q;
- alloc_boxes(l);
+ bv_ensure_space(l->boxes, s-q);
for ( j=q; j<s; j++ ) {
- l->boxes[l->n_boxes++] = boxes->boxes[j];
+ bv_add(l->boxes, bv_box(boxes, j));
}
}
-static void output(int a, int i, int *p, struct frame *fr,
- struct wrap_line *boxes)
+static void output(int a, int i, int *p, struct frame *fr, struct boxvec *boxes)
{
int q = i;
int r;
@@ -590,7 +571,7 @@ static void output(int a, int i, int *p, struct frame *fr,
* Practice and Experience 11 (1981) p1119-1184. Despite the name, it's
* supposed to work as well as the full TeX algorithm in almost all of the cases
* that we care about here. */
-static void UNUSED knuth_suboptimal_fit(struct wrap_line *boxes,
+static void UNUSED knuth_suboptimal_fit(struct boxvec *boxes,
double line_length, struct frame *fr,
double rho)
{
@@ -607,15 +588,14 @@ static void UNUSED knuth_suboptimal_fit(struct wrap_line *boxes,
n = boxes->n_boxes;
/* Set the space for the last box to be "end of paragraph" */
- boxes->boxes[boxes->n_boxes-1].space = WRAP_SPACE_EOP;
+ bv_last(boxes)->space = WRAP_SPACE_EOP;
/* Add empty zero-width box at end */
- if ( boxes->n_boxes == boxes->max_boxes ) {
- boxes->max_boxes += 32;
- alloc_boxes(boxes);
- if ( boxes->n_boxes == boxes->max_boxes ) return;
+ box = malloc(sizeof(struct wrap_box));
+ if ( box== NULL ) {
+ fprintf(stderr, "Couldn't allocate sentinel box\n");
+ return;
}
- box = &boxes->boxes[boxes->n_boxes];
box->type = WRAP_BOX_SENTINEL;
box->space = WRAP_SPACE_NONE;
box->font = NULL;
@@ -625,15 +605,15 @@ static void UNUSED knuth_suboptimal_fit(struct wrap_line *boxes,
box->editable = 1;
box->scblock = NULL;
box->offs_char = 0;
- boxes->n_boxes++;
+ bv_add(boxes, box);
line_length *= PANGO_SCALE;
reject = 0;
- for ( j=0; j<boxes->n_boxes; j++ ) {
- if ( boxes->boxes[j].width > line_length ) {
+ for ( j=0; j<bv_len(boxes); j++ ) {
+ if ( bv_box(boxes, j)->width > line_length ) {
fprintf(stderr, "ERROR: Box %i too long (%i %f)\n", j,
- boxes->boxes[j].width, line_length);
+ bv_box(boxes, j)->width, line_length);
fr->trouble = 1;
reject = 1;
}
@@ -772,6 +752,7 @@ static void UNUSED knuth_suboptimal_fit(struct wrap_line *boxes,
free(p);
free(s);
+ free(box); /* The sentinel box */
}
@@ -792,16 +773,7 @@ static struct wrap_line *new_line(struct frame *fr)
}
-static int maybe_extend_line(struct wrap_line *l)
-{
- if ( l->n_boxes < l->max_boxes ) return 0;
-
- l->max_boxes += 32;
- return alloc_boxes(l);
-}
-
-
-static void first_fit(struct wrap_line *boxes, double line_length,
+static void first_fit(struct boxvec *boxes, double line_length,
struct frame *fr)
{
struct wrap_line *line;
@@ -815,23 +787,20 @@ static void first_fit(struct wrap_line *boxes, double line_length,
do {
- boxes->boxes[j].sp = sp_x(boxes->boxes[j].space);
+ bv_box(boxes, j)->sp = sp_x(bv_box(boxes, j)->space);
- len += boxes->boxes[j].width;
+ len += bv_box(boxes, j)->width;
if ( len > line_length ) {
line = new_line(fr);
- len = boxes->boxes[j].width;
+ len = bv_box(boxes, j)->width;
}
- line->boxes[line->n_boxes] = boxes->boxes[j];
- line->boxes[line->n_boxes].cf = &boxes->boxes[j];
- line->n_boxes++;
- if ( maybe_extend_line(line) ) return;
+ bv_add(line->boxes, bv_box(boxes, j));
j++;
- if ( (j > 0) && (boxes->boxes[j-1].type != WRAP_BOX_SENTINEL) )
+ if ( (j > 0) && (bv_box(boxes, j-1)->type != WRAP_BOX_SENTINEL) )
{
- len += sp_x(boxes->boxes[j-1].space);
+ len += sp_x(bv_box(boxes, j-1)->space);
}
} while ( j < boxes->n_boxes );
@@ -842,66 +811,35 @@ static void first_fit(struct wrap_line *boxes, double line_length,
void wrap_line_free(struct wrap_line *l)
{
- int i, j;
- for ( i=0; i<l->n_boxes; i++ ) {
-
- switch ( l->boxes[i].type ) {
-
- case WRAP_BOX_PANGO :
- for ( j=0; j<l->boxes[i].n_segs; j++ ) {
- pango_glyph_string_free(l->boxes[i].segs[j].glyphs);
- }
- free(l->boxes[i].segs);
- break;
-
- case WRAP_BOX_IMAGE :
- break;
-
- case WRAP_BOX_CALLBACK :
- break;
-
- case WRAP_BOX_NOTHING :
- case WRAP_BOX_SENTINEL :
- break;
-
- }
-
- }
-
+ bv_free(l->boxes);
free(l->boxes);
}
-static struct wrap_line *split_paragraph(struct wrap_line *boxes, int *n,
- int *eop)
+static struct boxvec *split_paragraph(struct boxvec *boxes, int *n, int *eop)
{
int i;
int start = *n;
int end;
- if ( start >= boxes->n_boxes ) return NULL;
+ if ( start >= bv_len(boxes) ) return NULL;
*eop = 0;
- for ( i=start; i<boxes->n_boxes; i++ ) {
- if ( boxes->boxes[i].space == WRAP_SPACE_EOP ) {
+ for ( i=start; i<bv_len(boxes); i++ ) {
+ if ( bv_box(boxes, i)->space == WRAP_SPACE_EOP ) {
*eop = 1;
break;
}
}
end = i + 1;
*n = end;
- if ( i == boxes->n_boxes ) end--;
+ if ( i == bv_len(boxes) ) end--;
if ( end-start > 0 ) {
- struct wrap_line *para;
- para = malloc(sizeof(struct wrap_line));
- para->boxes = NULL;
- para->max_boxes = end-start;
- para->n_boxes = end-start;
- alloc_boxes(para);
+ struct boxvec *para = bv_new();
+ bv_ensure_space(para, end-start);
for ( i=start; i<end; i++ ) {
- para->boxes[i-start] = boxes->boxes[i];
- para->boxes[i-start].cf = &boxes->boxes[i];
+ bv_add(para, bv_box(boxes, i));
}
return para;
}
@@ -910,7 +848,7 @@ static struct wrap_line *split_paragraph(struct wrap_line *boxes, int *n,
}
-void show_boxes(struct wrap_line *boxes)
+void show_boxes(struct boxvec *boxes)
{
int i;
@@ -919,8 +857,8 @@ void show_boxes(struct wrap_line *boxes)
return;
}
- for ( i=0; i<boxes->n_boxes; i++ ) {
- struct wrap_box *box = &boxes->boxes[i];
+ for ( i=0; i<bv_len(boxes); i++ ) {
+ struct wrap_box *box = bv_box(boxes, i);
char *box_text;
printf("%3i", i);
if ( box->scblock != NULL ) {
@@ -971,7 +909,7 @@ static int wrap_everything(struct frame *fr, double wrap_w)
* and generate fr->lines */
int wrap_contents(struct frame *fr)
{
- struct wrap_line *para;
+ struct boxvec *para;
int i, eop = 0;
//const double rho = 2.0;
const double wrap_w = fr->w - fr->pad_l - fr->pad_r;
@@ -1016,54 +954,6 @@ int wrap_contents(struct frame *fr)
return 0;
}
- /* If the last paragraph ended with an EOP, add an extra line */
- if ( eop || (fr->n_lines == 0) ) {
-
- struct wrap_line *l;
- struct wrap_box *last_box;
-
- if ( fr->n_lines > 0 ) {
- l = &fr->lines[fr->n_lines-1];
- last_box = &l->boxes[l->n_boxes-1];
- } else {
- last_box = NULL;
- }
-
- if ( fr->n_lines + 1 > fr->max_lines ) {
- fr->max_lines += 32;
- alloc_lines(fr);
- if ( fr->n_lines == fr->max_lines ) return 1;
- }
-
- l = &fr->lines[fr->n_lines];
- fr->n_lines++;
- initialise_line(l);
-
- l->max_boxes = 1;
- alloc_boxes(l);
- l->n_boxes = 1;
- l->boxes[0].type = WRAP_BOX_NOTHING;
- l->boxes[0].editable = 1;
- l->boxes[0].space = WRAP_SPACE_NONE;
-
- if ( last_box != NULL ) {
- l->boxes[0].scblock = last_box->scblock;
- l->boxes[0].offs_char = last_box->len_chars
- + last_box->offs_char;
- l->boxes[0].ascent = last_box->ascent;
- l->boxes[0].height = last_box->height;
- l->boxes[0].width = 0;
- /* FIXME: Get ascent and descent from font metrics for
- * whichever font will be used in this box */
- } else {
- l->boxes[0].scblock = find_last_child(fr->scblocks);
- l->boxes[0].offs_char = 0;
- l->boxes[0].ascent = 10000;
- l->boxes[0].height = 10000;
- l->boxes[0].width = 0;
- }
- }
-
for ( i=0; i<fr->n_lines; i++ ) {
struct wrap_line *line = &fr->lines[i];
@@ -1071,8 +961,8 @@ int wrap_contents(struct frame *fr)
//distribute_spaces(line, wrap_w, rho);
/* Strip any sentinel boxes added by the wrapping algorithm */
- if ( line->boxes[line->n_boxes-1].type == WRAP_BOX_SENTINEL ) {
- line->n_boxes--;
+ if ( bv_last(line->boxes)->type == WRAP_BOX_SENTINEL ) {
+ line->boxes->n_boxes--;
}
}
@@ -1105,6 +995,8 @@ int insert_box(struct wrap_line *l, int pos)
{
int i;
+/* FIXME ! */
+#if 0
if ( l->n_boxes == l->max_boxes ) {
l->max_boxes += 32;
if ( alloc_boxes(l) ) return 1;
@@ -1116,6 +1008,8 @@ int insert_box(struct wrap_line *l, int pos)
}
l->n_boxes++;
+#endif
+return 1;
return 0;
}
diff --git a/src/wrap.h b/src/wrap.h
index 97dea37..0dcc190 100644
--- a/src/wrap.h
+++ b/src/wrap.h
@@ -3,7 +3,7 @@
*
* Text wrapping, hyphenation, justification and shaping
*
- * Copyright © 2014-2015 Thomas White <taw@bitwiz.org.uk>
+ * Copyright © 2014-2016 Thomas White <taw@bitwiz.org.uk>
*
* This file is part of Colloquium.
*
@@ -81,7 +81,6 @@ struct wrap_box
SCBlock *scblock;
int offs_char; /* offset (in characters, not bytes) into scblock */
- struct wrap_box *cf; /* Copied from */
/* Pango units */
int width;
@@ -109,22 +108,20 @@ struct wrap_box
};
+/* An actual wrap line, with geometry etc */
struct wrap_line
{
+ struct boxvec *boxes;
+
int width; /* Pango units */
int height; /* Pango units */
int ascent; /* Pango units */
- int n_boxes;
- int max_boxes;
- struct wrap_box *boxes;
-
int overfull;
int underfull;
int last_line;
};
-
extern int wrap_contents(struct frame *fr);
extern void get_cursor_pos(struct wrap_box *box, int pos,
@@ -137,7 +134,7 @@ extern int alloc_boxes(struct wrap_line *l);
extern void initialise_line(struct wrap_line *l);
extern void wrap_line_free(struct wrap_line *l);
-extern void show_boxes(struct wrap_line *boxes);
+extern void show_boxes(struct boxvec *boxes);
extern double total_height(struct frame *fr);
extern int insert_box(struct wrap_line *l, int pos);