aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mainwindow.c17
-rw-r--r--src/presentation.h2
-rw-r--r--src/sc_parse.c50
-rw-r--r--src/shape.c61
-rw-r--r--src/wrap.c50
-rw-r--r--src/wrap.h5
6 files changed, 105 insertions, 80 deletions
diff --git a/src/mainwindow.c b/src/mainwindow.c
index ef89e8c..30f35e1 100644
--- a/src/mainwindow.c
+++ b/src/mainwindow.c
@@ -1132,22 +1132,18 @@ static void do_backspace(struct frame *fr, struct presentation *p)
/* If this is, say, the top level frame, do nothing */
if ( fr->boxes == NULL ) return;
- 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;
move_cursor_back(p);
- printf("New: frame %p, line %i, box %i, pos %li\n",
- p->cursor_frame, p->cursor_line, p->cursor_box, p->cursor_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);
+ sc_delete_text(fbox->scblock, p->cursor_pos+fbox->offs_char,
+ sbox->scblock, sps+sbox->offs_char);
rerender_slide(p);
redraw_editor(p);
@@ -1615,15 +1611,10 @@ static void move_cursor(struct presentation *p, signed int x, signed int y)
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_next_char(np, NULL);
- if ( np > box_text+box->len_bytes ) {
+ if ( cp+1 > box->len_chars ) {
advance = 1;
} else {
- cp = np - box_text;
+ cp++;
}
} else {
diff --git a/src/presentation.h b/src/presentation.h
index d66692e..8add695 100644
--- a/src/presentation.h
+++ b/src/presentation.h
@@ -144,7 +144,7 @@ struct presentation
struct frame *cursor_frame;
int cursor_line;
int cursor_box;
- size_t cursor_pos;
+ int cursor_pos; /* characters into box */
/* This is the "native" size of the slide. It only exists to give
* font size some meaning in the context of a somewhat arbitrary DPI */
diff --git a/src/sc_parse.c b/src/sc_parse.c
index 71dd449..fc6a40d 100644
--- a/src/sc_parse.c
+++ b/src/sc_parse.c
@@ -30,6 +30,7 @@
#include <string.h>
#include <stdio.h>
#include <ctype.h>
+#include <glib.h>
#include "sc_parse.h"
@@ -378,7 +379,52 @@ SCBlock *sc_parse(const char *sc)
}
-void sc_delete_text(SCBlock *b1, int p1, SCBlock *b2, int p2)
+static void delete_from_block(SCBlock *b, int o1, int o2)
{
- printf("Deleting from %p/%i to %p/%i\n", b1, p1, b2, p2);
+ assert(o2 > o1);
+ char *p1 = g_utf8_offset_to_pointer(b->contents, o1);
+ char *p2 = g_utf8_offset_to_pointer(b->contents, o2);
+ printf("'%s' (%p), chars %i to %i\n", b->contents, b->contents, o1, o2);
+ printf("moving %i bytes from %p to %p\n", strlen(p2)+1, p2, p1);
+ memmove(p1, p2, strlen(p2)+1);
+ printf("new: '%s'\n", b->contents);
+}
+
+
+static void delete_to_end(SCBlock *b, int offs)
+{
+ char *p = g_utf8_offset_to_pointer(b->contents, offs);
+ p[0] = '\0';
+}
+
+
+static void delete_from_start(SCBlock *b, int offs)
+{
+ char *p = g_utf8_offset_to_pointer(b->contents, offs);
+ memmove(b->contents, p, strlen(p)+1);
+}
+
+
+/* Character offsets */
+void sc_delete_text(SCBlock *b1, int o1, SCBlock *b2, int o2)
+{
+ printf("Before:\n");
+ show_sc_blocks(b1);
+ if ( b1 == b2 ) {
+ printf("--------> dfb\n");
+ delete_from_block(b1, o1, o2);
+ } else if ( b2 == b1->next ) {
+ printf("--------> dte+dfs\n");
+ delete_to_end(b1, o1);
+ delete_from_start(b2, o2);
+ } else {
+ printf("--------> dte+dfs+chain\n");
+ delete_to_end(b1, o1);
+ delete_from_start(b2, o2);
+ while ( b1->next != b2 ) {
+ sc_block_free(b1->next);
+ }
+ }
+ printf("After:\n");
+ show_sc_blocks(b1);
}
diff --git a/src/shape.c b/src/shape.c
index 6078b55..e27db9a 100644
--- a/src/shape.c
+++ b/src/shape.c
@@ -40,7 +40,7 @@ struct box_adding_stuff
struct wrap_line *line;
SCInterpreter *scin;
int editable;
- char *text;
+ const char *text;
enum wrap_box_space space;
SCBlock *bl;
size_t offs;
@@ -70,8 +70,11 @@ static void add_wrap_box(gpointer vi, gpointer vb)
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->offs_char = g_utf8_pointer_to_offset(bas->text,
+ bas->text+item->offset+bas->offs);
box->len_bytes = item->length;
+ box->len_chars = g_utf8_strlen(bas->text+item->offset+bas->offs,
+ item->length);
col = sc_interp_get_fgcol(bas->scin);
box->col[0] = col[0]; /* Red */
box->col[1] = col[1]; /* Green */
@@ -80,8 +83,8 @@ static void add_wrap_box(gpointer vi, gpointer vb)
box->glyphs = pango_glyph_string_new();
box->item = item;
- pango_shape(bas->text+item->offset, item->length, &item->analysis,
- box->glyphs);
+ pango_shape(bas->text+bas->offs+item->offset, item->length,
+ &item->analysis, box->glyphs);
pango_glyph_string_extents(box->glyphs, box->font, NULL, &rect);
@@ -98,10 +101,10 @@ 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,
+static int add_wrap_boxes(struct wrap_line *line, const char *text,
enum wrap_box_space space, PangoContext *pc,
SCInterpreter *scin, SCBlock *bl, size_t offs,
- int editable)
+ size_t len, int editable)
{
GList *pango_items;
PangoAttrList *attrs;
@@ -111,7 +114,7 @@ static int add_wrap_boxes(struct wrap_line *line, char *text,
attrs = pango_attr_list_new();
attr = pango_attr_font_desc_new(sc_interp_get_fontdesc(scin));
pango_attr_list_insert_before(attrs, attr);
- pango_items = pango_itemize(pc, text, 0, strlen(text), attrs, NULL);
+ pango_items = pango_itemize(pc, text+offs, 0, len, attrs, NULL);
bas.line = line;
bas.scin = scin;
@@ -137,7 +140,7 @@ void add_image_box(struct wrap_line *line, const char *filename,
box = &line->boxes[line->n_boxes];
box->type = WRAP_BOX_IMAGE;
box->scblock = NULL;
- box->offs = 0;
+ box->offs_char = 0;
box->space = WRAP_SPACE_NONE;
box->width = pango_units_from_double(w);
box->ascent = pango_units_from_double(h);
@@ -175,7 +178,6 @@ int split_words(struct wrap_line *boxes, PangoContext *pc, SCBlock *bl,
if ( log_attrs[i].is_line_break ) {
- char *word;
enum wrap_box_space type;
size_t len;
char *ptr;
@@ -199,15 +201,8 @@ int split_words(struct wrap_line *boxes, PangoContext *pc, SCBlock *bl,
type = WRAP_SPACE_NONE;
}
- word = strndup(text+start, len);
- if ( word == NULL ) {
- fprintf(stderr, "strndup() failed.\n");
- free(log_attrs);
- return 1;
- }
-
- if ( add_wrap_boxes(boxes, word, type,
- pc, scin, bl, start, editable) ) {
+ if ( add_wrap_boxes(boxes, text, type, pc, scin, bl,
+ start, len, editable) ) {
fprintf(stderr, "Failed to add wrap box.\n");
}
start = offs;
@@ -217,35 +212,23 @@ int split_words(struct wrap_line *boxes, PangoContext *pc, SCBlock *bl,
}
if ( i > start ) {
- char *word;
- size_t l;
-
- word = strdup(text+start); /* to the end */
- if ( word == NULL ) {
- fprintf(stderr, "strndup() failed.\n");
- free(log_attrs);
- return 1;
- }
- l = strlen(word);
+ size_t l = strlen(text+start);
- if ( (word[l-1] == '\n') ) {
+ if ( (text[start+l-1] == '\n') ) {
/* There is a newline at the end of the SC */
- char *word2;
-
- word2 = strndup(word, l-1);
- add_wrap_boxes(boxes, word2,
+ add_wrap_boxes(boxes, text,
WRAP_SPACE_EOP, pc, scin, bl, start,
- editable);
- add_wrap_boxes(boxes, strdup(""),
- WRAP_SPACE_NONE, pc, scin, bl, start,
- editable);
+ l-1, editable);
+ //add_wrap_boxes(boxes, "",
+ // WRAP_SPACE_NONE, pc, scin, bl, start+l,
+ // 1, editable);
} else {
- add_wrap_boxes(boxes, word,
+ add_wrap_boxes(boxes, text,
WRAP_SPACE_NONE, pc, scin, bl, start,
- editable);
+ l, editable);
}
diff --git a/src/wrap.c b/src/wrap.c
index f356a75..084bf24 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 *block_text;
const char *box_text;
*xposd = 0.0;
@@ -141,9 +142,10 @@ void get_cursor_pos(struct wrap_box *box, size_t pos,
switch ( box->type ) {
case WRAP_BOX_PANGO :
- box_text = sc_block_contents(box->scblock) + box->offs;
- pango_glyph_string_index_to_x(box->glyphs,
- box_text,
+ block_text = sc_block_contents(box->scblock);
+ box_text = g_utf8_offset_to_pointer(block_text, box->offs_char);
+ /* cast because this function is not const-clean */
+ pango_glyph_string_index_to_x(box->glyphs, (char *)box_text,
box->len_bytes,
&box->item->analysis, pos,
FALSE, &p);
@@ -173,15 +175,10 @@ void move_cursor_back(struct presentation *p)
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 ) {
+ if ( cp == 0 ) {
retreat = 1;
} else {
- cp = np - box_text;
+ cp--;
}
} else {
@@ -191,8 +188,6 @@ void move_cursor_back(struct presentation *p)
if ( retreat ) {
- const char *box_text;
-
do {
cb--;
@@ -211,10 +206,8 @@ void move_cursor_back(struct presentation *p)
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);
+ cp = box->len_chars;
} else {
cp = 1;
}
@@ -269,7 +262,7 @@ static int find_cursor_box(struct frame *fr, struct wrap_line *l,
void find_cursor(struct frame *fr, double xposd, double yposd,
- int *line, int *box, size_t *pos)
+ int *line, int *box, int *pos)
{
struct wrap_line *l;
struct wrap_box *b;
@@ -279,6 +272,7 @@ void find_cursor(struct frame *fr, double xposd, double yposd,
int x_pos_i;
size_t offs;
int ln, bn;
+ const char *block_text;
const char *box_text;
if ( fr->n_lines == 0 ) {
@@ -313,12 +307,13 @@ void find_cursor(struct frame *fr, double xposd, double yposd,
case WRAP_BOX_PANGO :
x_pos_i = pango_units_from_double(x_pos);
- box_text = sc_block_contents(b->scblock) + b->offs;
- pango_glyph_string_x_to_index(b->glyphs, box_text,
+ block_text = sc_block_contents(b->scblock);
+ box_text = g_utf8_offset_to_pointer(block_text, b->offs_char);
+ /* cast because this function is not const-clean */
+ pango_glyph_string_x_to_index(b->glyphs, (char *)box_text,
b->len_bytes,
&b->item->analysis,
x_pos_i, &idx, &trail);
- /* FIXME: Assumes 1 byte char */
offs = idx + trail;
break;
@@ -599,7 +594,7 @@ static void knuth_suboptimal_fit(struct wrap_line *boxes, double line_length,
box->height = 0;
box->editable = 1;
box->scblock = NULL;
- box->offs = 0;
+ box->offs_char = 0;
boxes->n_boxes++;
line_length *= PANGO_SCALE;
@@ -821,10 +816,19 @@ void show_boxes(struct wrap_line *boxes)
}
for ( i=0; i<boxes->n_boxes; i++ ) {
+ struct wrap_box *box = &boxes->boxes[i];
+ char *box_text;
printf("%3i", i);
- 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);
+ 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 {
+ 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);
}
}
diff --git a/src/wrap.h b/src/wrap.h
index 24438b2..98ed632 100644
--- a/src/wrap.h
+++ b/src/wrap.h
@@ -62,7 +62,7 @@ struct wrap_box
int editable;
SCBlock *scblock;
- size_t offs; /* offset into contents of scblock */
+ int offs_char; /* offset (in characters, not bytes) into scblock */
/* Pango units */
int width;
@@ -78,6 +78,7 @@ struct wrap_box
PangoFont *font;
double col[4]; /* rgba colour */
size_t len_bytes; /* number of bytes (not characters) of text */
+ int len_chars;
/* For type == WRAP_BOX_IMAGE */
char *filename;
@@ -108,7 +109,7 @@ extern void get_cursor_pos(struct wrap_box *box, size_t pos,
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);
+ int *line, int *box, int *pos);
extern void alloc_boxes(struct wrap_line *l);
extern void initialise_line(struct wrap_line *l);