diff options
Diffstat (limited to 'libstorycode')
-rw-r--r-- | libstorycode/gtk/gtknarrativeview.c | 151 | ||||
-rw-r--r-- | libstorycode/gtk/gtknarrativeview.h | 5 | ||||
-rw-r--r-- | libstorycode/narrative.c | 77 | ||||
-rw-r--r-- | libstorycode/narrative.h | 2 |
4 files changed, 170 insertions, 65 deletions
diff --git a/libstorycode/gtk/gtknarrativeview.c b/libstorycode/gtk/gtknarrativeview.c index d33dc3b..47ee43c 100644 --- a/libstorycode/gtk/gtknarrativeview.c +++ b/libstorycode/gtk/gtknarrativeview.c @@ -143,6 +143,16 @@ static void rewrap_range(GtkNarrativeView *e, int min, int max) } +static void update_size(GtkNarrativeView *e) +{ + e->w = e->visible_width; + e->h = narrative_get_height(presentation_get_narrative(e->p)); + + set_vertical_params(e); + set_horizontal_params(e); +} + + static gboolean resize_sig(GtkWidget *widget, GdkEventConfigure *event, GtkNarrativeView *e) { @@ -156,11 +166,7 @@ static gboolean resize_sig(GtkWidget *widget, GdkEventConfigure *event, rewrap_range(e, 0, n->n_items-1); - e->w = e->visible_width; - e->h = narrative_get_height(presentation_get_narrative(e->p)); - - set_vertical_params(e); - set_horizontal_params(e); + update_size(e); return FALSE; } @@ -496,6 +502,10 @@ static size_t pos_trail_to_offset(struct narrative_item *item, int offs, int tra glong char_offs; char *ptr; + if ( item->type == NARRATIVE_ITEM_SLIDE ) { + return offs; + } + char_offs = g_utf8_pointer_to_offset(item->text, item->text+offs); char_offs += trail; ptr = g_utf8_offset_to_pointer(item->text, char_offs); @@ -619,49 +629,12 @@ static void check_cursor_visible(GtkNarrativeView *e) } -static void do_backspace(GtkNarrativeView *e) +static struct narrative_item *get_current_item(GtkNarrativeView *e, + Narrative **pn) { -// double wrapw = e->cursor_frame->w - e->cursor_frame->pad_l - e->cursor_frame->pad_r; -// -// if ( e->sel_active ) { -// -// /* Delete the selected block */ -// delete_text_from_frame(e->cursor_frame, e->sel_start, e->sel_end, wrapw); -// -// /* Cursor goes at start of deletion */ -// sort_positions(&e->sel_start, &e->sel_end); -// e->cpos = e->sel_start; -// e->sel_active = 0; -// -// } else { -// -// if ( para_type(e->cursor_frame->paras[e->cpos.para]) == PARA_TYPE_TEXT ) { -// -// /* Delete one character */ -// struct edit_pos p1, p2; -// -// p1 = e->cpos; -// -// p2 = p1; -// -// cursor_moveh(e->cursor_frame, &p2, -1); -// show_edit_pos(p1); -// show_edit_pos(p2); -// -// delete_text_from_frame(e->cursor_frame, p1, p2, wrapw); -// e->cpos = p2; -// -// } else { -// -// /* FIXME: Implement this */ -// fprintf(stderr, "Deleting non-text paragraph\n"); -// -// } -// -// } - - emit_change_sig(e); - redraw(e); + Narrative *n = presentation_get_narrative(e->p); + if ( pn != NULL ) *pn = n; + return &n->items[e->cpos.para]; } @@ -670,7 +643,26 @@ static size_t end_offset_of_para(Narrative *n, int pnum) assert(pnum >= 0); if ( n->items[pnum].type == NARRATIVE_ITEM_SLIDE ) return 0; return strlen(n->items[pnum].text); +} + +static void sort_positions(struct edit_pos *a, struct edit_pos *b) +{ + if ( a->para > b->para ) { + size_t tpos; + int tpara, ttrail; + tpara = b->para; tpos = b->pos; ttrail = b->trail; + b->para = a->para; b->pos = a->pos; b->trail = a->trail; + a->para = tpara; a->pos = tpos; a->trail = ttrail; + } + + if ( (a->para == b->para) && (a->pos > b->pos) ) + { + size_t tpos = b->pos; + int ttrail = b->trail; + b->pos = a->pos; b->trail = a->trail; + a->pos = tpos; a->trail = ttrail; + } } @@ -730,6 +722,53 @@ static void cursor_moveh(Narrative *n, struct edit_pos *cp, signed int dir) } +static void do_backspace(GtkNarrativeView *e) +{ + Narrative *n; + size_t o1, o2; + + n = presentation_get_narrative(e->p); + + if ( e->sel_active ) { + + /* Delete the selected block */ + sort_positions(&e->sel_start, &e->sel_end); + o1 = pos_trail_to_offset(&n->items[e->sel_start.para], + e->sel_start.pos, e->sel_start.trail); + o2 = pos_trail_to_offset(&n->items[e->sel_end.para], + e->sel_end.pos, e->sel_end.trail); + narrative_delete_block(n, e->sel_start.para, o1, + e->sel_end.para, o2); + + /* Cursor goes at start of deletion */ + e->cpos = e->sel_start; + e->sel_active = 0; + + } else { + + struct edit_pos p1, p2; + + /* Delete one character, as represented visually */ + p2 = e->cpos; + p1 = p2; + cursor_moveh(n, &p1, -1); + o1 = pos_trail_to_offset(&n->items[p1.para], p1.pos, p1.trail); + o2 = pos_trail_to_offset(&n->items[p2.para], p2.pos, p2.trail); + narrative_delete_block(n, p1.para, o1, p2.para, o2); + e->cpos = p1; + + } + + /* The only paragraphs which still exist and might have been + * affected by the deletion are sel_start.para and the one + * immediately afterwards. */ + rewrap_range(e, e->sel_start.para, e->sel_start.para+1); + update_size(e); + emit_change_sig(e); + redraw(e); +} + + static void insert_text_in_paragraph(struct narrative_item *item, size_t offs, char *t) { @@ -753,12 +792,11 @@ static void insert_text(char *t, GtkNarrativeView *e) do_backspace(e); } - n = presentation_get_narrative(e->p); - item = &n->items[e->cpos.para]; + item = get_current_item(e, &n); if ( strcmp(t, "\n") == 0 ) { //split_paragraph_at_cursor(e); FIXME - //update_size(e); + update_size(e); cursor_moveh(n, &e->cpos, +1); check_cursor_visible(e); emit_change_sig(e); @@ -773,7 +811,7 @@ static void insert_text(char *t, GtkNarrativeView *e) off = pos_trail_to_offset(item, e->cpos.pos, e->cpos.trail); insert_text_in_paragraph(item, off, t); rewrap_range(e, e->cpos.para, e->cpos.para); - //update_size(e); + update_size(e); cursor_moveh(n, &e->cpos, +1); } else { @@ -899,14 +937,6 @@ static gboolean key_press_sig(GtkWidget *da, GdkEventKey *event, switch ( event->keyval ) { - case GDK_KEY_Escape : - if ( !e->para_highlight ) { - //sc_editor_remove_cursor(e); - redraw(e); - claim = 1; - } - break; - case GDK_KEY_Left : cursor_moveh(n, &e->cpos, -1); redraw(e); @@ -931,14 +961,13 @@ static gboolean key_press_sig(GtkWidget *da, GdkEventKey *event, claim = 1; break; - case GDK_KEY_Return : im_commit_sig(NULL, "\n", e); claim = 1; break; case GDK_KEY_BackSpace : - //do_backspace(e->selection, e); + do_backspace(e); claim = 1; break; diff --git a/libstorycode/gtk/gtknarrativeview.h b/libstorycode/gtk/gtknarrativeview.h index 0a09175..13400db 100644 --- a/libstorycode/gtk/gtknarrativeview.h +++ b/libstorycode/gtk/gtknarrativeview.h @@ -73,9 +73,8 @@ enum drag_status struct edit_pos { int para; /* Paragraph number (corresponding to narrative items) */ - int pos; /* Byte position within paragraph - * Yes, really. See pango_layout_xy_to_index */ - int trail; + int pos; /* Byte position within paragraph (yes, really) */ + int trail; /* 1 = end of character, 0 = before */ }; diff --git a/libstorycode/narrative.c b/libstorycode/narrative.c index 18e2203..8cb54c3 100644 --- a/libstorycode/narrative.c +++ b/libstorycode/narrative.c @@ -41,8 +41,29 @@ Narrative *narrative_new() return n; } + +static void narrative_item_destroy(struct narrative_item *item) +{ + free(item->text); +#ifdef HAVE_PANGO + if ( item->layout != NULL ) { + g_object_unref(item->layout); + } +#endif +#ifdef HAVE_CAIRO + if ( item->slide_thumbnail != NULL ) { + cairo_surface_destroy(item->slide_thumbnail); + } +#endif +} + + void narrative_free(Narrative *n) { + int i; + for ( i=0; i<n->n_items; i++ ) { + narrative_item_destroy(&n->items[i]); + } free(n->items); free(n); } @@ -51,10 +72,16 @@ void narrative_free(Narrative *n) static struct narrative_item *add_item(Narrative *n) { struct narrative_item *new_items; + struct narrative_item *item; new_items = realloc(n->items, (n->n_items+1)*sizeof(struct narrative_item)); if ( new_items == NULL ) return NULL; n->items = new_items; - return &n->items[n->n_items++]; + item = &n->items[n->n_items++]; + item->layout = NULL; + item->text = NULL; + item->slide = NULL; + item->slide_thumbnail = NULL; + return item; } @@ -111,3 +138,51 @@ void narrative_add_slide(Narrative *n, Slide *slide) item->slide = slide; item->slide_thumbnail = NULL; } + + +static void delete_item(Narrative *n, int del) +{ + int i; + narrative_item_destroy(&n->items[del]); + for ( i=del; i<n->n_items-1; i++ ) { + n->items[i] = n->items[i+1]; + } + n->n_items--; +} + + +/* Delete from item i1 offset o1 to item i2 offset o2, inclusive */ +void narrative_delete_block(Narrative *n, int i1, size_t o1, int i2, size_t o2) +{ + int i; + + /* Starting item */ + if ( n->items[i1].type == NARRATIVE_ITEM_SLIDE ) { + delete_item(n, i1); + i1--; + i2--; + } else { + if ( i1 == i2 ) { + memmove(&n->items[i1].text[o1], + &n->items[i1].text[o2], + strlen(n->items[i1].text)-o2+1); + return; /* easy case */ + } else { + n->items[i1].text[o1] = '\0'; + } + } + + /* Middle items */ + for ( i=i1+1; i<i2; i++ ) { + delete_item(n, i); + i2--; + } + + /* Last item */ + if ( n->items[i2].type == NARRATIVE_ITEM_SLIDE ) { + delete_item(n, i2); + } else { + memmove(&n->items[i2].text[0], + &n->items[i2].text[o2], o2); + } +} diff --git a/libstorycode/narrative.h b/libstorycode/narrative.h index e42b4f3..412bc6b 100644 --- a/libstorycode/narrative.h +++ b/libstorycode/narrative.h @@ -38,6 +38,8 @@ extern void narrative_add_prestitle(Narrative *n, char *text); extern void narrative_add_bp(Narrative *n, char *text); extern void narrative_add_text(Narrative *n, char *text); extern void narrative_add_slide(Narrative *n, Slide *slide); +extern void narrative_delete_block(Narrative *n, int i1, size_t o1, + int i2, size_t o2); #endif /* NARRATIVE_H */ |