aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.org.uk>2016-03-20 17:20:23 +0100
committerThomas White <taw@bitwiz.org.uk>2016-03-20 17:20:23 +0100
commit1ee3354534505a62a28a8aa9ee927ae91cc6e3ec (patch)
tree5db8bc161d2e77f68d2c88534087c453afe5af62
parent44e484efec8838a3a0da0b88207d84939226d165 (diff)
Line break on editing
-rw-r--r--src/boxvec.c24
-rw-r--r--src/boxvec.h4
-rw-r--r--src/sc_editor.c64
3 files changed, 76 insertions, 16 deletions
diff --git a/src/boxvec.c b/src/boxvec.c
index 218dddb..e065a91 100644
--- a/src/boxvec.c
+++ b/src/boxvec.c
@@ -100,6 +100,30 @@ void bv_del(struct boxvec *vec, struct wrap_box *bx)
}
+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);
diff --git a/src/boxvec.h b/src/boxvec.h
index 259df89..9538a35 100644
--- a/src/boxvec.h
+++ b/src/boxvec.h
@@ -56,6 +56,10 @@ 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);
diff --git a/src/sc_editor.c b/src/sc_editor.c
index 2c11c67..9509e6a 100644
--- a/src/sc_editor.c
+++ b/src/sc_editor.c
@@ -827,44 +827,76 @@ static void shift_box_offsets(struct frame *fr, struct wrap_box *box, int n)
}
-static void fixup_line_breaks(struct wrap_box *sbox, struct wrap_line *line,
- int sbx, int cursor_pos, PangoLanguage *lang)
+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;
- return; /* FIXME ! */
+ /* 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 ( (len_chars > 1) && log_attrs[offs+1].is_line_break ) {
+ if ( log_attrs[offs+1].is_line_break ) {
struct wrap_box *nbox;
- printf("Adding line break (new box)\n");
+ 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 */
- insert_box(line, sbx);
- nbox = bv_box(line->boxes, sbx);
+ 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 = WRAP_SPACE_INTERWORD;
- nbox->len_chars = cursor_pos;
+ nbox->space = sbox->space;
+ nbox->len_chars = sbox->len_chars - cursor_pos;
+ 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;
+ sbox->len_chars = cursor_pos;
+ if ( log_attrs[offs].is_expandable_space ) {
+ sbox->space = WRAP_SPACE_INTERWORD;
+ nbox->len_chars--;
+ nbox->offs_char++;
+ } else if ( log_attrs[offs+1].is_mandatory_break ) {
+ sbox->space = WRAP_SPACE_EOP;
+ printf("New paragraph!\n");
+ nbox->offs_char++;
+ nbox->len_chars--;
+ } 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);
- shape_box(sbox);
- //shape_box(nbox);
+ itemize_and_shape(nbox, pc);
+ /* sbox will get done in just a moment */
}
@@ -914,13 +946,13 @@ static void insert_text(char *t, SCEditor *e)
/* 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);
- fixup_line_breaks(sbox, &e->cursor_frame->lines[sln], sbx,
- e->cursor_pos, e->lang);
-
fr->empty = 0;
wrap_contents(e->cursor_frame);