aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.org.uk>2014-06-05 09:22:13 +0200
committerThomas White <taw@bitwiz.org.uk>2014-06-05 09:22:13 +0200
commitceaa1b1f22ef86c5a592876c31e83cd04869b9ed (patch)
treee62016f5c66ea468358c7e1b5758cce2bcccee87
parent968e739012ca64e6be74074816f96f5b1d487422 (diff)
Cursor stuff
-rw-r--r--src/mainwindow.c114
-rw-r--r--src/sc_interp.c5
-rw-r--r--src/sc_parse.c6
-rw-r--r--src/sc_parse.h2
-rw-r--r--src/shape.c30
-rw-r--r--src/shape.h6
-rw-r--r--src/wrap.c83
-rw-r--r--src/wrap.h9
8 files changed, 147 insertions, 108 deletions
diff --git a/src/mainwindow.c b/src/mainwindow.c
index 4706e15..ef89e8c 100644
--- a/src/mainwindow.c
+++ b/src/mainwindow.c
@@ -1125,40 +1125,30 @@ static void insert_text(struct frame *fr, char *t, struct presentation *p)
static void do_backspace(struct frame *fr, struct presentation *p)
{
- int nln, nbx;
- size_t pos;
- struct wrap_box *box;
- glong ptr;
+ int sln, sbx, sps;
if ( fr == NULL ) return;
/* If this is, say, the top level frame, do nothing */
if ( fr->boxes == NULL ) return;
- nln = p->cursor_line;
- nbx = p->cursor_box;
- pos = p->cursor_pos;
-
- if ( pos == 0 ) {
- if ( nbx == 0 ) {
- if ( nln == 0 ) return;
- nln--;
- nbx = fr->lines[nln].n_boxes-1; /* The last box */
- } else {
- nbx--;
- }
- pos = strlen(fr->lines[nln].boxes[nbx].text)-1;
- }
+ printf("Old: frame %p, line %i, box %i, pos %li\n",
+ p->cursor_frame, p->cursor_line, p->cursor_box, p->cursor_pos);
+ sln = p->cursor_line;
+ sbx = p->cursor_box;
+ sps = p->cursor_pos;
- box = &fr->lines[nln].boxes[nbx];
+ move_cursor_back(p);
- p->cursor_line = nln;
- p->cursor_box = nbx;
- p->cursor_pos = pos;
+ printf("New: frame %p, line %i, box %i, pos %li\n",
+ p->cursor_frame, p->cursor_line, p->cursor_box, p->cursor_pos);
- ptr = g_utf8_pointer_to_offset(box->text, box->text+pos);
+ /* Delete may cross wrap boxes and maybe SCBlock boundaries */
+ struct wrap_box *sbox = &p->cursor_frame->lines[sln].boxes[sbx];
+ struct wrap_line *fline = &p->cursor_frame->lines[p->cursor_line];
+ struct wrap_box *fbox = &fline->boxes[p->cursor_box];
+ sc_delete_text(fbox->scblock, p->cursor_pos, sbox->scblock, sps);
-// reshape_box(box);
rerender_slide(p);
redraw_editor(p);
}
@@ -1610,29 +1600,30 @@ static gboolean button_release_sig(GtkWidget *da, GdkEventButton *event,
}
-
static void move_cursor(struct presentation *p, signed int x, signed int y)
{
- struct wrap_line *line = &p->cursor_frame->lines[p->cursor_line];
- struct wrap_box *box = &line->boxes[p->cursor_box];
- signed int cp, cb, cl;
-
- cp = p->cursor_pos;
- cb = p->cursor_box;
- cl = p->cursor_line;
-
if ( x > 0 ) {
int advance = 0;
+ signed int cp, cb, cl;
+ struct wrap_line *line = &p->cursor_frame->lines[p->cursor_line];
+ struct wrap_box *box = &line->boxes[p->cursor_box];
+
+ cp = p->cursor_pos;
+ cb = p->cursor_box;
+ cl = p->cursor_line;
if ( box->type == WRAP_BOX_PANGO ) {
char *np;
- np = g_utf8_find_next_char(box->text+cp, NULL);
- if ( np == box->text+cp ) {
+ const char *box_text;
+ box_text = sc_block_contents(box->scblock) + box->offs;
+ np = g_utf8_offset_to_pointer(box_text, cp);
+ np = g_utf8_find_next_char(np, NULL);
+ if ( np > box_text+box->len_bytes ) {
advance = 1;
} else {
- cp = np - box->text;
+ cp = np - box_text;
}
} else {
@@ -1669,57 +1660,8 @@ static void move_cursor(struct presentation *p, signed int x, signed int y)
p->cursor_pos = cp;
} else {
-
- int retreat = 0;
-
- if ( box->type == WRAP_BOX_PANGO ) {
-
- char *np;
- np = g_utf8_find_prev_char(box->text, box->text+cp);
- if ( np == NULL ) {
- retreat = 1;
- } else {
- cp = np - box->text;
- }
-
- } else {
- cp--;
- if ( cp < 0 ) retreat = 1;
- }
-
- if ( retreat ) {
-
- do {
-
- cb--;
-
- if ( cb < 0 ) {
- cl--;
- if ( cl < 0 ) return;
- p->cursor_line = cl;
- line = &p->cursor_frame->lines[cl];
- cb = line->n_boxes - 1;
- }
-
- } while ( (line->boxes[cb].type == WRAP_BOX_SENTINEL)
- || (line->boxes[cb].type == WRAP_BOX_NOTHING)
- || !line->boxes[cb].editable );
-
- p->cursor_box = cb;
- box = &line->boxes[cb];
- if ( box->type == WRAP_BOX_PANGO ) {
- cp = strlen(box->text);
- } else {
- cp = 1;
- }
-
- }
- p->cursor_pos = cp;
-
+ move_cursor_back(p);
}
-
- printf("Cursor at frame %p, line %i, box %i, pos %li\n",
- p->cursor_frame, p->cursor_line, p->cursor_box, p->cursor_pos);
}
diff --git a/src/sc_interp.c b/src/sc_interp.c
index a868a73..7dbe5f4 100644
--- a/src/sc_interp.c
+++ b/src/sc_interp.c
@@ -512,7 +512,7 @@ static int check_outputs(SCBlock *bl, SCInterpreter *scin)
if ( name == NULL ) {
split_words(sc_interp_get_frame(scin)->boxes,
- scin->pc, contents, scin->lang, 1,
+ scin->pc, bl, contents, scin->lang, 1,
scin);
} else if ( strcmp(name, "bgcol") == 0 ) {
@@ -541,7 +541,8 @@ static int check_outputs(SCBlock *bl, SCInterpreter *scin)
snprintf(tmp, 63, "%i",
scin->s_constants->slide_number);
split_words(sc_interp_get_frame(scin)->boxes,
- scin->pc, tmp, scin->lang, 0, scin);
+ scin->pc, bl, tmp, scin->lang, 0,
+ scin);
}
} else {
printf("No slide constants.\n");
diff --git a/src/sc_parse.c b/src/sc_parse.c
index aeb9ea9..71dd449 100644
--- a/src/sc_parse.c
+++ b/src/sc_parse.c
@@ -376,3 +376,9 @@ SCBlock *sc_parse(const char *sc)
return blf;
}
+
+
+void sc_delete_text(SCBlock *b1, int p1, SCBlock *b2, int p2)
+{
+ printf("Deleting from %p/%i to %p/%i\n", b1, p1, b2, p2);
+}
diff --git a/src/sc_parse.h b/src/sc_parse.h
index b5d2c5c..020c345 100644
--- a/src/sc_parse.h
+++ b/src/sc_parse.h
@@ -42,6 +42,8 @@ extern const char *sc_block_contents(const SCBlock *bl);
extern struct frame *sc_block_frame(const SCBlock *bl);
extern void sc_block_set_frame(SCBlock *bl, struct frame *fr);
+extern void sc_delete_text(SCBlock *b1, int p1, SCBlock *b2, int p2);
+
extern void show_sc_blocks(const SCBlock *bl);
extern void show_sc_block(const SCBlock *bl, const char *prefix);
diff --git a/src/shape.c b/src/shape.c
index 4c20812..6078b55 100644
--- a/src/shape.c
+++ b/src/shape.c
@@ -42,6 +42,8 @@ struct box_adding_stuff
int editable;
char *text;
enum wrap_box_space space;
+ SCBlock *bl;
+ size_t offs;
};
@@ -61,13 +63,15 @@ static void add_wrap_box(gpointer vi, gpointer vb)
box = &bas->line->boxes[bas->line->n_boxes];
box->type = WRAP_BOX_PANGO;
- box->text = bas->text;
box->space = bas->space;
box->font = sc_interp_get_font(bas->scin);
box->width = 0;
box->editable = bas->editable;
box->ascent = sc_interp_get_ascent(bas->scin);
box->height = sc_interp_get_height(bas->scin);
+ box->scblock = bas->bl;
+ box->offs = bas->offs + item->offset;
+ box->len_bytes = item->length;
col = sc_interp_get_fgcol(bas->scin);
box->col[0] = col[0]; /* Red */
box->col[1] = col[1]; /* Green */
@@ -96,7 +100,8 @@ static void add_wrap_box(gpointer vi, gpointer vb)
/* Add "text", followed by a space of type "space", to "line" */
static int add_wrap_boxes(struct wrap_line *line, char *text,
enum wrap_box_space space, PangoContext *pc,
- SCInterpreter *scin, int editable)
+ SCInterpreter *scin, SCBlock *bl, size_t offs,
+ int editable)
{
GList *pango_items;
PangoAttrList *attrs;
@@ -113,6 +118,8 @@ static int add_wrap_boxes(struct wrap_line *line, char *text,
bas.editable = editable;
bas.text = text;
bas.space = space;
+ bas.bl = bl;
+ bas.offs = offs;
g_list_foreach(pango_items, add_wrap_box, &bas);
g_list_free(pango_items);
@@ -129,7 +136,8 @@ void add_image_box(struct wrap_line *line, const char *filename,
box = &line->boxes[line->n_boxes];
box->type = WRAP_BOX_IMAGE;
- box->text = NULL;
+ box->scblock = NULL;
+ box->offs = 0;
box->space = WRAP_SPACE_NONE;
box->width = pango_units_from_double(w);
box->ascent = pango_units_from_double(h);
@@ -140,8 +148,9 @@ void add_image_box(struct wrap_line *line, const char *filename,
}
-int split_words(struct wrap_line *boxes, PangoContext *pc, const char *text,
- PangoLanguage *lang, int editable, SCInterpreter *scin)
+int split_words(struct wrap_line *boxes, PangoContext *pc, SCBlock *bl,
+ const char *text, PangoLanguage *lang, int editable,
+ SCInterpreter *scin)
{
PangoLogAttr *log_attrs;
glong len_chars, i;
@@ -198,7 +207,7 @@ int split_words(struct wrap_line *boxes, PangoContext *pc, const char *text,
}
if ( add_wrap_boxes(boxes, word, type,
- pc, scin, editable) ) {
+ pc, scin, bl, start, editable) ) {
fprintf(stderr, "Failed to add wrap box.\n");
}
start = offs;
@@ -226,14 +235,17 @@ int split_words(struct wrap_line *boxes, PangoContext *pc, const char *text,
word2 = strndup(word, l-1);
add_wrap_boxes(boxes, word2,
- WRAP_SPACE_EOP, pc, scin, editable);
+ WRAP_SPACE_EOP, pc, scin, bl, start,
+ editable);
add_wrap_boxes(boxes, strdup(""),
- WRAP_SPACE_NONE, pc, scin, editable);
+ WRAP_SPACE_NONE, pc, scin, bl, start,
+ editable);
} else {
add_wrap_boxes(boxes, word,
- WRAP_SPACE_NONE, pc, scin, editable);
+ WRAP_SPACE_NONE, pc, scin, bl, start,
+ editable);
}
diff --git a/src/shape.h b/src/shape.h
index bdc5775..43356e0 100644
--- a/src/shape.h
+++ b/src/shape.h
@@ -32,10 +32,12 @@
#include "wrap.h"
extern int split_words(struct wrap_line *boxes, PangoContext *pc,
- const char *text, PangoLanguage *lang, int editable,
- SCInterpreter *scin);
+ SCBlock *bl, const char *text, PangoLanguage *lang,
+ int editable, SCInterpreter *scin);
extern void add_image_box(struct wrap_line *line, const char *filename,
int w, int h, int editable);
+extern void reshape_box(struct wrap_box *box);
+
#endif /* SHAPE_H */
diff --git a/src/wrap.c b/src/wrap.c
index 2b680ed..f356a75 100644
--- a/src/wrap.c
+++ b/src/wrap.c
@@ -123,6 +123,7 @@ void get_cursor_pos(struct wrap_box *box, size_t pos,
double *xposd, double *yposd, double *line_height)
{
int p;
+ const char *box_text;
*xposd = 0.0;
*yposd = 0.0;
@@ -140,8 +141,10 @@ void get_cursor_pos(struct wrap_box *box, size_t pos,
switch ( box->type ) {
case WRAP_BOX_PANGO :
- pango_glyph_string_index_to_x(box->glyphs, box->text,
- strlen(box->text),
+ box_text = sc_block_contents(box->scblock) + box->offs;
+ pango_glyph_string_index_to_x(box->glyphs,
+ box_text,
+ box->len_bytes,
&box->item->analysis, pos,
FALSE, &p);
*xposd += pango_units_to_double(p);
@@ -157,6 +160,70 @@ void get_cursor_pos(struct wrap_box *box, size_t pos,
}
+void move_cursor_back(struct presentation *p)
+{
+ int retreat = 0;
+ signed int cp, cb, cl;
+ struct wrap_line *line = &p->cursor_frame->lines[p->cursor_line];
+ struct wrap_box *box = &line->boxes[p->cursor_box];
+
+ cp = p->cursor_pos;
+ cb = p->cursor_box;
+ cl = p->cursor_line;
+
+ if ( box->type == WRAP_BOX_PANGO ) {
+
+ char *np;
+ const char *box_text;
+ box_text = sc_block_contents(box->scblock) + box->offs;
+ np = g_utf8_offset_to_pointer(box_text, cp);
+ np = g_utf8_find_prev_char(box_text, np);
+ if ( np == NULL ) {
+ retreat = 1;
+ } else {
+ cp = np - box_text;
+ }
+
+ } else {
+ cp--;
+ if ( cp < 0 ) retreat = 1;
+ }
+
+ if ( retreat ) {
+
+ const char *box_text;
+
+ do {
+
+ cb--;
+
+ if ( cb < 0 ) {
+ cl--;
+ if ( cl < 0 ) return;
+ p->cursor_line = cl;
+ line = &p->cursor_frame->lines[cl];
+ cb = line->n_boxes - 1;
+ }
+
+ } while ( (line->boxes[cb].type == WRAP_BOX_SENTINEL)
+ || (line->boxes[cb].type == WRAP_BOX_NOTHING)
+ || !line->boxes[cb].editable );
+
+ p->cursor_box = cb;
+ box = &line->boxes[cb];
+ box_text = sc_block_contents(box->scblock) + box->offs;
+ if ( box->type == WRAP_BOX_PANGO ) {
+ cp = g_utf8_pointer_to_offset(box_text,
+ box_text+box->len_bytes);
+ } else {
+ cp = 1;
+ }
+
+ }
+ p->cursor_pos = cp;
+}
+
+
static int find_cursor_line(struct frame *fr, double yposd, int *end)
{
int i;
@@ -212,6 +279,7 @@ void find_cursor(struct frame *fr, double xposd, double yposd,
int x_pos_i;
size_t offs;
int ln, bn;
+ const char *box_text;
if ( fr->n_lines == 0 ) {
*line = 0;
@@ -245,12 +313,14 @@ void find_cursor(struct frame *fr, double xposd, double yposd,
case WRAP_BOX_PANGO :
x_pos_i = pango_units_from_double(x_pos);
- pango_glyph_string_x_to_index(b->glyphs, b->text,
- strlen(b->text),
+ box_text = sc_block_contents(b->scblock) + b->offs;
+ pango_glyph_string_x_to_index(b->glyphs, box_text,
+ b->len_bytes,
&b->item->analysis,
x_pos_i, &idx, &trail);
/* FIXME: Assumes 1 byte char */
offs = idx + trail;
+ break;
case WRAP_BOX_SENTINEL :
offs = 0;
@@ -522,13 +592,14 @@ static void knuth_suboptimal_fit(struct wrap_line *boxes, double line_length,
}
box = &boxes->boxes[boxes->n_boxes];
box->type = WRAP_BOX_SENTINEL;
- box->text = NULL;
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 = 0;
boxes->n_boxes++;
line_length *= PANGO_SCALE;
@@ -689,7 +760,6 @@ void wrap_line_free(struct wrap_line *l)
case WRAP_BOX_PANGO :
pango_glyph_string_free(l->boxes[i].glyphs);
pango_item_free(l->boxes[i].item);
- free(l->boxes[i].text);
break;
case WRAP_BOX_IMAGE :
@@ -752,7 +822,6 @@ void show_boxes(struct wrap_line *boxes)
for ( i=0; i<boxes->n_boxes; i++ ) {
printf("%3i", i);
- printf(" '%s'", boxes->boxes[i].text);
printf(" t=%i s=%i %i %5.2f\n",
boxes->boxes[i].type, boxes->boxes[i].space,
boxes->boxes[i].width, boxes->boxes[i].sp);
diff --git a/src/wrap.h b/src/wrap.h
index a4064e6..24438b2 100644
--- a/src/wrap.h
+++ b/src/wrap.h
@@ -3,7 +3,7 @@
*
* Text wrapping, hyphenation, justification and shaping
*
- * Copyright © 2013 Thomas White <taw@bitwiz.org.uk>
+ * Copyright © 2014 Thomas White <taw@bitwiz.org.uk>
*
* This file is part of Colloquium.
*
@@ -61,6 +61,9 @@ struct wrap_box
enum wrap_box_type type;
int editable;
+ SCBlock *scblock;
+ size_t offs; /* offset into contents of scblock */
+
/* Pango units */
int width;
int height;
@@ -73,8 +76,8 @@ struct wrap_box
PangoGlyphString *glyphs;
PangoItem *item;
PangoFont *font;
- char *text;
double col[4]; /* rgba colour */
+ size_t len_bytes; /* number of bytes (not characters) of text */
/* For type == WRAP_BOX_IMAGE */
char *filename;
@@ -102,6 +105,8 @@ extern int wrap_contents(struct frame *fr);
extern void get_cursor_pos(struct wrap_box *box, size_t pos,
double *xposd, double *yposd, double *line_height);
+extern void move_cursor_back(struct presentation *p);
+
extern void find_cursor(struct frame *fr, double xposd, double yposd,
int *line, int *box, size_t *pos);