aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/boxvec.c149
-rw-r--r--src/boxvec.h70
-rw-r--r--src/frame.c227
-rw-r--r--src/frame.h40
-rw-r--r--src/presentation.c1
-rw-r--r--src/render.c251
-rw-r--r--src/render.h5
-rw-r--r--src/sc_editor.c614
-rw-r--r--src/sc_editor.h5
-rw-r--r--src/sc_interp.c63
-rw-r--r--src/sc_interp.h6
-rw-r--r--src/shape.c423
-rw-r--r--src/shape.h50
-rw-r--r--src/slide_window.c1
-rw-r--r--src/wrap.c1032
-rw-r--r--src/wrap.h144
16 files changed, 397 insertions, 2684 deletions
diff --git a/src/boxvec.c b/src/boxvec.c
deleted file mode 100644
index e065a91..0000000
--- a/src/boxvec.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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 <stdio.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 n;
-}
-
-
-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;
-}
-
-
-static int find_box(struct boxvec *vec, struct wrap_box *bx)
-{
- int i = 0;
- while ( (i<vec->n_boxes) && (vec->boxes[i] != bx) ) i++;
- return i;
-}
-
-
-void bv_del(struct boxvec *vec, struct wrap_box *bx)
-{
- int n = find_box(vec, bx);
- if ( n == vec->n_boxes ) {
- fprintf(stderr, "Couldn't find box to delete it!\n");
- return;
- }
- assert(vec->boxes[n] == bx);
- if ( n < vec->n_boxes-1 ) {
- memmove(&vec->boxes[n], &vec->boxes[n+1],
- (vec->n_boxes-n-1)*sizeof(struct wrap_box *));
- }
- vec->n_boxes--;
-}
-
-
-int bv_add_after(struct boxvec *vec, struct wrap_box *bx, struct wrap_box *add)
-{
- int n = find_box(vec, bx);
- if ( n == vec->n_boxes ) {
- fprintf(stderr, "Couldn't find box to add after!\n");
- return 1;
- }
- assert(vec->boxes[n] == bx);
-
- n++;
- bv_ensure_space(vec, vec->n_boxes+1);
-
- if ( n < vec->n_boxes-1 ) {
- memmove(&vec->boxes[n+1], &vec->boxes[n],
- (vec->n_boxes-n)*sizeof(struct wrap_box *));
- } /* otherwise there's nothing to move */
-
- vec->boxes[n] = add;
- vec->n_boxes++;
-
- 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)
-{
- if ( vec == NULL ) return NULL;
- if ( vec->boxes == NULL ) return NULL;
- 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
deleted file mode 100644
index 9538a35..0000000
--- a/src/boxvec.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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);
-
-/* (Find and then) delete a box from a boxvec */
-extern void bv_del(struct boxvec *vec, struct wrap_box *bx);
-
-/* Add a new box after the specified one */
-extern int bv_add_after(struct boxvec *vec, struct wrap_box *bx,
- struct wrap_box *add);
-
-/* 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 7f41a41..c21589f 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1,7 +1,7 @@
/*
* frame.c
*
- * Copyright © 2013 Thomas White <taw@bitwiz.org.uk>
+ * Copyright © 2013-2016 Thomas White <taw@bitwiz.org.uk>
*
* This file is part of Colloquium.
*
@@ -31,8 +31,38 @@
#include "sc_parse.h"
#include "frame.h"
-#include "wrap.h"
-#include "boxvec.h"
+
+
+struct text_run
+{
+ SCBlock *scblock;
+ size_t offs_bytes;
+ size_t len_bytes;
+ PangoFontDescription *fontdesc;
+};
+
+
+struct _paragraph
+{
+ int n_runs;
+ struct text_run *runs;
+ int open;
+
+ PangoLayout *layout;
+ double height;
+};
+
+
+PangoLayout *paragraph_layout(Paragraph *para)
+{
+ return para->layout;
+}
+
+
+double paragraph_height(Paragraph *para)
+{
+ return para->height;
+}
static int alloc_ro(struct frame *fr)
@@ -66,42 +96,38 @@ struct frame *frame_new()
n->num_children = 0;
n->scblocks = NULL;
- n->n_paragraphs = 0;
- n->paragraphs = NULL;
- n->paragraph_start_lines = NULL;
- n->lines = NULL;
- n->n_lines = 0;
-
- n->boxes = bv_new();
+ n->n_paras = 0;
+ n->paras = NULL;
return n;
}
+static void free_paragraph(Paragraph *para)
+{
+ int i;
+
+ for ( i=0; i<para->n_runs; i++ ) {
+ pango_font_description_free(para->runs[i].fontdesc);
+ }
+ free(para->runs);
+ if ( para->layout != NULL ) g_object_unref(para->layout);
+ free(para);
+}
+
+
void frame_free(struct frame *fr)
{
int i;
if ( fr == NULL ) return;
- /* Free all lines */
- for ( i=0; i<fr->n_lines; i++ ) {
- wrap_line_free(&fr->lines[i]);
- }
- free(fr->lines);
-
/* Free paragraphs */
- if ( fr->paragraphs != NULL ) {
- for ( i=0; i<fr->n_paragraphs; i++ ) {
- free(fr->paragraphs[i]->boxes);
- free(fr->paragraphs[i]);
+ if ( fr->paras != NULL ) {
+ for ( i=0; i<fr->n_paras; i++ ) {
+ free_paragraph(fr->paras[i]);
}
- free(fr->paragraphs);
- }
- /* Free unwrapped boxes */
- if ( fr->boxes != NULL ) {
- free(fr->boxes->boxes);
- free(fr->boxes);
+ free(fr->paras);
}
/* Free all children */
@@ -201,6 +227,7 @@ 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;
@@ -215,3 +242,151 @@ struct frame *find_frame_with_scblocks(struct frame *fr, SCBlock *scblocks)
return NULL;
}
+
+
+void wrap_paragraph(Paragraph *para, PangoContext *pc, double w)
+{
+ size_t total_len = 0;
+ int i;
+ char *text;
+ PangoAttrList *attrs;
+ PangoRectangle rect;
+ size_t pos = 0;
+
+ for ( i=0; i<para->n_runs; i++ ) {
+ total_len += para->runs[i].len_bytes;
+ }
+
+ /* Allocate the complete text */
+ text = malloc(total_len+1);
+ if ( text == NULL ) {
+ fprintf(stderr, "Couldn't allocate combined text\n");
+ return;
+ }
+
+ /* Allocate the attributes */
+ attrs = pango_attr_list_new();
+
+ /* Put all of the text together */
+ text[0] = '\0';
+ for ( i=0; i<para->n_runs; i++ ) {
+
+ PangoAttribute *attr;
+ const char *run_text;
+
+ run_text = sc_block_contents(para->runs[i].scblock)
+ + para->runs[i].offs_bytes;
+
+ attr = pango_attr_font_desc_new(para->runs[i].fontdesc);
+ attr->start_index = pos;
+ attr->end_index = pos + para->runs[i].len_bytes;
+ pos += para->runs[i].len_bytes;
+
+ strncat(text, run_text, para->runs[i].len_bytes);
+ pango_attr_list_insert(attrs, attr);
+
+ }
+
+ if ( para->layout == NULL ) {
+ para->layout = pango_layout_new(pc);
+ }
+ pango_layout_set_width(para->layout, pango_units_from_double(w));
+ pango_layout_set_text(para->layout, text, total_len);
+ pango_layout_set_attributes(para->layout, attrs);
+ free(text);
+ pango_attr_list_unref(attrs);
+
+ pango_layout_get_extents(para->layout, NULL, &rect);
+ para->height = pango_units_to_double(rect.height);
+}
+
+
+void add_run(Paragraph *para, SCBlock *scblock, size_t offs_bytes,
+ size_t len_bytes, PangoFontDescription *fdesc, int eop)
+{
+ struct text_run *runs_new;
+
+ if ( !para->open ) {
+ fprintf(stderr, "Adding a run to a closed paragraph!\n");
+ return;
+ }
+
+ runs_new = realloc(para->runs,
+ (para->n_runs+1)*sizeof(struct text_run));
+ if ( runs_new == NULL ) {
+ fprintf(stderr, "Failed to add run.\n");
+ return;
+ }
+
+ para->runs = runs_new;
+ para->runs[para->n_runs].scblock = scblock;
+ para->runs[para->n_runs].offs_bytes = offs_bytes;
+ para->runs[para->n_runs].len_bytes = len_bytes;
+ para->runs[para->n_runs].fontdesc = pango_font_description_copy(fdesc);
+ para->n_runs++;
+
+ if ( eop ) para->open = 0;
+}
+
+
+void add_callback_para(struct frame *fr, double w, double h,
+ SCCallbackDrawFunc draw_func,
+ SCCallbackClickFunc click_func, void *bvp,
+ void *vp)
+{
+ /* FIXME */
+}
+
+
+void add_image_para(struct frame *fr, const char *filename,
+ double w, double h, int editable)
+{
+ /* FIXME */
+}
+
+
+double total_height(struct frame *fr)
+{
+ int i;
+ double t = 0.0;
+ for ( i=0; i<fr->n_paras; i++ ) {
+ t += fr->paras[i]->height + 20.0;
+ }
+ return t;
+}
+
+
+Paragraph *last_open_para(struct frame *fr)
+{
+ Paragraph **paras_new;
+ Paragraph *pnew;
+
+ if ( (fr->paras != NULL) && (fr->paras[fr->n_paras-1]->open) ) {
+ return fr->paras[fr->n_paras-1];
+ }
+
+ /* No open paragraph found, create a new one */
+ paras_new = realloc(fr->paras, (fr->n_paras+1)*sizeof(Paragraph *));
+ if ( paras_new == NULL ) return NULL;
+
+ pnew = calloc(1, sizeof(struct _paragraph));
+ if ( pnew == NULL ) return NULL;
+
+ fr->paras = paras_new;
+ fr->paras[fr->n_paras++] = pnew;
+
+ pnew->open = 1;
+ pnew->n_runs = 0;
+ pnew->runs = NULL;
+ pnew->layout = NULL;
+ pnew->height = 0.0;
+
+ return pnew;
+}
+
+
+void close_last_paragraph(struct frame *fr)
+{
+ if ( fr->paras == NULL ) return;
+ fr->paras[fr->n_paras-1]->open = 0;
+}
diff --git a/src/frame.h b/src/frame.h
index 8b1a645..99e5df4 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -1,7 +1,7 @@
/*
* frame.h
*
- * Copyright © 2013-2015 Thomas White <taw@bitwiz.org.uk>
+ * Copyright © 2013-2016 Thomas White <taw@bitwiz.org.uk>
*
* This file is part of Colloquium.
*
@@ -31,6 +31,7 @@
#include <cairo.h>
#include "sc_parse.h"
+#include "sc_interp.h"
typedef enum
@@ -47,6 +48,7 @@ typedef enum
GRAD_VERT
} GradientType;
+typedef struct _paragraph Paragraph;
struct frame
{
@@ -55,16 +57,10 @@ struct frame
int max_children;
SCBlock *scblocks;
- 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;
+ Paragraph **paras;
+ int n_paras;
+ int max_paras;
/* The font which will be used by default for this frame */
PangoFontDescription *fontdesc;
@@ -94,9 +90,6 @@ struct frame
/* True if this frame can be resized and moved */
int resizable;
-
- /* True if wrapping failed for this frame */
- int trouble;
};
@@ -108,4 +101,25 @@ extern void delete_subframe(struct frame *top, struct frame *fr);
extern struct frame *find_frame_with_scblocks(struct frame *top,
SCBlock *scblocks);
+extern double total_height(struct frame *fr);
+
+extern Paragraph *last_open_para(struct frame *fr);
+extern void close_last_paragraph(struct frame *fr);
+
+extern PangoLayout *paragraph_layout(Paragraph *para);
+extern double paragraph_height(Paragraph *para);
+
+extern void add_run(Paragraph *para, SCBlock *scblock, size_t offs_bytes,
+ size_t len_bytes, PangoFontDescription *fdesc, int eop);
+
+extern void add_callback_para(struct frame *fr, double w, double h,
+ SCCallbackDrawFunc draw_func,
+ SCCallbackClickFunc click_func, void *bvp,
+ void *vp);
+
+extern void add_image_para(struct frame *fr, const char *filename,
+ double w, double h, int editable);
+
+extern void wrap_paragraph(Paragraph *para, PangoContext *pc, double w);
+
#endif /* FRAME_H */
diff --git a/src/presentation.c b/src/presentation.c
index 98f9ecc..60c27f8 100644
--- a/src/presentation.c
+++ b/src/presentation.c
@@ -34,7 +34,6 @@
#include "slide_window.h"
#include "frame.h"
#include "imagestore.h"
-#include "wrap.h"
#include "notes.h"
#include "inhibit_screensaver.h"
#include "render.h"
diff --git a/src/render.c b/src/render.c
index 506863d..b91509f 100644
--- a/src/render.c
+++ b/src/render.c
@@ -40,30 +40,10 @@
#include "presentation.h"
#include "frame.h"
#include "render.h"
-#include "wrap.h"
#include "imagestore.h"
-#include "boxvec.h"
-
-
-static void render_glyph_box(cairo_t *cr, struct wrap_box *box)
-{
- int i;
-
- cairo_new_path(cr);
- cairo_move_to(cr, 0.0, 0.0);
- if ( box->segs == NULL ) {
- fprintf(stderr, "Box %p has NULL pointer.\n", box);
- return;
- }
- cairo_set_source_rgba(cr, box->col[0], box->col[1], box->col[2],
- box->col[3]);
- for ( i=0; i<box->n_segs; i++ ) {
- pango_cairo_show_glyph_string(cr, box->font,
- box->segs[i].glyphs);
- }
-}
+#if 0
static void render_callback_box(cairo_t *cr, struct wrap_box *box)
{
double ascd;
@@ -112,8 +92,10 @@ static void render_callback_box(cairo_t *cr, struct wrap_box *box)
cairo_surface_destroy(surf);
}
+#endif
+#if 0
static void render_image_box(cairo_t *cr, struct wrap_box *box, ImageStore *is,
enum is_size isz)
{
@@ -160,172 +142,9 @@ static void render_image_box(cairo_t *cr, struct wrap_box *box, ImageStore *is,
cairo_fill(cr);
cairo_restore(cr);
}
+#endif
-static void UNUSED draw_outline(cairo_t *cr, struct wrap_box *box)
-{
- double asc, desc;
-
- if ( box->type == WRAP_BOX_SENTINEL ) return;
-
- asc = pango_units_to_double(box->ascent);
- desc = pango_units_to_double(box->height) - asc;
-
- cairo_rectangle(cr, 0.0, -asc, pango_units_to_double(box->width),
- asc + desc);
- if ( box->type == WRAP_BOX_NOTHING ) {
- cairo_set_source_rgb(cr, 0.0, 0.0, 1.0);
- cairo_set_line_width(cr, 0.1);
- } else if ( box->type == WRAP_BOX_SENTINEL ) {
- cairo_set_source_rgb(cr, 1.0, 0.0, 1.0);
- cairo_set_line_width(cr, 0.5);
- } else {
- cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
- cairo_set_line_width(cr, 0.1);
- }
- cairo_stroke(cr);
-
- cairo_rectangle(cr, pango_units_to_double(box->width), -asc,
- pango_units_to_double(box->sp), asc + desc);
- cairo_set_source_rgba(cr, 0.7, 0.4, 0.7, 0.2);
- cairo_fill(cr);
-}
-
-
-static void render_boxes(struct wrap_line *line, cairo_t *cr, ImageStore *is,
- enum is_size isz)
-{
- int j;
- double x_pos = 0.0;
-
- for ( j=0; j<bv_len(line->boxes); j++ ) {
-
- struct wrap_box *box;
-
- cairo_save(cr);
-
- box = bv_box(line->boxes, j);
- cairo_translate(cr, x_pos, 0.0);
-
- draw_outline(cr, box);
-
- switch ( box->type ) {
-
- case WRAP_BOX_PANGO :
- render_glyph_box(cr, box);
- break;
-
- case WRAP_BOX_IMAGE :
- render_image_box(cr, box, is, isz);
- break;
-
- case WRAP_BOX_CALLBACK:
- render_callback_box(cr, box);
- break;
-
- case WRAP_BOX_NOTHING :
- break;
-
- case WRAP_BOX_SENTINEL :
- /* Do nothing */
- break;
-
- }
-
- x_pos += pango_units_to_double(box->width);
- x_pos += pango_units_to_double(box->sp);
-
- cairo_restore(cr);
-
- }
-}
-
-
-static void draw_overfull_marker(cairo_t *cr, struct frame *fr, int i)
-{
- cairo_move_to(cr, fr->w - fr->pad_l- fr->pad_r, 0.0);
- cairo_line_to(cr, fr->w - fr->pad_l - fr->pad_r,
- pango_units_to_double(fr->lines[i].height));
- cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
- cairo_set_line_width(cr, 4.0);
- cairo_stroke(cr);
-}
-
-
-static void draw_underfull_marker(cairo_t *cr, struct frame *fr, int i)
-{
- cairo_move_to(cr, fr->w - fr->pad_l- fr->pad_r, 0.0);
- cairo_line_to(cr, fr->w - fr->pad_l - fr->pad_r,
- pango_units_to_double(fr->lines[i].height));
- cairo_set_source_rgb(cr, 0.0, 0.0, 1.0);
- cairo_set_line_width(cr, 4.0);
- cairo_stroke(cr);
-}
-
-
-static void render_lines(struct frame *fr, cairo_t *cr, ImageStore *is,
- enum is_size isz, double min_y, double max_y)
-{
- int i;
- double y_pos = 0.0;
- const int debug = 0;
-
- for ( i=0; i<fr->n_lines; i++ ) {
-
- /* FIXME: Line spacing */
- double lh = pango_units_to_double(fr->lines[i].height);
-
- if ( y_pos+lh < min_y ) {
- y_pos += lh;
- continue;
- }
-
- if ( y_pos > max_y ) break;
-
- cairo_save(cr);
-
- /* Move to beginning of the line */
- cairo_translate(cr, 0.0, y_pos);
-
- if ( debug ) {
- cairo_move_to(cr,
- 0.0,
- 0.5+pango_units_to_double(fr->lines[i].ascent));
- cairo_line_to(cr,
- pango_units_to_double(fr->lines[i].width),
- 0.5+pango_units_to_double(fr->lines[i].ascent));
- cairo_set_source_rgb(cr, 0.0, 0.0, 1.0);
- cairo_set_line_width(cr, 1.0);
- cairo_stroke(cr);
-
- cairo_move_to(cr, 0.0, 0.0);
- cairo_line_to(cr, 0.0,
- pango_units_to_double(fr->lines[i].height));
- cairo_set_line_width(cr, 3.0);
- cairo_set_source_rgb(cr, 0.0, 1.0, 0.0);
- cairo_stroke(cr);
- }
-
- /* Render the line */
- cairo_save(cr);
- cairo_translate(cr, 0.0,
- pango_units_to_double(fr->lines[i].ascent));
- render_boxes(&fr->lines[i], cr, is, isz);
- cairo_restore(cr);
-
- if ( debug && fr->lines[i].overfull ) {
- draw_overfull_marker(cr, fr, i);
- }
- if ( debug && fr->lines[i].underfull ) {
- draw_underfull_marker(cr, fr, i);
- }
-
- y_pos += lh;
-
- cairo_restore(cr);
-
- }
-}
static void do_background(cairo_t *cr, struct frame *fr)
@@ -375,23 +194,34 @@ static void do_background(cairo_t *cr, struct frame *fr)
}
+static void render_paragraph(cairo_t *cr, Paragraph *para)
+{
+ PangoLayout *layout = paragraph_layout(para);
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ pango_cairo_update_layout(cr, layout);
+ pango_cairo_show_layout(cr, layout);
+ cairo_fill(cr);
+}
+
+
static int draw_frame(cairo_t *cr, struct frame *fr, ImageStore *is,
enum is_size isz, double min_y, double max_y)
{
+ int i;
+ double hpos = 0.0;
+
cairo_save(cr);
do_background(cr, fr);
- if ( fr->trouble ) {
- cairo_new_path(cr);
- cairo_rectangle(cr, 0.0, 0.0, fr->w, fr->h);
- cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
- cairo_set_line_width(cr, 2.0);
- cairo_stroke(cr);
- }
-
- /* Actually render the lines */
+ /* Actually render the contents */
cairo_translate(cr, fr->pad_l, fr->pad_t);
- render_lines(fr, cr, is, isz, min_y, max_y);
+ for ( i=0; i<fr->n_paras; i++ ) {
+ cairo_save(cr);
+ cairo_translate(cr, 0.0, hpos);
+ render_paragraph(cr, fr->paras[i]);
+ hpos += paragraph_height(fr->paras[i]) + 20.0;
+ cairo_restore(cr);
+ }
cairo_restore(cr);
return 0;
@@ -419,15 +249,24 @@ int recursive_draw(struct frame *fr, cairo_t *cr,
}
-int recursive_wrap(struct frame *fr, ImageStore *is, enum is_size isz)
+void wrap_frame(struct frame *fr, PangoContext *pc)
+{
+ int i;
+
+ for ( i=0; i<fr->n_paras; i++ ) {
+ wrap_paragraph(fr->paras[i], pc, fr->w - fr->pad_l - fr->pad_r);
+ }
+}
+
+
+int recursive_wrap(struct frame *fr, PangoContext *pc)
{
int i;
- /* Wrap boxes -> wrap lines */
- wrap_contents(fr);
+ wrap_frame(fr, pc);
for ( i=0; i<fr->num_children; i++ ) {
- recursive_wrap(fr->children[i], is, isz);
+ recursive_wrap(fr->children[i], pc);
}
return 0;
@@ -498,7 +337,8 @@ static struct frame *render_sc_to_surface(SCBlock *scblocks, cairo_surface_t *su
cairo_t *cr, double log_w, double log_h,
SCBlock **stylesheets, SCCallbackList *cbl,
ImageStore *is, enum is_size isz,
- int slide_number, PangoLanguage *lang)
+ int slide_number, PangoLanguage *lang,
+ PangoContext *pc)
{
struct frame *top;
@@ -509,7 +349,7 @@ static struct frame *render_sc_to_surface(SCBlock *scblocks, cairo_surface_t *su
top = interp_and_shape(scblocks, stylesheets, cbl, is, isz,
slide_number, cr, log_w, log_h, lang);
- recursive_wrap(top, is, isz);
+ recursive_wrap(top, pc);
recursive_draw(top, cr, is, isz, 0.0, log_h);
@@ -527,13 +367,15 @@ cairo_surface_t *render_sc(SCBlock *scblocks, int w, int h,
cairo_surface_t *surf;
cairo_t *cr;
struct frame *top;
+ PangoContext *pc;
surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h);
cr = cairo_create(surf);
+ pc = pango_cairo_create_context(cr);
cairo_scale(cr, w/log_w, h/log_h);
top = render_sc_to_surface(scblocks, surf, cr, log_w, log_h,
stylesheets, cbl, is, isz,slide_number,
- lang);
+ lang, pc);
cairo_destroy(cr);
*ptop = top;
@@ -551,6 +393,7 @@ int export_pdf(struct presentation *p, const char *filename)
cairo_t *cr;
SCBlock *bl;
int i;
+ PangoContext *pc;
r = p->slide_height / p->slide_width;
@@ -562,6 +405,7 @@ int export_pdf(struct presentation *p, const char *filename)
cr = cairo_create(surf);
scale = w / p->slide_width;
+ pc = pango_cairo_create_context(cr);
i = 1;
while ( bl != NULL ) {
@@ -586,7 +430,7 @@ int export_pdf(struct presentation *p, const char *filename)
render_sc_to_surface(sc_block_child(bl), surf, cr, p->slide_width,
p->slide_height, stylesheets, NULL,
- p->is, ISZ_SLIDESHOW, i, p->lang);
+ p->is, ISZ_SLIDESHOW, i, p->lang, pc);
cairo_restore(cr);
@@ -597,6 +441,7 @@ int export_pdf(struct presentation *p, const char *filename)
}
+ g_object_unref(pc);
cairo_surface_finish(surf);
cairo_destroy(cr);
diff --git a/src/render.h b/src/render.h
index 486f129..be9bfd8 100644
--- a/src/render.h
+++ b/src/render.h
@@ -1,7 +1,7 @@
/*
* render.h
*
- * Copyright © 2013-2015 Thomas White <taw@bitwiz.org.uk>
+ * Copyright © 2013-2016 Thomas White <taw@bitwiz.org.uk>
*
* This file is part of Colloquium.
*
@@ -50,7 +50,8 @@ extern struct frame *interp_and_shape(SCBlock *scblocks, SCBlock **stylesheets,
int slide_number, cairo_t *cr,
double w, double h, PangoLanguage *lang);
-extern int recursive_wrap(struct frame *fr, ImageStore *is, enum is_size isz);
+extern void wrap_frame(struct frame *fr, PangoContext *pc);
+extern int recursive_wrap(struct frame *fr, PangoContext *pc);
extern int export_pdf(struct presentation *p, const char *filename);
diff --git a/src/sc_editor.c b/src/sc_editor.c
index 27ab849..9b81980 100644
--- a/src/sc_editor.c
+++ b/src/sc_editor.c
@@ -38,13 +38,10 @@
#include "slide_window.h"
#include "render.h"
#include "frame.h"
-#include "wrap.h"
#include "sc_parse.h"
#include "sc_interp.h"
#include "sc_editor.h"
#include "slideshow.h"
-#include "shape.h"
-#include "boxvec.h"
static void scroll_interface_init(GtkScrollable *iface)
@@ -118,12 +115,17 @@ static void update_size(SCEditor *e)
static gboolean resize_sig(GtkWidget *widget, GdkEventConfigure *event,
SCEditor *e)
{
+ PangoContext *pc;
+ cairo_t *cr;
+
+ cr = gdk_cairo_create(gtk_widget_get_window(widget));
+ pc = pango_cairo_create_context(cr);
+
e->visible_height = event->height;
e->visible_width = event->width;
/* Interpret and shape, if not already done */
if ( e->top == NULL ) {
- cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(widget));
double w, h;
if ( e->flow ) {
w = event->width;
@@ -135,8 +137,7 @@ static gboolean resize_sig(GtkWidget *widget, GdkEventConfigure *event,
e->top = interp_and_shape(e->scblocks, e->stylesheets, e->cbl,
e->is, ISZ_EDITOR, 0, cr, w, h,
e->lang);
- recursive_wrap(e->top, e->is, ISZ_EDITOR);
- cairo_destroy(cr);
+ recursive_wrap(e->top, pc);
}
if ( e->flow ) {
@@ -145,11 +146,15 @@ static gboolean resize_sig(GtkWidget *widget, GdkEventConfigure *event,
e->top->h = 0.0; /* To be updated in a moment */
e->top->x = 0.0;
e->top->y = 0.0;
- wrap_contents(e->top); /* Only the top level needs to be wrapped */
+ /* Only the top level needs to be wrapped */
+ wrap_frame(e->top, pc);
}
update_size(e);
+ g_object_unref(pc);
+ cairo_destroy(cr);
+
return FALSE;
}
@@ -301,7 +306,7 @@ void sc_editor_set_background(SCEditor *e, double r, double g, double b)
void sc_editor_remove_cursor(SCEditor *e)
{
e->cursor_frame = NULL;
- e->cursor_line = 0;
+ e->cursor_para = 0;
e->cursor_pos = 0;
e->selection = NULL;
}
@@ -312,26 +317,30 @@ void sc_editor_remove_cursor(SCEditor *e)
* invalid. The cursor position will be unset. */
static void full_rerender(SCEditor *e)
{
+ cairo_t *cr;
+ PangoContext *pc;
+
frame_free(e->top);
- e->cursor_frame = NULL;
- e->cursor_line = 0;
- e->cursor_pos = 0;
- e->selection = NULL;
+ sc_editor_remove_cursor(e);
+
+ cr = gdk_cairo_create(gtk_widget_get_window(GTK_WIDGET(e)));
+ pc = pango_cairo_create_context(cr);
- cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(GTK_WIDGET(e)));
e->top = interp_and_shape(e->scblocks, e->stylesheets, e->cbl,
e->is, ISZ_EDITOR, 0, cr, e->w, 0.0, e->lang);
- cairo_destroy(cr);
e->top->x = 0.0;
e->top->y = 0.0;
e->top->w = e->w;
e->top->h = 0.0; /* To be updated in a moment */
- recursive_wrap(e->top, e->is, ISZ_EDITOR);
+ recursive_wrap(e->top, pc);
update_size(e);
sc_editor_redraw(e);
+
+ g_object_unref(pc);
+ cairo_destroy(cr);
}
@@ -353,182 +362,24 @@ void sc_editor_delete_selected_frame(SCEditor *e)
}
-static void move_cursor_back(SCEditor *e)
+static int find_cursor(struct frame *fr, double x, double y,
+ int *ppara, int *ppos)
{
- int retreat = 0;
- signed int cp, cb, cl;
- struct wrap_line *line;
- struct wrap_box *box;
-
- cp = e->cursor_pos;
- cb = e->cursor_box;
- cl = e->cursor_line;
-
- line = &e->cursor_frame->lines[e->cursor_line];
- box = bv_box(line->boxes, e->cursor_box);
- if ( box->type == WRAP_BOX_PANGO ) {
-
- if ( cp == 0 ) {
- retreat = 1;
- } else {
- cp--;
- }
-
- } else {
- cp--;
- if ( cp < 0 ) retreat = 1;
- }
-
- if ( retreat ) {
-
- do {
-
- cb--;
-
- if ( cb < 0 ) {
- cl--;
- if ( cl < 0 ) return;
- e->cursor_line = cl;
- line = &e->cursor_frame->lines[cl];
- cb = bv_len(line->boxes) - 1;
- }
-
- } while ( !bv_box(line->boxes, cb)->editable );
-
- e->cursor_box = cb;
- box = bv_box(line->boxes, cb);
- if ( box->type == WRAP_BOX_PANGO ) {
- cp = box->len_chars;
- if ( box->space == WRAP_SPACE_NONE ) {
- cp--;
- }
- } else {
- cp = 0;
- }
-
- }
- e->cursor_pos = cp;
+ *ppara = 0;
+ *ppos = 0;
+ return 0;
}
-void cur_box_diag(SCEditor *e)
+static void move_cursor_back(SCEditor *e)
{
- int sln, sbx, sps;
- struct frame *fr;
-
- fr = e->cursor_frame;
- sln = e->cursor_line;
- sbx = e->cursor_box;
- sps = e->cursor_pos;
-
- if ( fr->lines == NULL ) {
- printf("Current frame has no lines!\n");
- return;
- }
-
- if ( fr->lines[sln].boxes == NULL ) {
- printf("line %i of %i, but it has no boxes\n",
- sln, fr->n_lines);
- return;
- }
-
- struct wrap_box *sbox = bv_box(fr->lines[sln].boxes, sbx);
-
- if ( sbox == NULL ) {
- printf("line/box: [%i of %i]/[%i of %i]/NULL box\n",
- sln, fr->n_lines, sbx,
- bv_len(e->cursor_frame->lines[sln].boxes));
- return;
- }
-
- printf("line/box/pos: [%i of %i]/[%i of %i]/[%i of %i]\n",
- 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 ) {
- printf("Warning: in a nothing box!\n");
- }
-
- struct wrap_line *ln = &fr->lines[sln];
- int i;
- for ( i=0; i<bv_len(ln->boxes); i++ ) {
- char pp = '[';
- char pq = ']';
- 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);
- }
- printf("\n");
+ /* FIXME */
}
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 = bv_box(line->boxes, e->cursor_box);
-
- cp = e->cursor_pos;
- cb = e->cursor_box;
- cl = e->cursor_line;
-
- /* FIXME: For Pango boxes, we should be counting cursor positions, not
- * characters */
-
- switch ( box->type ) {
-
- case WRAP_BOX_PANGO:
- if ( cp+1 > box->len_chars ) {
- advance = 1;
- } else {
- cp++;
- }
- break;
-
- case WRAP_BOX_NOTHING:
- case WRAP_BOX_SENTINEL:
- advance = 1;
- break;
-
- case WRAP_BOX_IMAGE:
- case WRAP_BOX_CALLBACK:
- cp++;
- if ( cp > 1 ) advance = 1;
- break;
-
- }
-
- if ( advance ) {
-
- do {
-
- cb++;
- cp = 0;
-
- if ( box->space == WRAP_SPACE_NONE ) {
- cp = 1;
- }
-
- if ( cb >= bv_len(line->boxes) ) {
- cl++;
- if ( cl >= e->cursor_frame->n_lines ) {
- /* Give up - could not move */
- return;
- }
- line = &e->cursor_frame->lines[cl];
- cb = 0;
- cp = 0;
- }
-
- } while ( !bv_box(line->boxes, cb)->editable );
-
- e->cursor_line = cl;
- e->cursor_box = cb;
-
- }
- e->cursor_pos = cp;
+ /* FIXME */
}
@@ -569,39 +420,23 @@ static void draw_editing_box(cairo_t *cr, struct frame *fr)
}
-static void draw_caret(cairo_t *cr, struct frame *fr,
- int cursor_line, int cursor_box, int cursor_pos)
+static void draw_caret(cairo_t *cr, struct frame *fr)
{
- double xposd, yposd, line_height;
- double cx, clow, chigh;
+#if 0
+ double xposd, yposd, cx;
+ double clow, chigh;
+ PangoRectangle pos;
const double t = 1.8;
- struct wrap_box *box;
- int i;
- if ( fr == NULL ) return;
- if ( fr->n_lines == 0 ) return;
- if ( fr->lines == NULL ) return;
- if ( fr->lines[cursor_line].boxes == NULL ) return;
-
- /* Locate the cursor in a "logical" and "geographical" sense */
- 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;
-
- for ( i=0; i<cursor_line; i++ ) {
- yposd += pango_units_to_double(fr->lines[i].height);
- }
-
- for ( i=0; i<cursor_box; i++ ) {
- 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);
- }
+ pango_layout_get_cursor_pos(o->layout,
+ o->insertion_point+o->insertion_trail,
+ &pos, NULL);
- cx = fr->x + xposd;
- clow = fr->y + yposd;
- chigh = clow + line_height;
+ xposd = pos.x/PANGO_SCALE;
+ cx = o->base.x - o->offs_x + xposd;
+ yposd = pos.y/PANGO_SCALE;
+ clow = o->base.y - o->offs_y + yposd;
+ chigh = clow + (pos.height/PANGO_SCALE);
cairo_move_to(cr, cx, clow);
cairo_line_to(cr, cx, chigh);
@@ -619,6 +454,7 @@ static void draw_caret(cairo_t *cr, struct frame *fr,
cairo_set_source_rgb(cr, 0.86, 0.0, 0.0);
cairo_set_line_width(cr, 1.0);
cairo_stroke(cr);
+#endif
}
@@ -652,8 +488,7 @@ static void draw_overlay(cairo_t *cr, SCEditor *e)
draw_resize_handle(cr, x+w-20.0, y+h-20.0);
}
- draw_caret(cr, e->cursor_frame, e->cursor_line, e->cursor_box,
- e->cursor_pos);
+ draw_caret(cr, e->cursor_frame);
}
@@ -726,49 +561,6 @@ static gboolean draw_sig(GtkWidget *da, cairo_t *cr, SCEditor *e)
}
-static void fixup_cursor(SCEditor *e)
-{
- struct frame *fr;
- struct wrap_line *sline;
- struct wrap_box *sbox;
-
- fr = e->cursor_frame;
-
- 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 = bv_len(fr->lines[fr->n_lines-1].boxes)-1;
- }
-
- sline = &fr->lines[e->cursor_line];
-
- if ( e->cursor_box >= bv_len(sline->boxes) ) {
-
- /* We find ourselves in a box which doesn't exist */
-
- if ( e->cursor_line < fr->n_lines-1 ) {
- /* This isn't the last line, so go to the first box of
- * the next line */
- e->cursor_line++;
- e->cursor_box = 0;
- sline = &e->cursor_frame->lines[e->cursor_line];
- } else {
- /* 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 = bv_len(sline->boxes)-1;
- }
- }
-
- 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);
- }
-}
-
-
static void move_cursor(SCEditor *e, signed int x, signed int y)
{
if ( x > 0 ) {
@@ -781,6 +573,8 @@ static void move_cursor(SCEditor *e, signed int x, signed int y)
void insert_scblock(SCBlock *scblock, SCEditor *e)
{
+#if 0
+ /* FIXME: Insert "scblock" at the cursor */
int sln, sbx, sps;
struct wrap_box *sbox;
struct frame *fr = e->cursor_frame;
@@ -804,303 +598,21 @@ void insert_scblock(SCBlock *scblock, SCEditor *e)
//fixup_cursor(e);
//advance_cursor(e);
//sc_editor_redraw(e);
+#endif
}
-static void shift_box_offsets(struct frame *fr, struct wrap_box *box, int n)
-{
- int i;
- int sn = 0;
-
- for ( i=0; i<fr->boxes->n_boxes; i++ ) {
- if ( bv_box(fr->boxes, i) == box ) {
- sn = i+1;
- break;
- }
- }
-
- assert(sn > 0); /* Lowest it can possibly be is 1 */
-
- for ( i=sn; i<fr->boxes->n_boxes; i++ ) {
- bv_box(fr->boxes, i)->offs_char += n;
- }
-}
-
-
-static void maybe_downgrade_box(struct wrap_box *box)
-{
- if ( box->len_chars == 0 ) {
-
- printf("Downgrading box.\n");
- box->type = WRAP_BOX_NOTHING;
- }
-}
-
-
-static void split_boxes(struct wrap_box *sbox, PangoLogAttr *log_attrs,
- int offs, int cursor_pos, struct boxvec *boxes,
- PangoContext *pc)
-{
- struct wrap_box *nbox;
-
- printf("Adding line break (new box) at pos %i\n", offs);
- printf("offset %i into box\n", cursor_pos);
-
- /* Add a new box containing the text after the break */
- nbox = calloc(1, sizeof(struct wrap_box));
- if ( nbox == NULL ) {
- fprintf(stderr, "Failed to allocate a text box.\n");
- return;
- }
- bv_add_after(boxes, sbox, nbox);
- nbox->type = WRAP_BOX_PANGO;
- nbox->space = sbox->space;
- nbox->len_chars = sbox->len_chars - cursor_pos;
- if ( nbox->len_chars == 0 ) {
- printf("WARNING! Zero-length box!\n");
- }
- nbox->offs_char = sbox->offs_char + cursor_pos;
- nbox->scblock = sbox->scblock;
- nbox->fontdesc = pango_font_description_copy(sbox->fontdesc);
- nbox->col[0] = sbox->col[0];
- nbox->col[1] = sbox->col[1];
- nbox->col[2] = sbox->col[2];
- nbox->col[3] = sbox->col[3];
- nbox->editable = sbox->editable;
-
- /* Shorten the text in the first box */
- sbox->len_chars = cursor_pos;
- if ( log_attrs[offs].is_expandable_space ) {
- sbox->space = WRAP_SPACE_INTERWORD;
- nbox->len_chars--;
- nbox->offs_char++;
- maybe_downgrade_box(nbox);
- } else if ( log_attrs[offs+1].is_mandatory_break ) {
- sbox->space = WRAP_SPACE_EOP;
- printf("New paragraph!\n");
- nbox->offs_char++;
- nbox->len_chars--;
- maybe_downgrade_box(nbox);
- } else {
- sbox->space = WRAP_SPACE_NONE;
- printf("two boxes.\n");
- }
-
- printf("boxes: <%i %i %i>[%i %i %i]\n",
- sbox->offs_char, sbox->len_chars, sbox->n_segs,
- nbox->offs_char, nbox->len_chars, nbox->n_segs);
-
- itemize_and_shape(nbox, pc);
- /* sbox will get done in just a moment */
-}
-
-
-static void fixup_line_breaks(struct wrap_box *sbox, struct boxvec *boxes,
- int cursor_pos, PangoLanguage *lang,
- PangoContext *pc)
-{
- const char *text;
- size_t len_bytes;
- int len_chars;
- PangoLogAttr *log_attrs;
- int offs;
-
- /* Run pango_get_log_attrs on the entire SCBlock, to get good context */
- text = sc_block_contents(sbox->scblock);
- len_bytes = strlen(text);
- len_chars = g_utf8_strlen(text, -1);
- if ( len_chars <= 1 ) return;
- log_attrs = malloc((len_chars+1)*sizeof(PangoLogAttr));
- if ( log_attrs == NULL ) return;
- pango_get_log_attrs(text, len_bytes, -1, lang,
- log_attrs, len_chars+1);
-
- /* Take a peek at the situation near where we just typed */
- offs = sbox->offs_char + cursor_pos;
- if ( log_attrs[offs+1].is_line_break ) {
-
- /* If there just happens to be two boxes without a space
- * between them, just tweak the space. */
- if ( (cursor_pos == sbox->len_chars-1)
- && (sbox->space == WRAP_SPACE_NONE) )
- {
- printf("Easy case! :D\n");
- if ( log_attrs[offs].is_expandable_space ) {
- sbox->space = WRAP_SPACE_INTERWORD;
- sbox->len_chars--;
- } else if ( log_attrs[offs+1].is_mandatory_break ) {
- sbox->space = WRAP_SPACE_EOP;
- sbox->len_chars--;
- } else {
- printf("WTF space type?\n");
- }
- } else {
- split_boxes(sbox, log_attrs, offs, cursor_pos,
- boxes, pc);
- }
-
-
- } else {
- if ( log_attrs[offs].is_expandable_space ) {
- printf("Space at end!\n");
- if ( sbox->space == WRAP_SPACE_NONE ) {
- sbox->space = WRAP_SPACE_INTERWORD;
- }
- }
- }
-
- free(log_attrs);
-}
-
static void insert_text(char *t, SCEditor *e)
{
- int sln, sbx, sps;
- struct wrap_box *sbox;
- struct frame *fr = e->cursor_frame;
-
- printf("insert! ---------------------------------------------------\n");
-
- if ( fr == NULL ) return;
-
- /* If this is, say, the top level frame, do nothing */
- if ( fr->boxes == NULL ) return;
-
- sln = e->cursor_line;
- sbx = e->cursor_box;
- sps = e->cursor_pos;
- sbox = bv_box(e->cursor_frame->lines[sln].boxes, sbx);
-
- if ( sbox->type == WRAP_BOX_NOTHING ) {
- printf("Upgrading nothing box %p to Pango box\n", sbox);
- sbox->type = WRAP_BOX_PANGO;
- sbox->col[0] = fr->col[0];
- sbox->col[1] = fr->col[1];
- sbox->col[2] = fr->col[2];
- sbox->col[3] = fr->col[3];
- sbox->fontdesc = pango_font_description_copy(fr->fontdesc);
- sbox->segs = NULL;
- }
-
- cur_box_diag(e);
- printf("sps=%i, offs_char=%i\n", sps, sbox->offs_char);
- if ( sbox->type == WRAP_BOX_NOTHING ) {
- printf("Editing a nothing box!\n");
- return;
- }
-
- sc_insert_text(sbox->scblock, sps+sbox->offs_char, t);
- sbox->len_chars += 1;
-
- /* Tweak the offsets of all the subsequent boxes */
- shift_box_offsets(fr, sbox, 1);
-
- fixup_line_breaks(sbox, e->cursor_frame->boxes, e->cursor_pos,
- e->lang, e->pc);
-
- /* The box must be analysed by Pango again, because the segments
- * might have changed */
- itemize_and_shape(sbox, e->pc);
-
- fr->empty = 0;
-
- wrap_contents(e->cursor_frame);
- update_size(e);
- fixup_cursor(e);
- printf("done! -----------------------------------------------------\n");
-
- advance_cursor(e);
-
+ /* FIXME: Insert "t" at the cursor */
sc_editor_redraw(e);
}
static void do_backspace(struct frame *fr, SCEditor *e)
{
- int sln, sbx, sps;
-
- if ( fr == NULL ) return;
-
- /* If this is, say, the top level frame, do nothing */
- if ( fr->n_lines == 0 ) return;
-
- printf("Backspace! ------------------------------------------------\n");
- printf("sbox:\n");
- cur_box_diag(e);
- sln = e->cursor_line;
- sbx = e->cursor_box;
- sps = e->cursor_pos;
- struct wrap_box *sbox = bv_box(e->cursor_frame->lines[sln].boxes, sbx);
-
- move_cursor_back(e);
- printf("fbox:\n");
- cur_box_diag(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 = bv_box(fline->boxes, e->cursor_box);
-
- if ( (fbox->scblock == NULL) || (sbox->scblock == NULL) ) return;
- sc_delete_text(fbox->scblock, e->cursor_pos+fbox->offs_char,
- sbox->scblock, sps+sbox->offs_char);
-
- if ( (sps == 0) && (fbox->space == WRAP_SPACE_INTERWORD) ) {
-
- /* We are deleting an interword space.
- * It's enough just to change the space type, and leave two
- * boxes butted up with no space. */
- fbox->space = WRAP_SPACE_NONE;
- shift_box_offsets(fr, fbox, -1);
- itemize_and_shape(fbox, e->pc);
-
- } else if ( (sps == 0) && (fbox->space == WRAP_SPACE_NONE) ) {
-
- /* We are deleting across a box boundary, but there is no
- * space to delete */
- if ( fbox->len_chars == 0 ) {
- printf("Deleting a zero-length box\n");
-
- } else {
- fbox->len_chars -= 1;
- shift_box_offsets(fr, fbox, -1);
- itemize_and_shape(fbox, e->pc);
- }
-
- } else if ( (sps == 0) && (fbox->space == WRAP_SPACE_EOP) ) {
-
- /* We are deleting the newline between paragraphs */
- fbox->space = WRAP_SPACE_NONE;
- shift_box_offsets(fr, fbox, -1);
- itemize_and_shape(fbox, e->pc);
-
- } else {
-
- sbox->len_chars -= 1;
- shift_box_offsets(fr, sbox, -1);
- if ( sbox->len_chars == 0 ) {
-
- if ( sbox->space == WRAP_SPACE_NONE ) {
- printf("deleting box.\n");
- bv_del(e->cursor_frame->boxes, sbox);
- free(sbox);
- } else {
- printf("downgrading box.\n");
- sbox->type = WRAP_BOX_NOTHING;
- sbox->width = 0;
- }
-
- } else {
- itemize_and_shape(sbox, e->pc);
- }
-
- }
-
- wrap_contents(e->cursor_frame);
- update_size(e);
- fixup_cursor(e);
- cur_box_diag(e);
- printf("done! -----------------------------------------------------\n");
-
+ /* FIXME: Delete at the cursor */
sc_editor_redraw(e);
}
@@ -1296,14 +808,10 @@ static void calculate_box_size(struct frame *fr, SCEditor *e,
}
-static struct wrap_box *cbox(struct frame *fr, int ln, int bn)
-{
- return bv_box(fr->lines[ln].boxes, bn);;
-}
-
-
static int callback_click(SCEditor *e, struct frame *fr, double x, double y)
{
+#if 0
+/* FIXME */
int ln, bn, pn;
struct wrap_box *bx;
@@ -1315,6 +823,7 @@ static int callback_click(SCEditor *e, struct frame *fr, double x, double y)
if ( bx->type == WRAP_BOX_CALLBACK ) {
return bx->click_func(x, y, bx->bvp, bx->vp);
}
+#endif
return 0;
}
@@ -1372,8 +881,7 @@ static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event,
e->cursor_frame = clicked;
find_cursor(clicked, x-fr->x, y-fr->y,
- &e->cursor_line, &e->cursor_box,
- &e->cursor_pos);
+ &e->cursor_para, &e->cursor_pos);
e->start_corner_x = event->x - e->border_offs_x;
e->start_corner_y = event->y - e->border_offs_y;
@@ -1406,8 +914,7 @@ static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event,
e->selection = clicked;
e->cursor_frame = clicked;
find_cursor(clicked, x-clicked->x, y-clicked->y,
- &e->cursor_line, &e->cursor_box,
- &e->cursor_pos);
+ &e->cursor_para, &e->cursor_pos);
}
@@ -1568,10 +1075,8 @@ static gboolean button_release_sig(GtkWidget *da, GdkEventButton *event,
e->drag_corner_y - e->start_corner_y);
e->selection = fr;
e->cursor_frame = fr;
- e->cursor_line = 0;
- e->cursor_box = 0;
+ e->cursor_para = 0;
e->cursor_pos = 0;
- cur_box_diag(e);
break;
case DRAG_REASON_IMPORT :
@@ -1664,9 +1169,6 @@ static gboolean key_press_sig(GtkWidget *da, GdkEventKey *event,
full_rerender(e);
break;
- case GDK_KEY_F6 :
- cur_box_diag(e);
-
}
if ( claim ) return TRUE;
diff --git a/src/sc_editor.h b/src/sc_editor.h
index 166e640..99afa50 100644
--- a/src/sc_editor.h
+++ b/src/sc_editor.h
@@ -117,9 +117,8 @@ struct _sceditor
/* Location of the cursor */
struct frame *cursor_frame;
- int cursor_line;
- int cursor_box;
- int cursor_pos; /* characters into box */
+ int cursor_para; /* paragraph index */
+ int cursor_pos; /* character offset into paragraph */
/* Border surrounding actual slide within drawingarea */
double border_offs_x;
diff --git a/src/sc_interp.c b/src/sc_interp.c
index 35531b6..3291725 100644
--- a/src/sc_interp.c
+++ b/src/sc_interp.c
@@ -33,8 +33,7 @@
#include "sc_parse.h"
#include "sc_interp.h"
-#include "shape.h"
-#include "wrap.h"
+#include "presentation.h"
struct macro
@@ -217,9 +216,9 @@ static void do_callback(SCInterpreter *scin, SCBlock *bl, const char *name)
if ( strcmp(cbl->names[i], name) != 0 ) continue;
r = cbl->box_funcs[i](scin, bl, &w, &h, &bvp, cbl->vps[i]);
if ( !r ) return;
- add_callback_box(sc_interp_get_frame(scin)->boxes, w, h,
- cbl->draw_funcs[i], cbl->click_funcs[i],
- bvp, cbl->vps[i]);
+ add_callback_para(sc_interp_get_frame(scin), w, h,
+ cbl->draw_funcs[i], cbl->click_funcs[i],
+ bvp, cbl->vps[i]);
return;
}
@@ -812,6 +811,52 @@ static int in_macro(SCInterpreter *scin)
}
+/* 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)
+{
+ glong len_chars;
+ const char *text = sc_block_contents(bl);
+ size_t start, len_bytes;
+ PangoFontDescription *fontdesc;
+
+ /* Empty block? */
+ if ( text == NULL ) return 1;
+
+ /* Zero-length block? */
+ len_chars = g_utf8_strlen(text, -1);
+ if ( len_chars == 0 ) return 1;
+
+ fontdesc = sc_interp_get_fontdesc(scin);
+
+ len_bytes = strlen(text);
+ 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);
+ }
+
+ if ( text[start] == '\n' ) {
+ close_last_paragraph(fr);
+ } else {
+ Paragraph *para = last_open_para(fr);
+ add_run(para, bl, start, len, fontdesc, 0);
+ }
+ start += len + 1;
+
+ } while ( start < len_bytes );
+
+ return 0;
+}
+
+
static int check_outputs(SCBlock *bl, SCInterpreter *scin)
{
const char *name = sc_block_name(bl);
@@ -819,8 +864,8 @@ static int check_outputs(SCBlock *bl, SCInterpreter *scin)
SCBlock *child = sc_block_child(bl);
if ( name == NULL ) {
- split_words(sc_interp_get_frame(scin)->boxes,
- scin->pc, bl, scin->lang, 1, scin);
+ add_text(sc_interp_get_frame(scin),
+ scin->pc, bl, scin->lang, 1, scin);
} else if ( strcmp(name, "image")==0 ) {
double w, h;
@@ -828,8 +873,8 @@ static int check_outputs(SCBlock *bl, SCInterpreter *scin)
if ( parse_image_options(options, sc_interp_get_frame(scin),
&w, &h, &filename) == 0 )
{
- add_image_box(sc_interp_get_frame(scin)->boxes,
- filename, w, h, 1);
+ add_image_para(sc_interp_get_frame(scin),
+ filename, w, h, 1);
free(filename);
} else {
fprintf(stderr, "Invalid image options '%s'\n",
diff --git a/src/sc_interp.h b/src/sc_interp.h
index e5f4d0a..54e2233 100644
--- a/src/sc_interp.h
+++ b/src/sc_interp.h
@@ -1,7 +1,7 @@
/*
* sc_interp.h
*
- * Copyright © 2014-2015 Thomas White <taw@bitwiz.org.uk>
+ * Copyright © 2014-2016 Thomas White <taw@bitwiz.org.uk>
*
* This file is part of Colloquium.
*
@@ -29,7 +29,7 @@
#include <pango/pangocairo.h>
-#include "frame.h"
+struct frame;
struct presentation;
typedef struct _scinterp SCInterpreter;
@@ -39,6 +39,8 @@ typedef int (*SCCallbackBoxFunc)(SCInterpreter *scin, SCBlock *bl,
typedef cairo_surface_t *(*SCCallbackDrawFunc)(int w, int h, void *, void *);
typedef int (*SCCallbackClickFunc)(double x, double y, void *, void *);
+#include "frame.h"
+
extern SCInterpreter *sc_interp_new(PangoContext *pc, PangoLanguage *lang,
struct frame *top);
extern void sc_interp_destroy(SCInterpreter *scin);
diff --git a/src/shape.c b/src/shape.c
deleted file mode 100644
index 44e9256..0000000
--- a/src/shape.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * shape.c
- *
- * Copyright © 2014-2015 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 <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pango/pangocairo.h>
-
-#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)
-{
- PangoRectangle rect;
- 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),
- box->offs_char + seg->offs_char
- + seg->len_chars);
-
- if ( seg->glyphs != NULL ) {
- pango_glyph_string_free(seg->glyphs);
- }
- //printf("shaping '%s' (%i chars)\n", tp, seg->len_chars);
- seg->glyphs = pango_glyph_string_new();
- pango_shape(tp, ep-tp, &seg->analysis, seg->glyphs);
-
- pango_glyph_string_extents(seg->glyphs, box->font, NULL, &rect);
-
- seg->width = rect.width;
- seg->height = rect.height;
- seg->ascent = PANGO_ASCENT(rect);
-}
-
-
-static void calc_box_geometry(struct wrap_box *box)
-{
- int i;
-
- if ( box->type != WRAP_BOX_PANGO ) return;
-
- box->width = 0;
- box->height = 0;
- box->ascent = 0;
-
- for ( i=0; i<box->n_segs; i++ ) {
- struct text_seg *seg = &box->segs[i];
- box->width += seg->width;
- if ( seg->height > box->height ) box->height = seg->height;
- if ( seg->ascent > box->ascent ) box->ascent = seg->ascent;
- }
-}
-
-
-void shape_box(struct wrap_box *box)
-{
- int i;
- printf("shaping box %p! n_segs=%i\n", box, box->n_segs);
-
- for ( i=0; i<box->n_segs; i++ ) {
- shape_segment(box, &box->segs[i]);
- }
-
- calc_box_geometry(box);
-}
-
-
-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;
-
- box = calloc(1, sizeof(struct wrap_box));
- if ( box == NULL ) {
- fprintf(stderr, "Failed to allocate a nothing box.\n");
- return;
- }
- box->type = WRAP_BOX_NOTHING;
- box->scblock = scblock;
- box->offs_char = offs;
- box->space = sp;
- box->width = 0;
- box->len_chars = 0;
- box->ascent = sc_interp_get_ascent(scin);
- box->height = sc_interp_get_height(scin);
- box->filename = NULL;
- box->editable = editable;
- box->segs = NULL;
- box->n_segs = 0;
- bv_add(boxes, box);
-}
-
-
-static UNUSED char *swizzle(const char *inp, size_t len)
-{
- int i;
- char *out = malloc(len+1);
- strncpy(out, inp, len);
- out[len] = '\0';
- for ( i=0; i<len; i++ ) {
- if ( out[i] == '\n' ) out[i] = '`';
- }
- return out;
-}
-
-
-static UNUSED void debug_log_attrs(size_t len_chars, const char *text,
- PangoLogAttr *log_attrs)
-{
- int i;
- const gchar *p = text;
-
- if ( !g_utf8_validate(text, -1, NULL) ) {
- fprintf(stderr, "Invalid UTF8!\n");
- return;
- }
-
- for ( i=0; i<len_chars; i++ ) {
- gunichar c = g_utf8_get_char(p);
- p = g_utf8_next_char(p);
- if ( c == '\n' ) {
- printf("`");
- } else {
- printf("%lc", c);
- }
- }
- printf("\n");
- for ( i=0; i<=len_chars; i++ ) {
- if ( log_attrs[i].is_line_break ) {
- if ( log_attrs[i].is_mandatory_break ) {
- printf("n");
- } else {
- printf("b");
- }
- } else {
- printf(".");
- }
- }
- printf("\n");
-}
-
-
-static void add_seg(gpointer vi, gpointer vb)
-{
- PangoItem *item = vi;
- struct wrap_box *box = vb;
-
- box->segs[box->n_segs].analysis = item->analysis;
- box->segs[box->n_segs].glyphs = NULL;
- box->segs[box->n_segs].offs_char = item->offset;
- box->segs[box->n_segs].len_chars = item->num_chars;
- shape_segment(box, &box->segs[box->n_segs++]);
-}
-
-
-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)
-{
- struct wrap_box *box;
- const char *tp;
- double *col;
-
- while ( len==0 ) {
- add_nothing_box(boxes, bl, editable, space, scin, offs);
- return 0;
- }
-
- /* Create the box */
- box = calloc(1, sizeof(struct wrap_box));
- if ( box == NULL ) {
- fprintf(stderr, "Failed to allocate a text box.\n");
- return 1;
- }
-
- box->type = WRAP_BOX_PANGO;
- box->space = space;
- box->fontdesc = pango_font_description_copy(sc_interp_get_fontdesc(scin));
- box->width = 0;
- box->editable = editable;
- box->ascent = sc_interp_get_ascent(scin);
- box->height = sc_interp_get_height(scin);
-
- /* Link to the actual text */
- box->scblock = bl;
- tp = sc_block_contents(bl);
- box->offs_char = g_utf8_pointer_to_offset(tp, tp+offs);
- box->len_chars = g_utf8_strlen(tp+offs, len);
-
- col = sc_interp_get_fgcol(scin);
- box->col[0] = col[0]; /* Red */
- box->col[1] = col[1]; /* Green */
- box->col[2] = col[2]; /* Blue */
- box->col[3] = col[3]; /* Alpha */
-
- if ( itemize_and_shape(box, pc) == 0 ) {
- bv_add(boxes, box);
- } else {
- fprintf(stderr, "Shaping error!\n");
- return 1;
- }
-
- return 0;
-}
-
-
-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;
-
- box = calloc(1, sizeof(struct wrap_box));
- if ( box == NULL ) {
- fprintf(stderr, "Failed to allocate a callback box.\n");
- return;
- }
-
- box->type = WRAP_BOX_CALLBACK;
- box->scblock = NULL;
- box->offs_char = 0;
- box->space = WRAP_SPACE_NONE;
- box->width = pango_units_from_double(w);
- box->ascent = pango_units_from_double(h);
- box->height = pango_units_from_double(h);
- box->draw_func = draw_func;
- box->click_func = click_func;
- box->bvp = bvp;
- box->vp = vp;
- box->editable = 0;
- bv_add(boxes, box);
-}
-
-
-void add_image_box(struct boxvec *boxes, const char *filename,
- int w, int h, int editable)
-{
- struct wrap_box *box;
-
- box = calloc(1, sizeof(struct wrap_box));
- if ( box == NULL ) {
- fprintf(stderr, "Failed to allocate a callback box.\n");
- return;
- }
-
- box->type = WRAP_BOX_IMAGE;
- box->scblock = NULL;
- box->offs_char = 0;
- box->space = WRAP_SPACE_NONE;
- box->width = pango_units_from_double(w);
- box->ascent = pango_units_from_double(h);
- box->height = pango_units_from_double(h);
- box->filename = strdup(filename);
- box->editable = editable;
- bv_add(boxes, box);
-}
-
-
-int split_words(struct boxvec *boxes, PangoContext *pc, SCBlock *bl,
- PangoLanguage *lang, int editable, SCInterpreter *scin)
-{
- PangoLogAttr *log_attrs;
- glong len_chars, i;
- size_t len_bytes, start;
- int chars_done;
- const char *text = sc_block_contents(bl);
-
- /* Empty block? */
- if ( text == NULL ) return 1;
-
- len_chars = g_utf8_strlen(text, -1);
- if ( len_chars == 0 ) {
- add_text_box(boxes, WRAP_SPACE_NONE, pc, scin, bl,
- 0, 0, editable);
- return 1;
- }
-
- len_bytes = strlen(text);
-
- log_attrs = malloc((len_chars+1)*sizeof(PangoLogAttr));
- if ( log_attrs == NULL ) return 1;
-
- pango_get_log_attrs(text, len_bytes, -1, lang, log_attrs, len_chars+1);
-
- //debug_log_attrs(len_chars, text, log_attrs);
-
- start = 0;
- chars_done = 0;
- for ( i=0; i<len_chars; i++ ) {
-
- if ( log_attrs[i].is_line_break ) {
-
- enum wrap_box_space type;
- size_t len;
- char *ptr;
- size_t offs;
-
- ptr = g_utf8_offset_to_pointer(text, i);
- offs = ptr - text;
-
- /* Stuff up to (but not including) sc[i] forms a
- * wrap box */
- len = offs - start;
- if ( log_attrs[i].is_mandatory_break ) {
- type = WRAP_SPACE_EOP;
- if ( (i>0) && (g_utf8_prev_char(ptr)[0]=='\n') ) len--;
- } else if ( (i>0)
- && log_attrs[i-1].is_expandable_space ) {
- type = WRAP_SPACE_INTERWORD;
- len--;
- } else {
- type = WRAP_SPACE_NONE;
- }
-
- if ( add_text_box(boxes, type, pc, scin, bl,
- start, len, editable) ) {
- fprintf(stderr, "Failed to add wrap box.\n");
- }
- start = offs;
- chars_done = i;
-
- }
-
- }
-
- /* Add the stuff left over at the end */
- if ( i > chars_done ) {
-
- size_t l = strlen(text+start);
-
- if ( (text[start+l-1] == '\n') ) {
-
- /* There is a newline at the end of the SC */
- add_text_box(boxes, WRAP_SPACE_EOP, pc, scin, bl,
- start, l-1, editable);
-
- } else {
-
- add_text_box(boxes, WRAP_SPACE_NONE, pc, scin, bl,
- start, l, editable);
-
- }
-
- }
-
- free(log_attrs);
- return 0;
-}
diff --git a/src/shape.h b/src/shape.h
deleted file mode 100644
index f9e1758..0000000
--- a/src/shape.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * shape.h
- *
- * Copyright © 2014-2015 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 SHAPE_H
-#define SHAPE_H
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <pango/pangocairo.h>
-
-#include "wrap.h"
-
-extern void shape_box(struct wrap_box *box);
-
-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);
-
-extern void add_callback_box(struct boxvec *boxes, double w, double h,
- SCCallbackDrawFunc draw_func,
- SCCallbackClickFunc click_func,
- void *bvp, void *vp);
-
-#endif /* SHAPE_H */
diff --git a/src/slide_window.c b/src/slide_window.c
index 478deb5..b232e58 100644
--- a/src/slide_window.c
+++ b/src/slide_window.c
@@ -38,7 +38,6 @@
#include "render.h"
#include "frame.h"
#include "slideshow.h"
-#include "wrap.h"
#include "notes.h"
#include "pr_clock.h"
#include "sc_parse.h"
diff --git a/src/wrap.c b/src/wrap.c
deleted file mode 100644
index 6d0ea60..0000000
--- a/src/wrap.c
+++ /dev/null
@@ -1,1032 +0,0 @@
-/*
- * wrap.c
- *
- * Text wrapping, hyphenation, justification etc
- *
- * Copyright © 2013-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 <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pango/pangocairo.h>
-#include <math.h>
-#include <gdk/gdk.h>
-
-#include "sc_parse.h"
-#include "sc_interp.h"
-#include "wrap.h"
-#include "frame.h"
-#include "presentation.h"
-#include "boxvec.h"
-
-
-static void alloc_lines(struct frame *fr)
-{
- struct wrap_line *lines_new;
-
- lines_new = realloc(fr->lines, fr->max_lines * sizeof(struct wrap_line));
- if ( lines_new == NULL ) {
- fprintf(stderr, "Couldn't allocate memory for lines!\n");
- return;
- }
-
- fr->lines = lines_new;
-}
-
-
-void initialise_line(struct wrap_line *l)
-{
- l->width = 0;
- l->height = 0;
- l->ascent = 0;
- l->last_line = 0;
- l->overfull = 0;
- l->boxes = bv_new();
-}
-
-
-#if 0
-static struct wrap_line *get_cursor_line(struct frame *fr, size_t pos,
- double *yposd)
-{
- int line = 0;
- int i;
- int found = 0;
-
- *yposd = 0;
-
- for ( i=0; i<fr->n_lines; i++ ) {
- if ( fr->lines[i].sc_offset > pos ) {
- line = i-1;
- found = 1;
- break;
- }
- }
- if ( !found ) {
- /* Cursor is on the last line */
- line = fr->n_lines-1;
- }
- if ( line < 0 ) {
- printf("Couldn't find cursor.\n");
- return NULL;
- }
- for ( i=0; i<line; i++ ) {
- *yposd += fr->lines[i].height;
- }
-
- *yposd /= PANGO_SCALE;
- *yposd += fr->pad_t;
-
- return &fr->lines[line];
-}
-#endif
-
-
-int which_segment(struct wrap_box *box, int pos, int *err)
-{
- int i = 0;
- int ch = 0;
-
- if ( box->type != WRAP_BOX_PANGO ) {
- fprintf(stderr, "which_segment() called on wrong box type.\n");
- *err = 1;
- return 0;
- }
-
- do {
- if ( ch + box->segs[i].len_chars >= pos ) break;
- ch += box->segs[i++].len_chars;
- } while ( i < box->n_segs );
-
- if ( i == box->n_segs ) {
- fprintf(stderr, "Position not found in box!\n");
- *err = 1;
- return 0;
- }
-
- *err = 0;
- return i;
-}
-
-
-/* Return the horizontal position of "pos" within "box", in cairo units */
-static double text_box_index_to_x(struct wrap_box *box, int pos)
-{
- double x = 0.0;
- int nseg;
- struct text_seg *seg;
- const char *seg_text;
- const char *ep;
- int p;
- int i;
- int err;
- ptrdiff_t offs_p;
-
- nseg = which_segment(box, pos, &err);
- if ( err ) return 0.0;
-
- for ( i=0; i<nseg; i++ ) {
- PangoRectangle rect;
- pango_glyph_string_extents(box->segs[i].glyphs,
- box->font, NULL, &rect);
- x += rect.width;
- }
-
- /* We are in "seg" inside "box" */
- seg = &box->segs[nseg];
- seg_text = g_utf8_offset_to_pointer(sc_block_contents(box->scblock),
- box->offs_char + seg->offs_char);
- ep = g_utf8_offset_to_pointer(seg_text, seg->len_chars);
-
- /* Make character position relative to segment start (not box start) */
- pos -= seg->offs_char;
-
- /* Convert the character position to a byte offset */
- offs_p = g_utf8_offset_to_pointer(seg_text, pos) - seg_text;
-
- pango_glyph_string_index_to_x(seg->glyphs, (char *)seg_text,
- ep - seg_text, &seg->analysis,
- offs_p, FALSE, &p);
-
- return pango_units_to_double(x+p);
-}
-
-
-void get_cursor_pos(struct wrap_box *box, int pos,
- double *xposd, double *yposd, double *line_height)
-{
- *xposd = 0.0;
- *yposd = 0.0;
- *line_height = 20.0;
-
- if ( box == NULL ) return;
-
- *line_height = pango_units_to_double(box->height);
-
- if ( !box->editable ) {
- *xposd += pango_units_to_double(box->width);
- return;
- }
-
- switch ( box->type ) {
-
- case WRAP_BOX_PANGO :
- *xposd += text_box_index_to_x(box, pos);
- break;
-
- case WRAP_BOX_IMAGE :
- if ( pos > 0 ) {
- *xposd += pango_units_to_double(box->width);
- } /* else zero */
- break;
-
- case WRAP_BOX_CALLBACK :
- if ( pos > 0 ) {
- *xposd += pango_units_to_double(box->width);
- }
- break;
-
- case WRAP_BOX_NOTHING :
- case WRAP_BOX_SENTINEL :
- *xposd = 0.0;
- break;
-
- }
-}
-
-
-static int find_cursor_line(struct frame *fr, double yposd, int *end)
-{
- int i;
- double y = fr->pad_t;
-
- *end = 0;
-
- for ( i=0; i<fr->n_lines; i++ ) {
- double height = pango_units_to_double(fr->lines[i].height);
- if ( yposd < y + height ) {
- return i;
- }
- y += height;
- }
-
- *end = 1;
- return fr->n_lines-1;
-}
-
-
-static int find_cursor_box(struct frame *fr, struct wrap_line *l,
- double xposd, double *x_pos, int *end)
-{
- int i;
- double x = fr->pad_l;
-
- *end = 0;
-
- 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;
- }
- x += width;
- }
-
- *end = 1;
- *x_pos = x;
- return bv_len(l->boxes)-1;
-}
-
-
-void find_cursor(struct frame *fr, double xposd, double yposd,
- int *line, int *box, int *pos)
-{
- struct wrap_line *l;
- struct wrap_box *b;
- int end;
- double x_pos = 0.0;
- int idx, trail;
- int x_pos_i;
- size_t offs;
- int ln, bn;
- const char *block_text;
- const char *box_text;
-
- if ( fr->n_lines == 0 ) {
- *line = 0;
- *box = 0;
- *pos = 0;
- return;
- }
-
- ln = find_cursor_line(fr, yposd, &end);
- l = &fr->lines[ln];
- *line = ln;
-
- if ( end ) {
- bn = l->boxes->n_boxes-1;
- } else {
- bn = find_cursor_box(fr, l, xposd, &x_pos, &end);
- }
- b = bv_box(l->boxes, bn);
- *box = bn;
- if ( end ) {
- *pos = b->len_chars;
- return;
- }
-
- if ( !b->editable ) {
- *pos = 0;
- return;
- }
-
- switch ( b->type ) {
-
- case WRAP_BOX_NOTHING:
- case WRAP_BOX_SENTINEL:
- case WRAP_BOX_IMAGE:
- case WRAP_BOX_CALLBACK:
- offs = 0;
- break;
-
- case WRAP_BOX_PANGO:
- x_pos_i = pango_units_from_double(x_pos);
- if ( x_pos_i < b->width ) {
- block_text = sc_block_contents(b->scblock);
- box_text = g_utf8_offset_to_pointer(block_text,
- b->offs_char);
- printf("box text '%s'\n", box_text);
- /* cast because this function is not const-clean */
- /* FIXME: Assumes one segment per box! */
- pango_glyph_string_x_to_index(b->segs[0].glyphs,
- (char *)box_text,
- strlen(box_text),
- &b->segs[0].analysis,
- x_pos_i, &idx, &trail);
- offs = idx + trail;
- /* FIXME: Bug in Pango? */
- if ( offs > b->len_chars ) offs = b->len_chars;
- } else {
- offs = 0;
- };
- break;
-
- default:
- fprintf(stderr, "find_cursor(): box %i\n", b->type);
- offs = 0;
- break;
-
- }
-
- *pos = offs;
-}
-
-
-static void calc_line_geometry(struct wrap_line *line)
-{
- int i;
-
- line->width = 0;
- line->ascent = 0;
- line->height = 0;
-
- for ( i=0; i<line->boxes->n_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;
- line->width += box->sp;
- if ( box->height > line->height ) line->height = box->height;
- if ( box->ascent > line->ascent ) line->ascent = box->ascent;
-
- }
-
- line->height *= 1.07;
-}
-
-
-/* Normal width of space */
-static double sp_x(enum wrap_box_space s)
-{
- switch ( s ) {
-
- case WRAP_SPACE_INTERWORD :
- return 10.0*PANGO_SCALE;
-
- case WRAP_SPACE_EOP :
- return 0.0;
-
- default:
- case WRAP_SPACE_NONE :
- return 0.0;
-
- }
-}
-
-
-/* Stretchability of space */
-static double sp_y(enum wrap_box_space s)
-{
- switch ( s ) {
-
- case WRAP_SPACE_INTERWORD :
- return 10.0*PANGO_SCALE;
-
- case WRAP_SPACE_EOP :
- return INFINITY;
-
- default:
- case WRAP_SPACE_NONE :
- return 0.0;
-
- }
-}
-
-
-/* Shrinkability of space */
-static double sp_z(enum wrap_box_space s)
-{
- switch ( s ) {
-
- case WRAP_SPACE_INTERWORD :
- return 7.0*PANGO_SCALE;
-
- case WRAP_SPACE_EOP :
- return 0.0;
-
- default:
- case WRAP_SPACE_NONE :
- return 0.0;
-
- }
-}
-
-
-/* Minimum width of space */
-static double sp_zp(enum wrap_box_space s)
-{
- return sp_x(s) - sp_z(s);
-}
-
-
-/* Maximum width of space */
-static double sp_yp(enum wrap_box_space s, double rho)
-{
- return sp_x(s) + rho*sp_y(s);
-}
-
-
-static void consider_break(double sigma_prime, double sigma_prime_max,
- double sigma_prime_min, double line_length,
- double *s, int j, double *dprime, int *jprime,
- double rho)
-{
- double r;
- double d;
-
- if ( sigma_prime < line_length ) {
- r = rho*(line_length - sigma_prime)
- / (sigma_prime_max - sigma_prime);
- } else if ( sigma_prime > line_length ) {
- r = rho*(line_length - sigma_prime)
- / (sigma_prime - sigma_prime_min);
- } else {
- r = 0.0;
- }
-
- d = s[j] + pow(1.0 + 100.0 * pow(abs(r),3.0), 2.0);
- if ( d < *dprime ) {
- *dprime = d;
- *jprime = j;
- }
-}
-
-
-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 bv_box(boxes, i-1)->width;
-}
-
-
-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 bv_box(boxes, i-1)->space;
-}
-
-
-static void UNUSED distribute_spaces(struct wrap_line *line, double l,
- double rho)
-{
- int i;
- double L, Y, Z, r;
- int overfull = 0;
- int underfull = 0;
-
- l = pango_units_from_double(l);
-
- L = 0.0; Y = 0.0; Z = 0.0;
- 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 += bv_last(line->boxes)->width;
-
- if ( L < l ) {
- r = (l - L)/Y;
- } else if ( L > l ) {
- r = (l - L)/Z;
- } else {
- r = 0.0;
- }
-
- if ( r >= 0.0 ) {
- 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; 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);
- }
- }
-
- 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 boxvec *boxes)
-{
- struct wrap_line *l;
- int j;
-
- l = &fr->lines[fr->n_lines];
- fr->n_lines++;
- initialise_line(l);
-
- bv_ensure_space(l->boxes, s-q);
- for ( j=q; j<s; j++ ) {
- bv_add(l->boxes, bv_box(boxes, j));
- }
-}
-
-
-static void output(int a, int i, int *p, struct frame *fr, struct boxvec *boxes)
-{
- int q = i;
- int r;
- int s = 0;
-
- if ( fr->n_lines + (i-a) + 1 > fr->max_lines ) {
- fr->max_lines += 32;
- alloc_lines(fr);
- if ( fr->n_lines == fr->max_lines ) return;
- }
-
- while ( q != a ) {
- r = p[q];
- p[q] = s;
- s = q;
- q = r;
- }
-
- while ( q != i ) {
-
- output_line(q, s, fr, boxes);
-
- q = s;
- s = p[q];
-
- }
-
-}
-
-
-/* This is the "suboptimal fit" algorithm from Knuth and Plass, Software -
- * 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 boxvec *boxes,
- double line_length, struct frame *fr,
- double rho)
-{
- int a = 0;
- int *p;
- double *s;
- struct wrap_box *box;
- int j;
- double sigma_prime, sigma_max_prime, sigma_min_prime;
- double dprime;
- int n;
- int reject;
-
- n = boxes->n_boxes;
-
- /* Set the space for the last box to be "end of paragraph" */
- bv_last(boxes)->space = WRAP_SPACE_EOP;
-
- /* Add empty zero-width box at end */
- box = malloc(sizeof(struct wrap_box));
- if ( box== NULL ) {
- fprintf(stderr, "Couldn't allocate sentinel box\n");
- return;
- }
- box->type = WRAP_BOX_SENTINEL;
- box->space = WRAP_SPACE_NONE;
- box->font = NULL;
- box->width = 0;
- box->ascent = 0;
- box->height = 0;
- box->editable = 1;
- box->scblock = NULL;
- box->offs_char = 0;
- bv_add(boxes, box);
-
- line_length *= PANGO_SCALE;
-
- reject = 0;
- 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,
- bv_box(boxes, j)->width, line_length);
- fr->trouble = 1;
- reject = 1;
- }
- }
- if ( reject ) return;
-
- p = malloc((n+2) * sizeof(int)); /* p[0]..p[n+1] inclusive */
- if ( p == NULL ) {
- fprintf(stderr, "Failed to allocate p_k\n");
- return;
- }
-
- s = malloc((n+2) * sizeof(double)); /* s[0]..s[n+1] inclusive */
- if ( s == NULL ) {
- fprintf(stderr, "Failed to allocate s_k\n");
- return;
- }
-
- do {
-
- int i = a;
- int k = i+1;
- double sigma = width(boxes, k);
- double sigma_min = sigma;
- double sigma_max = sigma;
- int m = 1;
- int jprime = 999;
-
- s[i] = 0;
-
- do {
-
- while ( sigma_min > line_length ) {
-
- /* Begin <advance i by 1> */
- if ( s[i] < INFINITY ) m--;
- i++;
- sigma -= width(boxes, i);
- sigma -= sp_z(space(boxes, i));
-
- sigma_max -= width(boxes, i);
- sigma_max -= sp_yp(space(boxes, i), rho);
-
- sigma_min -= width(boxes, i);
- sigma_min -= sp_zp(space(boxes, i));
- /* End */
-
- }
-
- /* Begin <examine all feasible lines ending at k> */
- j = i;
- sigma_prime = sigma;
- sigma_max_prime = sigma_max;
- sigma_min_prime = sigma_min;
- dprime = INFINITY;
- while ( sigma_max_prime >= line_length ) {
- if ( s[j] < INFINITY ) {
- consider_break(sigma_prime,
- sigma_max_prime,
- sigma_min_prime,
- line_length, s, j,
- &dprime, &jprime,
- rho);
- }
- j++;
- sigma_prime -= width(boxes, j);
- sigma_prime -= sp_x(space(boxes, j));
-
- sigma_max_prime -= width(boxes, j);
- sigma_max_prime -= sp_yp(space(boxes, j),
- rho);
-
- sigma_min_prime -= width(boxes, j);
- sigma_min_prime -= sp_zp(space(boxes, j));
- }
- /* End */
-
- s[k] = dprime;
- if ( dprime < INFINITY ) {
- m++;
- p[k] = jprime;
- }
- if ( (m == 0) || (k > n) ) break;
- sigma += width(boxes, k+1);
- sigma += sp_x(space(boxes, k));
-
- sigma_max += width(boxes, k+1);
- sigma_max += sp_yp(space(boxes, k), rho);
-
- sigma_min += width(boxes, k+1);
- sigma_min += sp_zp(space(boxes, k));
- k++;
-
- } while ( 1 );
-
- if ( k > n ) {
- output(a, n+1, p, fr, boxes);
- break;
- } else {
-
- /* Begin <try hyphenation> */
- do {
-
- sigma += width(boxes, i);
- sigma += sp_x(space(boxes, i));
-
- sigma_max += width(boxes, i);
- sigma_max += sp_yp(space(boxes, i), rho);
-
- sigma_min += width(boxes, i);
- sigma_min += sp_zp(space(boxes, i));
- i--;
-
- } while ( s[i] >= INFINITY );
- output(a, i, p, fr, boxes);
-
- /* Begin <split box k at the best place> */
- jprime = 0;
- dprime = INFINITY;
- /* Test hyphenation points here */
- /* End */
-
- /* Begin <output and adjust w_k> */
- output_line(i, k-1, fr, boxes);
- /* End */
-
- /* End */
-
- a = k-1;
-
- }
-
- } while ( 1 );
-
- fr->lines[fr->n_lines-1].last_line = 1;
-
- free(p);
- free(s);
- free(box); /* The sentinel box */
-}
-
-
-static struct wrap_line *new_line(struct frame *fr)
-{
- struct wrap_line *l;
-
- if ( fr->n_lines + 1 > fr->max_lines ) {
- fr->max_lines += 32;
- alloc_lines(fr);
- if ( fr->n_lines == fr->max_lines ) return NULL;
- }
-
- l = &fr->lines[fr->n_lines];
- fr->n_lines++;
- initialise_line(l);
- return l;
-}
-
-
-static void first_fit(struct boxvec *boxes, double line_length,
- struct frame *fr)
-{
- struct wrap_line *line;
- double len;
- int j = 0;
-
- line_length *= PANGO_SCALE;
-
- line = new_line(fr);
- len = 0.0;
-
- do {
-
- bv_box(boxes, j)->sp = sp_x(bv_box(boxes, j)->space);
-
- len += bv_box(boxes, j)->width;
-
- if ( len > line_length ) {
- line = new_line(fr);
- len = bv_box(boxes, j)->width;
- }
- bv_add(line->boxes, bv_box(boxes, j));
- j++;
-
- if ( (j > 0) && (bv_box(boxes, j-1)->type != WRAP_BOX_SENTINEL) )
- {
- len += sp_x(bv_box(boxes, j-1)->space);
- }
-
- } while ( j < boxes->n_boxes );
-
- fr->lines[fr->n_lines-1].last_line = 1;
-}
-
-
-void wrap_line_free(struct wrap_line *l)
-{
- bv_free(l->boxes);
-}
-
-
-static struct boxvec *split_paragraph(struct boxvec *boxes, int *n, int *eop)
-{
- int i;
- int start = *n;
- int end;
-
- if ( start >= bv_len(boxes) ) return NULL;
-
- *eop = 0;
- 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 == bv_len(boxes) ) end--;
-
- if ( end-start > 0 ) {
- struct boxvec *para = bv_new();
- bv_ensure_space(para, end-start);
- for ( i=start; i<end; i++ ) {
- bv_add(para, bv_box(boxes, i));
- }
- return para;
- }
-
- return NULL;
-}
-
-
-void show_boxes(struct boxvec *boxes)
-{
- int i;
-
- if ( boxes == NULL ) {
- printf("Empty line.\n");
- return;
- }
-
- 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 ) {
- const char *block_text = sc_block_contents(box->scblock);
- box_text = g_utf8_offset_to_pointer(block_text,
- box->offs_char);
- } else if ( box->type == WRAP_BOX_IMAGE ) {
- box_text = box->filename;
- } else {
- box_text = NULL;
- }
- printf(" t=%i s=%i %10i %5i %8.2f '%s'\n",
- box->type, box->space, box->width, box->offs_char,
- box->sp, box_text);
- }
-}
-
-
-static int wrap_everything(struct frame *fr, double wrap_w)
-{
- int i;
-
- fr->paragraph_start_lines = malloc(fr->n_paragraphs*sizeof(int));
- if ( fr->paragraph_start_lines == NULL ) {
- fprintf(stderr, "Failed to allocate paragraph start lines\n");
- return 1;
- }
-
- /* Split paragraphs into lines */
- fr->paragraph_start_lines[0] = 0;
- for ( i=0; i<fr->n_paragraphs; i++ ) {
-
- //int n;
-
- /* Choose wrapping algorithm here */
- //knuth_suboptimal_fit(para, wrap_w, fr, rho);
- first_fit(fr->paragraphs[i], wrap_w, fr);
-
- //fr->paragraph_start_lines = n;
-
- }
-
- return 0;
-}
-
-
-/* Wrap the StoryCode inside "fr->sc" so that it fits within width "fr->w",
- * and generate fr->lines */
-int wrap_contents(struct frame *fr)
-{
- struct boxvec *para;
- int i, eop = 0;
- //const double rho = 2.0;
- const double wrap_w = fr->w - fr->pad_l - fr->pad_r;
- int max_para = 64;
-
- /* Clear lines */
- fr->n_lines = 0;
- fr->max_lines = 32;
- fr->lines = NULL;
- fr->trouble = 0;
- alloc_lines(fr);
-
- for ( i=0; i<fr->n_paragraphs; i++ ) {
- bv_free(fr->paragraphs[i]);
- }
- free(fr->paragraphs);
- free(fr->paragraph_start_lines);
- for ( i=0; i<fr->n_lines; i++ ) {
- wrap_line_free(&fr->lines[i]);
- }
-
- /* Split text into paragraphs */
- i = 0;
- fr->n_paragraphs = 0;
- fr->paragraphs = malloc(max_para * sizeof(struct boxvec *));
- if ( fr->paragraphs == NULL ) {
- fprintf(stderr, "Failed to allocate paragraphs\n");
- return 1;
- }
- do {
- para = split_paragraph(fr->boxes, &i, &eop);
- if ( para != NULL ) {
- fr->paragraphs[fr->n_paragraphs++] = para;
- }
- if ( fr->n_paragraphs == max_para ) {
- max_para += 64;
- fr->paragraphs = realloc(fr->paragraphs,
- max_para*sizeof(struct boxvec *));
- if ( fr->paragraphs == NULL ) {
- fprintf(stderr, "Failed to allocate space"
- " for paragraphs\n");
- return 1;
- }
- }
- } while ( para != NULL );
-
- if ( fr->n_paragraphs > 0 ) {
- if ( wrap_everything(fr, wrap_w) ) return 1;
- } else {
- fr->paragraph_start_lines = NULL;
- return 0;
- }
-
- for ( i=0; i<fr->n_lines; i++ ) {
-
- struct wrap_line *line = &fr->lines[i];
-
- //distribute_spaces(line, wrap_w, rho);
-
- /* Strip any sentinel boxes added by the wrapping algorithm */
- if ( (bv_last(line->boxes) != NULL)
- && (bv_last(line->boxes)->type == WRAP_BOX_SENTINEL) )
- {
- line->boxes->n_boxes--;
- }
-
- }
-
- for ( i=0; i<fr->n_lines; i++ ) {
- calc_line_geometry(&fr->lines[i]);
- }
-
- return 0;
-}
-
-
-double total_height(struct frame *fr)
-{
- int i;
- double tot = 0.0;
-
- if ( fr == NULL ) return 0.0;
-
- for ( i=0; i<fr->n_lines; i++ ) {
- tot += fr->lines[i].height;
- }
-
- return pango_units_to_double(tot);
-}
-
-
-/* Insert a new box, which will be at position 'pos' */
-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;
- }
-
- /* Shuffle the boxes along */
- for ( i=l->n_boxes; i>pos+1; i-- ) {
- l->boxes[i] = l->boxes[i-1];
- }
-
- l->n_boxes++;
-#endif
-return 1;
-
- return 0;
-}
diff --git a/src/wrap.h b/src/wrap.h
deleted file mode 100644
index f3df4e4..0000000
--- a/src/wrap.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * wrap.h
- *
- * Text wrapping, hyphenation, justification and shaping
- *
- * Copyright © 2014-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 WRAP_H
-#define WRAP_H
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "frame.h"
-#include "sc_interp.h"
-#include "presentation.h"
-
-
-enum wrap_box_type
-{
- WRAP_BOX_NOTHING,
- WRAP_BOX_SENTINEL,
- WRAP_BOX_PANGO,
- WRAP_BOX_IMAGE,
- WRAP_BOX_CALLBACK
-};
-
-
-/* Possible types of space following a wrap box */
-enum wrap_box_space
-{
- WRAP_SPACE_INTERWORD, /* Normal inter-word space */
- WRAP_SPACE_NONE, /* Box ends with an explicit hyphen or an SC
- * block boundary */
- WRAP_SPACE_EOP /* End of paragraph */
- /* TODO: Space between sentences etc */
-};
-
-
-struct text_seg
-{
- PangoGlyphString *glyphs;
- PangoAnalysis analysis;
-
- /* Offset of this text segment into the wrap box */
- int offs_char;
- int len_chars;
-
- /* Pango units */
- int width;
- int height;
- int ascent;
-};
-
-
-/* A wrap box is a run of content - could be text, an image or so one - that is
- * one logical unit as far as Colloquium is concerned. It might consist of
- * multiple units, for example, in Pango's mind. */
-struct wrap_box
-{
- enum wrap_box_type type;
- int editable;
-
- SCBlock *scblock;
- int offs_char; /* offset (in characters, not bytes) into scblock */
-
- /* Pango units */
- int width;
- int height;
- int ascent;
-
- enum wrap_box_space space; /* Type of "space" following box */
- double sp; /* Calculated space (Pango units) after box */
-
- /* For type == WRAP_BOX_PANGO */
- PangoFont *font;
- PangoFontDescription *fontdesc;
- double col[4]; /* rgba colour */
- int len_chars;
- int n_segs;
- struct text_seg *segs;
-
- /* For type == WRAP_BOX_IMAGE */
- char *filename;
-
- /* For type == WRAP_BOX_CALLBACK */
- SCCallbackDrawFunc draw_func;
- SCCallbackClickFunc click_func;
- void *bvp;
- void *vp;
-};
-
-
-/* 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 overfull;
- int underfull;
- int last_line;
-};
-
-extern int wrap_contents(struct frame *fr);
-
-extern void get_cursor_pos(struct wrap_box *box, int pos,
- double *xposd, double *yposd, double *line_height);
-
-extern void find_cursor(struct frame *fr, double xposd, double yposd,
- int *line, int *box, int *pos);
-
-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 boxvec *boxes);
-extern double total_height(struct frame *fr);
-
-extern int insert_box(struct wrap_line *l, int pos);
-extern int which_segment(struct wrap_box *box, int pos, int *err);
-
-#endif /* WRAP_H */