diff options
-rw-r--r-- | Makefile.am | 5 | ||||
-rw-r--r-- | data/colloquium.ui | 5 | ||||
-rw-r--r-- | src/mainwindow.c | 124 | ||||
-rw-r--r-- | src/objects.c | 206 | ||||
-rw-r--r-- | src/objects.h | 23 | ||||
-rw-r--r-- | src/presentation.h | 6 | ||||
-rw-r--r-- | src/slide_render.c | 107 | ||||
-rw-r--r-- | src/stylesheet.c | 392 | ||||
-rw-r--r-- | src/stylesheet.h | 27 | ||||
-rw-r--r-- | src/tool_text.c | 203 | ||||
-rw-r--r-- | src/tool_text.h | 39 |
11 files changed, 541 insertions, 596 deletions
diff --git a/Makefile.am b/Makefile.am index 98e31d7..445f004 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,12 +10,13 @@ LDADD = $(top_builddir)/lib/libgnu.a @IGNORE_UNUSED_LIBRARIES_CFLAGS@ src_colloquium_SOURCES = src/colloquium.c src/presentation.c src/mainwindow.c \ src/slide_render.c src/objects.c src/slideshow.c \ - src/stylesheet.c src/loadsave.c + src/stylesheet.c src/loadsave.c src/tool_text.c INCLUDES = "-I$(top_srcdir)/data" EXTRA_DIST += src/presentation.h src/mainwindow.h src/slide_render .h \ - src/objects.h src/slideshow.h src/stylesheet.h src/loadsave.h + src/objects.h src/slideshow.h src/stylesheet.h src/loadsave.h \ + src/tool_text.h colloquiumdir = $(datadir)/colloquium colloquium_DATA = data/colloquium.ui diff --git a/data/colloquium.ui b/data/colloquium.ui index f52500d..532056b 100644 --- a/data/colloquium.ui +++ b/data/colloquium.ui @@ -24,6 +24,11 @@ <menuitem name="Stylesheet..." action="EditStyleAction" /> </menu> + <menu name="insert" action="InsertAction"> + <menuitem name="newslide" action="NewSlideAction" /> + <separator /> + </menu> + <menu name="tools" action="ToolsAction"> <menuitem name="slideshow" action="TSlideshowAction" /> <menuitem name="preferences" action="PrefsAction" /> diff --git a/src/mainwindow.c b/src/mainwindow.c index b308cfe..3446aed 100644 --- a/src/mainwindow.c +++ b/src/mainwindow.c @@ -38,6 +38,7 @@ #include "slideshow.h" #include "stylesheet.h" #include "loadsave.h" +#include "tool_text.h" static void add_ui_sig(GtkUIManager *ui, GtkWidget *widget, @@ -255,6 +256,8 @@ static void update_toolbar(struct presentation *p) gtk_widget_set_sensitive(GTK_WIDGET(d), FALSE); } + + } @@ -369,44 +372,11 @@ static gint set_tool_sig(GtkWidget *widget, GtkRadioAction *action, } -static void layout_changed_sig(GtkComboBox *combo, struct presentation *p) -{ - int n; - - if ( p->editing_object != NULL ) { - printf("Can't change layout element!\n"); - return; - } - - n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo)); - p->cur_layout = p->ss->layout_elements[n]; - - -} - - -static void text_style_changed_sig(GtkComboBox *combo, struct presentation *p) -{ - int n; - - n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo)); - p->cur_style = p->ss->text_styles[n]; - - if ( p->editing_object != NULL ) { - set_text_style(p->editing_object, p->cur_style); - gdk_window_invalidate_rect(p->drawingarea->window, NULL, FALSE); - } -} - - static void add_menu_bar(struct presentation *p, GtkWidget *vbox) { GError *error = NULL; - GtkWidget *label; - GtkWidget *combo; GtkToolItem *titem; - GtkWidget *box; - int i; + GtkWidget *toolbar; GtkActionEntry entries[] = { { "FileAction", NULL, "_File", NULL, NULL, NULL }, @@ -439,6 +409,10 @@ static void add_menu_bar(struct presentation *p, GtkWidget *vbox) { "EditStyleAction", NULL, "Stylesheet...", NULL, NULL, G_CALLBACK(open_stylesheet_sig) }, + { "InsertAction", NULL, "_Insert", NULL, NULL, NULL }, + { "NewSlideAction", GTK_STOCK_ADD, "_New Slide", + NULL, NULL, G_CALLBACK(add_slide_sig) }, + { "ToolsAction", NULL, "_Tools", NULL, NULL, NULL }, { "TSlideshowAction", GTK_STOCK_FULLSCREEN, "_Start slideshow", "F5", NULL, G_CALLBACK(start_slideshow_sig) }, @@ -492,43 +466,15 @@ static void add_menu_bar(struct presentation *p, GtkWidget *vbox) gtk_ui_manager_get_accel_group(p->ui)); gtk_ui_manager_ensure_update(p->ui); - p->toolbar = gtk_ui_manager_get_widget(p->ui, - "/ui/displaywindowtoolbar"); - + toolbar = gtk_ui_manager_get_widget(p->ui, + "/ui/displaywindowtoolbar"); titem = gtk_separator_tool_item_new(); - gtk_toolbar_insert(GTK_TOOLBAR(p->toolbar), titem, -1); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), titem, -1); - box = gtk_vbox_new(FALSE, 0.0); p->tbox = gtk_hbox_new(FALSE, 0.0); titem = gtk_tool_item_new(); - gtk_box_pack_start(GTK_BOX(box), p->tbox, FALSE, FALSE, 5.0); - gtk_container_add(GTK_CONTAINER(titem), box); - gtk_toolbar_insert(GTK_TOOLBAR(p->toolbar), titem, -1); - label = gtk_label_new("Layout element:"); - gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); - gtk_box_pack_start(GTK_BOX(p->tbox), label, FALSE, FALSE, 5.0); - combo = gtk_combo_box_new_text(); - for ( i=0; i<p->ss->n_layout_elements; i++ ) { - gtk_combo_box_append_text(GTK_COMBO_BOX(combo), - p->ss->layout_elements[i]->name); - } - gtk_box_pack_start(GTK_BOX(p->tbox), combo, FALSE, FALSE, 5.0); - g_signal_connect(G_OBJECT(combo), "changed", - G_CALLBACK(layout_changed_sig), p); - gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); - - label = gtk_label_new("Text style:"); - gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); - gtk_box_pack_start(GTK_BOX(p->tbox), label, FALSE, FALSE, 5.0); - combo = gtk_combo_box_new_text(); - for ( i=0; i<p->ss->n_text_styles; i++ ) { - gtk_combo_box_append_text(GTK_COMBO_BOX(combo), - p->ss->text_styles[i]->name); - } - gtk_box_pack_start(GTK_BOX(p->tbox), combo, FALSE, FALSE, 5.0); - g_signal_connect(G_OBJECT(combo), "changed", - G_CALLBACK(text_style_changed_sig), p); - gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); + gtk_container_add(GTK_CONTAINER(titem), p->tbox); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), titem, -1); update_toolbar(p); } @@ -670,9 +616,10 @@ static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event, case TOOL_TEXT : if ( !clicked ) { struct object *n; + /* FIXME: Insert ESP here and possibly + * select a different style */ n = add_text_object(p->view_slide, x, y, - p->cur_layout, - p->cur_style); + p->ss->styles[0]); p->editing_object = n; } else { p->editing_object = clicked; @@ -707,6 +654,7 @@ static void draw_editing_bits(cairo_t *cr, struct presentation *p, { draw_editing_box(cr, o->x, o->y, o->bb_width, o->bb_height); + /* FIXME: Dispatch table */ switch ( o->type ) { case TEXT : @@ -716,31 +664,27 @@ static void draw_editing_bits(cairo_t *cr, struct presentation *p, } - if ( o->le != NULL ) { - - cairo_move_to(cr, o->le->margin_left, -p->border_offs_y); - cairo_line_to(cr, o->le->margin_left, - p->slide_height+p->border_offs_y); + cairo_move_to(cr, o->style->margin_left, -p->border_offs_y); + cairo_line_to(cr, o->style->margin_left, + p->slide_height+p->border_offs_y); - cairo_move_to(cr, p->slide_width-o->le->margin_right, - -p->border_offs_y); - cairo_line_to(cr, p->slide_width-o->le->margin_right, - p->slide_height+p->border_offs_y); + cairo_move_to(cr, p->slide_width-o->style->margin_right, + -p->border_offs_y); + cairo_line_to(cr, p->slide_width-o->style->margin_right, + p->slide_height+p->border_offs_y); - cairo_move_to(cr, -p->border_offs_x, o->le->margin_top); - cairo_line_to(cr, p->slide_width+p->border_offs_x, - o->le->margin_top); + cairo_move_to(cr, -p->border_offs_x, o->style->margin_top); + cairo_line_to(cr, p->slide_width+p->border_offs_x, + o->style->margin_top); - cairo_move_to(cr, -p->border_offs_x, - p->slide_height-o->le->margin_bottom); - cairo_line_to(cr, p->slide_width+p->border_offs_x, - p->slide_height-o->le->margin_bottom); + cairo_move_to(cr, -p->border_offs_x, + p->slide_height-o->style->margin_bottom); + cairo_line_to(cr, p->slide_width+p->border_offs_x, + p->slide_height-o->style->margin_bottom); - cairo_set_source_rgb(cr, 0.2, 0.2, 0.2); - cairo_set_line_width(cr, 1.0); - cairo_stroke(cr); - - } + cairo_set_source_rgb(cr, 0.2, 0.2, 0.2); + cairo_set_line_width(cr, 1.0); + cairo_stroke(cr); } diff --git a/src/objects.c b/src/objects.c index ae634a5..4d18df1 100644 --- a/src/objects.c +++ b/src/objects.c @@ -34,7 +34,7 @@ #include "mainwindow.h" -static struct object *new_object(enum objtype t, struct layout_element *le) +struct object *new_object(enum objtype t, struct style *sty) { struct object *new; @@ -44,13 +44,13 @@ static struct object *new_object(enum objtype t, struct layout_element *le) new->type = t; new->empty = 1; new->parent = NULL; - new->le = le; + new->style = sty; return new; } -static void free_object(struct object *o) +void free_object(struct object *o) { if ( o->layout != NULL ) g_object_unref(o->layout); if ( o->fontdesc != NULL ) pango_font_description_free(o->fontdesc); @@ -58,207 +58,29 @@ static void free_object(struct object *o) } -struct object *add_text_object(struct slide *s, double x, double y, - struct layout_element *el, struct text_style *ts) +struct object *add_image_object(struct slide *s, double x, double y, + const char *filename, + double width, double height) { struct object *new; - new = new_object(TEXT, el); + new = new_object(IMAGE, NULL); + + new->x = x; new->y = y; + new->bb_width = width; + new->bb_height = height; + if ( add_object_to_slide(s, new) ) { free_object(new); return NULL; } - - new->x = x; new->y = y; - new->bb_width = 10.0; - new->bb_height = 40.0; - new->text = malloc(1); - new->text[0] = '\0'; - new->text_len = 1; - new->insertion_point = 0; - new->style = ts; - new->layout = NULL; - new->fontdesc = NULL; - s->object_seq++; return new; } -void insert_text(struct object *o, char *t) -{ - char *tmp; - size_t tlen, olen; - int i; - - assert(o->type == TEXT); - tlen = strlen(t); - olen = strlen(o->text); - - if ( tlen + olen + 1 > o->text_len ) { - - char *try; - - try = realloc(o->text, o->text_len + tlen + 64); - if ( try == NULL ) return; /* Failed to insert */ - o->text = try; - o->text_len += 64; - o->text_len += tlen; - - } - - tmp = malloc(o->text_len); - if ( tmp == NULL ) return; - - for ( i=0; i<o->insertion_point; i++ ) { - tmp[i] = o->text[i]; - } - for ( i=0; i<tlen; i++ ) { - tmp[i+o->insertion_point] = t[i]; - } - for ( i=0; i<olen-o->insertion_point; i++ ) { - tmp[i+o->insertion_point+tlen] = o->text[i+o->insertion_point]; - } - tmp[olen+tlen] = '\0'; - memcpy(o->text, tmp, o->text_len); - free(tmp); - - o->insertion_point += tlen; - o->parent->object_seq++; - o->empty = 0; -} - - -void set_text_style(struct object *o, struct text_style *ts) -{ - assert(o->type == TEXT); - o->style = ts; - o->parent->object_seq++; -} - - -static int find_prev_index(const char *t, int p) -{ - int i, nback; - - if ( p == 0 ) return 0; - - if ( !(t[p-1] & 0x80) ) { - nback = 1; - } else { - nback = 0; - for ( i=1; i<=6; i++ ) { - if ( p-i == 0 ) return 0; - if ( !(t[p-i] & 0xC0) ) nback++; - } - } - - return p - nback; -} - - -static int find_next_index(const char *t, int p) -{ - int i, nfor; - - if ( t[p] == '\0' ) return p; - - if ( !(t[p+1] & 0x80) ) { - nfor = 1; - } else { - nfor = 0; - for ( i=1; i<=6; i++ ) { - if ( t[p+i] == '\0' ) return p+i; - if ( !(t[p+i] & 0xC0) ) nfor++; - } - } - - return p + nfor; -} - - -void handle_text_backspace(struct object *o) -{ - int prev_index; - - assert(o->type == TEXT); - - if ( o->insertion_point == 0 ) return; /* Nothing to delete */ - - prev_index = find_prev_index(o->text, o->insertion_point); - - memmove(o->text+prev_index, o->text+o->insertion_point, - o->text_len-o->insertion_point); - - o->insertion_point = prev_index; - - if ( strlen(o->text) == 0 ) o->empty = 1; - - o->parent->object_seq++; -} - - -void move_cursor_left(struct object *o) -{ - o->insertion_point = find_prev_index(o->text, o->insertion_point); -} - - -void move_cursor_right(struct object *o) -{ - o->insertion_point = find_next_index(o->text, o->insertion_point); -} - - -void position_caret(struct object *o, double x, double y) -{ - int idx, trail; - int xp, yp; - gboolean v; - - assert(o->type == TEXT); - - xp = (x - o->x)*PANGO_SCALE; - yp = (y - o->y)*PANGO_SCALE; - - v = pango_layout_xy_to_index(o->layout, xp, yp, &idx, &trail); - - o->insertion_point = idx+trail; -} - - -void notify_style_update(struct presentation *p, struct text_style *ts) -{ - int i; - int changed = 0; - - for ( i=0; i<p->num_slides; i++ ) { - - int j; - struct slide *s; - - s = p->slides[i]; - - for ( j=0; j<p->slides[i]->num_objects; j++ ) { - - if ( s->objects[j]->type != TEXT ) continue; - if ( s->objects[j]->style != ts ) continue; - - s->object_seq++; - if ( p->view_slide == s ) changed = 1; - break; - - } - - } - - p->completely_empty = 0; - if ( changed ) notify_slide_update(p); -} - - -void notify_layout_update(struct presentation *p, struct layout_element *le) +void notify_style_update(struct presentation *p, struct style *sty) { int i; int changed = 0; @@ -272,7 +94,7 @@ void notify_layout_update(struct presentation *p, struct layout_element *le) for ( j=0; j<p->slides[i]->num_objects; j++ ) { - if ( s->objects[j]->le != le ) continue; + if ( s->objects[j]->style != sty ) continue; s->object_seq++; if ( p->view_slide == s ) changed = 1; diff --git a/src/objects.h b/src/objects.h index ddbd2a8..d7eb706 100644 --- a/src/objects.h +++ b/src/objects.h @@ -31,6 +31,7 @@ enum objtype { TEXT, + IMAGE, }; @@ -38,7 +39,7 @@ struct object { enum objtype type; struct slide *parent; - struct layout_element *le; + struct style *style; /* Position of corner of object */ double x; @@ -56,23 +57,17 @@ struct object int insertion_point; PangoLayout *layout; PangoFontDescription *fontdesc; - struct text_style *style; }; +extern struct object *new_object(enum objtype t, struct style *sty); +extern void free_object(struct object *o); +extern struct object *add_image_object(struct slide *s, double x, double y, + const char *filename, + double width, double height); -extern struct object *add_text_object(struct slide *s, double x, double y, - struct layout_element *el, - struct text_style *ts); -extern void insert_text(struct object *o, char *t); -extern void set_text_style(struct object *o, struct text_style *ts); -extern void notify_style_update(struct presentation *p, struct text_style *ts); -extern void handle_text_backspace(struct object *o); -extern void move_cursor_left(struct object *o); -extern void move_cursor_right(struct object *o); -extern void position_caret(struct object *o, double x, double y); -extern void notify_layout_update(struct presentation *p, - struct layout_element *ts); +extern void notify_style_update(struct presentation *p, + struct style *sty); extern void delete_object(struct object *o); diff --git a/src/presentation.h b/src/presentation.h index d48fd96..db53f07 100644 --- a/src/presentation.h +++ b/src/presentation.h @@ -67,7 +67,6 @@ struct presentation GtkUIManager *ui; GtkActionGroup *action_group; GtkIMContext *im_context; - GtkWidget *toolbar; GtkWidget *tbox; int drag_preview_pending; int have_drag_data; @@ -79,9 +78,8 @@ struct presentation int drag_y; /* Stylesheet */ - StyleSheet *ss; - struct text_style *cur_style; - struct layout_element *cur_layout; + StyleSheet *ss; + struct style *default_style; /* Dialogue boxes */ StylesheetWindow *stylesheetwindow; diff --git a/src/slide_render.c b/src/slide_render.c index 3a34f6a..8c438d4 100644 --- a/src/slide_render.c +++ b/src/slide_render.c @@ -35,38 +35,37 @@ #include "stylesheet.h" -static void render_text_object(cairo_t *cr, struct object *o) +static void calculate_size_from_style(struct object *o, + double *peright, double *pebottom, + double *pmw, double *pmh) { - double ebottom, eright, mw, mh; double max_width, max_height; - double xo, yo; - PangoRectangle ink, logical; - - o->layout = pango_cairo_create_layout(cr); - pango_layout_set_text(o->layout, o->text, -1); - o->fontdesc = pango_font_description_from_string(o->style->font); - pango_layout_set_font_description(o->layout, o->fontdesc); + double ebottom, eright, mw, mh; - eright = o->parent->slide_width - o->le->margin_right; - ebottom = o->parent->slide_height - o->le->margin_bottom; + eright = o->parent->slide_width - o->style->margin_right; + ebottom = o->parent->slide_height - o->style->margin_bottom; mw = o->parent->slide_width; mh = o->parent->slide_height; - max_width = mw - o->le->margin_left - o->le->margin_right; + *peright = eright; *pebottom = ebottom; + *pmw = mw; *pmh = mh; + + max_width = mw - o->style->margin_left - o->style->margin_right; /* Use the provided maximum width if it exists and is smaller */ - if ( o->le->use_max_width && (o->le->max_width < max_width) ) { - max_width = o->le->max_width; + if ( o->style->use_max_width && (o->style->max_width < max_width) ) + { + max_width = o->style->max_width; } - max_height = mh - o->le->margin_top - o->le->margin_bottom; + max_height = mh - o->style->margin_top - o->style->margin_bottom; pango_layout_set_width(o->layout, max_width*PANGO_SCALE); pango_layout_set_height(o->layout, max_height*PANGO_SCALE); pango_layout_set_wrap(o->layout, PANGO_WRAP_WORD_CHAR); pango_layout_set_ellipsize(o->layout, PANGO_ELLIPSIZE_MIDDLE); - switch ( o->le->halign ) { + switch ( o->style->halign ) { case J_LEFT : pango_layout_set_alignment(o->layout, PANGO_ALIGN_LEFT); break; @@ -77,66 +76,100 @@ static void render_text_object(cairo_t *cr, struct object *o) pango_layout_set_alignment(o->layout, PANGO_ALIGN_CENTER); break; } +} - pango_cairo_update_layout(cr, o->layout); + +static void calculate_position_from_style(struct object *o, + double eright, double ebottom, + double mw, double mh) +{ + double xo, yo; + PangoRectangle ink, logical; pango_layout_get_extents(o->layout, &ink, &logical); - o->bb_width = ink.width / PANGO_SCALE; - o->bb_height = logical.height/PANGO_SCALE; xo = ink.x/PANGO_SCALE; yo = logical.y/PANGO_SCALE; - switch ( o->le->halign ) { + switch ( o->style->halign ) { case J_LEFT : - o->x = -xo + o->le->margin_left; + o->x = -xo + o->style->margin_left; break; case J_RIGHT : o->x = -xo + eright - o->bb_width; break; case J_CENTER : - o->x = mw/2.0 - o->bb_width/2.0 - xo + o->le->offset_x; + o->x = mw/2.0 - o->bb_width/2.0 - xo + o->style->offset_x; break; } - if ( o->le->halign == J_CENTER ) { + if ( o->style->halign == J_CENTER ) { - if ( o->x+xo < o->le->margin_left ) { - o->x = o->le->margin_left - xo; + if ( o->x+xo < o->style->margin_left ) { + o->x = o->style->margin_left - xo; } - if ( o->x+xo + o->bb_width > mw-o->le->margin_right ) { - o->x = mw-o->le->margin_right - xo - o->bb_width; + if ( o->x+xo + o->bb_width > mw-o->style->margin_right ) { + o->x = mw-o->style->margin_right - xo - o->bb_width; } } - switch ( o->le->valign ) { + switch ( o->style->valign ) { case V_TOP : - o->y = o->le->margin_top; + o->y = o->style->margin_top; break; case V_BOTTOM : o->y = ebottom - o->bb_height; break; case V_CENTER : - o->y = mh/2.0 - o->bb_height/2.0 + yo - o->le->offset_y; + o->y = mh/2.0 - o->bb_height/2.0 + yo - o->style->offset_y; break; } - if ( o->le->valign == V_CENTER ) { + if ( o->style->valign == V_CENTER ) { - if ( o->y < o->le->margin_top ) { - o->y = o->le->margin_top; + if ( o->y < o->style->margin_top ) { + o->y = o->style->margin_top; } - if ( o->y+yo + o->bb_height > mh - o->le->margin_bottom ) { - o->y = mh-o->le->margin_bottom - yo - o->bb_height; + if ( o->y+yo + o->bb_height > mh - o->style->margin_bottom ) { + o->y = mh-o->style->margin_bottom - yo - o->bb_height; } } + o->x += xo; + o->y += yo; +} + + +static void render_text_object(cairo_t *cr, struct object *o) +{ + PangoRectangle ink, logical; + double eright, ebottom, mw, mh; + + o->layout = pango_cairo_create_layout(cr); + pango_layout_set_text(o->layout, o->text, -1); + o->fontdesc = pango_font_description_from_string(o->style->font); + pango_layout_set_font_description(o->layout, o->fontdesc); + + if ( o->style != o->parent->parent->ss->styles[0] ) + { + calculate_size_from_style(o, &eright, &ebottom, &mw, &mh); + } + + pango_cairo_update_layout(cr, o->layout); + + pango_layout_get_extents(o->layout, &ink, &logical); + o->bb_width = ink.width / PANGO_SCALE; + o->bb_height = logical.height/PANGO_SCALE; + + if ( o->style != o->parent->parent->ss->styles[0] ) + { + calculate_position_from_style(o, eright, ebottom, mw, mh); + } + cairo_move_to(cr, o->x, o->y); cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); pango_cairo_show_layout(cr, o->layout); - o->x += xo; - o->y += yo; } diff --git a/src/stylesheet.c b/src/stylesheet.c index 46167a1..b4cc11e 100644 --- a/src/stylesheet.c +++ b/src/stylesheet.c @@ -57,38 +57,20 @@ struct _stylesheetwindow GtkWidget *max_width; GtkWidget *use_max; - struct text_style *cur_text_style; - struct layout_element *cur_layout_element; + struct style *cur_style; }; -static void text_changed_sig(GtkComboBox *combo, - struct _stylesheetwindow *s) -{ - int n; - GdkColor col; - - n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo)); - s->cur_text_style = s->ss->text_styles[n]; - - gtk_font_button_set_font_name(GTK_FONT_BUTTON(s->text_font), - s->cur_text_style->font); - - gdk_color_parse(s->cur_text_style->colour, &col); - gtk_color_button_set_color(GTK_COLOR_BUTTON(s->text_colour), &col); -} - - static void text_font_set_sig(GtkFontButton *widget, struct _stylesheetwindow *s) { const gchar *font; font = gtk_font_button_get_font_name(widget); - free(s->cur_text_style->font); - s->cur_text_style->font = strdup(font); + free(s->cur_style->font); + s->cur_style->font = strdup(font); - notify_style_update(s->p, s->cur_text_style); + notify_style_update(s->p, s->cur_style); } @@ -99,147 +81,84 @@ static void text_colour_set_sig(GtkColorButton *widget, guint16 al; gtk_color_button_get_color(widget, &col); - free(s->cur_text_style->colour); - s->cur_text_style->colour = gdk_color_to_string(&col); + free(s->cur_style->colour); + s->cur_style->colour = gdk_color_to_string(&col); al = gtk_color_button_get_alpha(widget); - s->cur_text_style->alpha = (double)al / 65535.0; + s->cur_style->alpha = (double)al / 65535.0; - notify_style_update(s->p, s->cur_text_style); -} - - -static void do_text(struct _stylesheetwindow *s, GtkWidget *b) -{ - GtkWidget *table; - GtkWidget *box; - GtkWidget *line; - GtkWidget *label; - GtkWidget *combo; - GtkWidget *vbox; - int i; - - vbox = gtk_vbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(b), vbox, TRUE, TRUE, 0); - - table = gtk_table_new(4, 2, FALSE); - gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 5); - gtk_table_set_row_spacings(GTK_TABLE(table), 5.0); - gtk_table_set_col_spacings(GTK_TABLE(table), 5.0); - - label = gtk_label_new("Style:"); - gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); - gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1); - combo = gtk_combo_box_new_text(); - gtk_table_attach_defaults(GTK_TABLE(table), combo, 1, 4, 0, 1); - - for ( i=0; i<s->ss->n_text_styles; i++ ) { - gtk_combo_box_append_text(GTK_COMBO_BOX(combo), - s->ss->text_styles[i]->name); - } - gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); - gtk_widget_set_size_request(GTK_WIDGET(combo), 300, -1); - g_signal_connect(G_OBJECT(combo), "changed", - G_CALLBACK(text_changed_sig), s); - - line = gtk_hseparator_new(); - gtk_table_attach_defaults(GTK_TABLE(table), line, 0, 4, 1, 2); - gtk_table_set_row_spacing(GTK_TABLE(table), 0, 10); - gtk_table_set_row_spacing(GTK_TABLE(table), 1, 10); - - label = gtk_label_new("Font:"); - gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); - gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3); - s->text_font = gtk_font_button_new_with_font("Sans 12"); - box = gtk_hbox_new(FALSE, 0); - gtk_table_attach_defaults(GTK_TABLE(table), box, 1, 2, 2, 3); - gtk_box_pack_start(GTK_BOX(box), s->text_font, FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(s->text_font), "font-set", - G_CALLBACK(text_font_set_sig), s); - - label = gtk_label_new("Colour:"); - gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); - gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4); - s->text_colour = gtk_color_button_new(); - box = gtk_hbox_new(FALSE, 0); - gtk_table_attach_defaults(GTK_TABLE(table), box, 1, 2, 3, 4); - gtk_box_pack_start(GTK_BOX(box), s->text_colour, FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(s->text_colour), "color-set", - G_CALLBACK(text_colour_set_sig), s); - - /* Force first update */ - text_changed_sig(GTK_COMBO_BOX(combo), s); + notify_style_update(s->p, s->cur_style); } static void margin_left_changed_sig(GtkSpinButton *spin, struct _stylesheetwindow *s) { - s->cur_layout_element->margin_left = gtk_spin_button_get_value(spin); - notify_layout_update(s->p, s->cur_layout_element); + s->cur_style->margin_left = gtk_spin_button_get_value(spin); + notify_style_update(s->p, s->cur_style); } static void margin_right_changed_sig(GtkSpinButton *spin, struct _stylesheetwindow *s) { - s->cur_layout_element->margin_right = gtk_spin_button_get_value(spin); - notify_layout_update(s->p, s->cur_layout_element); + s->cur_style->margin_right = gtk_spin_button_get_value(spin); + notify_style_update(s->p, s->cur_style); } static void margin_top_changed_sig(GtkSpinButton *spin, struct _stylesheetwindow *s) { - s->cur_layout_element->margin_top = gtk_spin_button_get_value(spin); - notify_layout_update(s->p, s->cur_layout_element); + s->cur_style->margin_top = gtk_spin_button_get_value(spin); + notify_style_update(s->p, s->cur_style); } static void margin_bottom_changed_sig(GtkSpinButton *spin, struct _stylesheetwindow *s) { - s->cur_layout_element->margin_bottom = gtk_spin_button_get_value(spin); - notify_layout_update(s->p, s->cur_layout_element); + s->cur_style->margin_bottom = gtk_spin_button_get_value(spin); + notify_style_update(s->p, s->cur_style); } static void offset_x_changed_sig(GtkSpinButton *spin, struct _stylesheetwindow *s) { - s->cur_layout_element->offset_x = gtk_spin_button_get_value(spin); - notify_layout_update(s->p, s->cur_layout_element); + s->cur_style->offset_x = gtk_spin_button_get_value(spin); + notify_style_update(s->p, s->cur_style); } static void offset_y_changed_sig(GtkSpinButton *spin, struct _stylesheetwindow *s) { - s->cur_layout_element->offset_y = gtk_spin_button_get_value(spin); - notify_layout_update(s->p, s->cur_layout_element); + s->cur_style->offset_y = gtk_spin_button_get_value(spin); + notify_style_update(s->p, s->cur_style); } static void halign_changed_sig(GtkComboBox *combo, struct _stylesheetwindow *s) { - s->cur_layout_element->halign = gtk_combo_box_get_active(combo); - notify_layout_update(s->p, s->cur_layout_element); + s->cur_style->halign = gtk_combo_box_get_active(combo); + notify_style_update(s->p, s->cur_style); } static void valign_changed_sig(GtkComboBox *combo, struct _stylesheetwindow *s) { - s->cur_layout_element->valign = gtk_combo_box_get_active(combo); - notify_layout_update(s->p, s->cur_layout_element); + s->cur_style->valign = gtk_combo_box_get_active(combo); + notify_style_update(s->p, s->cur_style); } static void max_changed_sig(GtkSpinButton *spin, struct _stylesheetwindow *s) { - s->cur_layout_element->max_width = gtk_spin_button_get_value(spin); - notify_layout_update(s->p, s->cur_layout_element); + s->cur_style->max_width = gtk_spin_button_get_value(spin); + notify_style_update(s->p, s->cur_style); } @@ -249,45 +168,56 @@ static void use_max_toggled_sig(GtkToggleButton *combo, int v; v = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(s->use_max)); - s->cur_layout_element->use_max_width = v; + s->cur_style->use_max_width = v; gtk_widget_set_sensitive(s->max_width, - s->cur_layout_element->use_max_width); - notify_layout_update(s->p, s->cur_layout_element); + s->cur_style->use_max_width); + notify_style_update(s->p, s->cur_style); } -static void layout_changed_sig(GtkComboBox *combo, +static void style_changed_sig(GtkComboBox *combo, struct _stylesheetwindow *s) { int n; + GdkColor col; n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo)); - s->cur_layout_element = s->ss->layout_elements[n]; + s->cur_style = s->ss->styles[n]; + /* FIXME: Handle default style */ gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->margin_left), - s->cur_layout_element->margin_left); + s->cur_style->margin_left); gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->margin_right), - s->cur_layout_element->margin_right); + s->cur_style->margin_right); gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->margin_bottom), - s->cur_layout_element->margin_bottom); + s->cur_style->margin_bottom); gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->margin_top), - s->cur_layout_element->margin_top); + s->cur_style->margin_top); gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->offset_x), - s->cur_layout_element->offset_x); + s->cur_style->offset_x); gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->offset_y), - s->cur_layout_element->offset_y); + s->cur_style->offset_y); gtk_combo_box_set_active(GTK_COMBO_BOX(s->halign), - s->cur_layout_element->halign); + s->cur_style->halign); gtk_combo_box_set_active(GTK_COMBO_BOX(s->valign), - s->cur_layout_element->valign); + s->cur_style->valign); gtk_widget_set_sensitive(s->max_width, - s->cur_layout_element->use_max_width); + s->cur_style->use_max_width); gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->max_width), - s->cur_layout_element->max_width); + s->cur_style->max_width); + + n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo)); + s->cur_style = s->ss->styles[n]; + + gtk_font_button_set_font_name(GTK_FONT_BUTTON(s->text_font), + s->cur_style->font); + + gdk_color_parse(s->cur_style->colour, &col); + gtk_color_button_set_color(GTK_COLOR_BUTTON(s->text_colour), &col); } @@ -307,13 +237,13 @@ static void do_layout(struct _stylesheetwindow *s, GtkWidget *b) gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); combo = gtk_combo_box_new_text(); - for ( i=0; i<s->ss->n_layout_elements; i++ ) { + for ( i=0; i<s->ss->n_styles; i++ ) { gtk_combo_box_append_text(GTK_COMBO_BOX(combo), - s->ss->layout_elements[i]->name); + s->ss->styles[i]->name); } gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); g_signal_connect(G_OBJECT(combo), "changed", - G_CALLBACK(layout_changed_sig), s); + G_CALLBACK(style_changed_sig), s); gtk_box_pack_start(GTK_BOX(box), combo, TRUE, TRUE, 0); line = gtk_hseparator_new(); @@ -428,8 +358,34 @@ static void do_layout(struct _stylesheetwindow *s, GtkWidget *b) g_signal_connect(G_OBJECT(s->max_width), "value-changed", G_CALLBACK(max_changed_sig), s); + /* Font/colour stuff */ + table = gtk_table_new(3, 2, FALSE); + gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 5); + gtk_table_set_row_spacings(GTK_TABLE(table), 5.0); + gtk_table_set_col_spacings(GTK_TABLE(table), 5.0); + + label = gtk_label_new("Font:"); + gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); + gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1); + s->text_font = gtk_font_button_new_with_font("Sans 12"); + box = gtk_hbox_new(FALSE, 0); + gtk_table_attach_defaults(GTK_TABLE(table), box, 1, 2, 0, 1); + gtk_box_pack_start(GTK_BOX(box), s->text_font, FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(s->text_font), "font-set", + G_CALLBACK(text_font_set_sig), s); + + label = gtk_label_new("Colour:"); + gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); + gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2); + s->text_colour = gtk_color_button_new(); + box = gtk_hbox_new(FALSE, 0); + gtk_table_attach_defaults(GTK_TABLE(table), box, 1, 2, 1, 2); + gtk_box_pack_start(GTK_BOX(box), s->text_colour, FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(s->text_colour), "color-set", + G_CALLBACK(text_colour_set_sig), s); + /* Force first update */ - layout_changed_sig(GTK_COMBO_BOX(combo), s); + style_changed_sig(GTK_COMBO_BOX(combo), s); } @@ -442,115 +398,85 @@ static gint destroy_stylesheet_sig(GtkWidget *w, struct _stylesheetwindow *s) } -static void add_text_style(StyleSheet *ss, struct text_style *st) -{ - int n = ss->n_text_styles; - ss->text_styles = realloc(ss->text_styles, - (n+1)*sizeof(st)); - - ss->text_styles[n] = st; - - ss->n_text_styles = n+1; -} - - -static struct text_style *new_text_style(StyleSheet *ss, const char *name) +static struct style *new_style(StyleSheet *ss, const char *name) { - struct text_style *st; - - st = malloc(sizeof(*st)); - if ( st == NULL ) return NULL; - - st->name = strdup(name); - st->colour = strdup("#000000000000"); /* Black */ - st->alpha = 1.0; - - add_text_style(ss, st); - - return st; -} - - -static struct layout_element *new_layout_element(StyleSheet *ss, - const char *name) -{ - struct layout_element *ly; + struct style *sty; int n; + struct style **styles_new; - ly = malloc(sizeof(*ly)); - if ( ly == NULL ) return NULL; - - ly->name = strdup(name); - - n = ss->n_layout_elements; - ss->layout_elements = realloc(ss->layout_elements, (n+1)*sizeof(ly)); - /* Yes, the size of the pointer */ + sty = malloc(sizeof(*sty)); + if ( sty == NULL ) return NULL; - ss->layout_elements[n] = ly; - ss->n_layout_elements = n+1; + n = ss->n_styles; + styles_new = realloc(ss->styles, (n+1)*sizeof(sty)); + if ( styles_new == NULL ) { + free(sty); + return NULL; + } + ss->styles = styles_new; + ss->styles[n] = sty; + ss->n_styles = n+1; - return ly; + return sty; } static void default_stylesheet(StyleSheet *ss) { - struct text_style *st; - struct layout_element *ly; - - st = new_text_style(ss, "Slide title"); - st->font = strdup("Sans 40"); - ly = new_layout_element(ss, st->name); - ly->text_style = st; - ly->margin_left = 20.0; - ly->margin_right = 20.0; - ly->margin_top = 20.0; - ly->margin_bottom = 20.0; - ly->halign = J_CENTER; - ly->valign = V_TOP; - ly->offset_x = 0.0; - ly->offset_y = 0.0; /* irrelevant */ - - st = new_text_style(ss, "Presentation title"); - st->font = strdup("Sans 50"); - ly = new_layout_element(ss, st->name); - ly->text_style = st; - ly->margin_left = 20.0; - ly->margin_right = 20.0; - ly->margin_top = 20.0; - ly->margin_bottom = 20.0; - ly->halign = J_CENTER; - ly->valign = V_CENTER; - ly->offset_x = -200.0; - ly->offset_y = +300.0; - - st = new_text_style(ss, "Presentation author"); - st->font = strdup("Sans 30"); - ly = new_layout_element(ss, st->name); - ly->text_style = st; - ly->margin_left = 20.0; - ly->margin_right = 20.0; - ly->margin_top = 20.0; - ly->margin_bottom = 20.0; - ly->halign = J_CENTER; - ly->valign = V_CENTER; - ly->offset_x = +200.0; - ly->offset_y = -300.0; - - st = new_text_style(ss, "Running text"); - st->font = strdup("Sans 14"); - - ly = new_layout_element(ss, "Slide content"); - ly->text_style = st; - ly->margin_left = 20.0; - ly->margin_right = 20.0; - ly->margin_top = 20.0; - ly->margin_bottom = 20.0; - ly->halign = J_CENTER; - ly->valign = V_CENTER; - ly->offset_x = +200.0; - ly->offset_y = -300.0; - + struct style *sty; + + /* Default style must be first */ + sty = new_style(ss, "Default"); + sty->font = strdup("Sans 18"); + sty->colour = strdup("#000000000000"); /* Black */ + sty->alpha = 1.0; + sty->margin_left = 20.0; + sty->margin_right = 20.0; + sty->margin_top = 20.0; + sty->margin_bottom = 20.0; + sty->halign = J_CENTER; /* Ignored */ + sty->valign = V_CENTER; /* Ignored */ + sty->offset_x = 0.0; /* Ignored */ + sty->offset_y = 0.0; /* Ignored */ + + sty = new_style(ss, "Slide title"); + sty->font = strdup("Sans 40"); + sty->colour = strdup("#000000000000"); /* Black */ + sty->alpha = 1.0; + sty->margin_left = 20.0; + sty->margin_right = 20.0; + sty->margin_top = 20.0; + sty->margin_bottom = 20.0; + sty->halign = J_CENTER; + sty->valign = V_TOP; + sty->offset_x = 0.0; + sty->offset_y = 0.0; /* irrelevant */ + + sty = new_style(ss, "Presentation title"); + sty->font = strdup("Sans 50"); + sty->colour = strdup("#000000000000"); /* Black */ + sty->alpha = 1.0; + sty->margin_left = 20.0; + sty->margin_right = 20.0; + sty->margin_top = 20.0; + sty->margin_bottom = 20.0; + sty->halign = J_CENTER; + sty->valign = V_CENTER; + sty->offset_x = -200.0; + sty->offset_y = +300.0; + + sty = new_style(ss, "Presentation author"); + sty->font = strdup("Sans 30"); + sty->colour = strdup("#000000000000"); /* Black */ + sty->alpha = 1.0; + sty->margin_left = 20.0; + sty->margin_right = 20.0; + sty->margin_top = 20.0; + sty->margin_bottom = 20.0; + sty->halign = J_CENTER; + sty->valign = V_CENTER; + sty->offset_x = +200.0; + sty->offset_y = -300.0; } @@ -561,10 +487,8 @@ StyleSheet *new_stylesheet() ss = calloc(1, sizeof(struct _stylesheet)); if ( ss == NULL ) return NULL; - ss->n_text_styles = 0; - ss->text_styles = NULL; - ss->n_layout_elements = 0; - ss->layout_elements = NULL; + ss->n_styles = 0; + ss->styles = NULL; default_stylesheet(ss); return ss; @@ -622,8 +546,8 @@ StylesheetWindow *open_stylesheet(struct presentation *p) s->p = p; s->ss = p->ss; - s->cur_text_style = NULL; - s->cur_layout_element = NULL; + s->cur_style = NULL; + s->cur_style = NULL; s->window = gtk_dialog_new_with_buttons("Stylesheet", GTK_WINDOW(p->window), 0, @@ -639,12 +563,6 @@ StylesheetWindow *open_stylesheet(struct presentation *p) text_box = gtk_vbox_new(FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(text_box), 12); gtk_notebook_append_page(GTK_NOTEBOOK(nb), text_box, - gtk_label_new("Text styles")); - do_text(s, text_box); - - text_box = gtk_vbox_new(FALSE, 0); - gtk_container_set_border_width(GTK_CONTAINER(text_box), 12); - gtk_notebook_append_page(GTK_NOTEBOOK(nb), text_box, gtk_label_new("Slide layout")); do_layout(s, text_box); diff --git a/src/stylesheet.h b/src/stylesheet.h index 8f9733e..4b7f7fb 100644 --- a/src/stylesheet.h +++ b/src/stylesheet.h @@ -28,15 +28,6 @@ #endif -struct text_style -{ - char *name; - char *font; - char *colour; - double alpha; -}; - - enum justify { J_LEFT = 0, @@ -53,10 +44,9 @@ enum vert_pos }; -struct layout_element +struct style { char *name; - struct text_style *text_style; double margin_left; double margin_right; @@ -70,22 +60,19 @@ struct layout_element double offset_x; double offset_y; + + char *font; + char *colour; + double alpha; }; struct _stylesheet { - /* Slide layout */ - struct layout_element **layout_elements; - int n_layout_elements; - - /* Normal text styles */ - struct text_style **text_styles; - int n_text_styles; + struct style **styles; + int n_styles; /* Background stuff */ - - /* Image styles */ }; diff --git a/src/tool_text.c b/src/tool_text.c new file mode 100644 index 0000000..9419a12 --- /dev/null +++ b/src/tool_text.c @@ -0,0 +1,203 @@ +/* + * tool_text.c + * + * Colloquium - A tiny presentation program + * + * Copyright (c) 2011 Thomas White <taw@bitwiz.org.uk> + * + * This program 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 <string.h> +#include <assert.h> + +#include "presentation.h" +#include "objects.h" +#include "mainwindow.h" + + +struct object *add_text_object(struct slide *s, double x, double y, + struct style *sty) +{ + struct object *new; + + new = new_object(TEXT, sty); + + new->x = x; new->y = y; + new->bb_width = 10.0; + new->bb_height = 40.0; + new->text = malloc(1); + new->text[0] = '\0'; + new->text_len = 1; + new->insertion_point = 0; + new->layout = NULL; + new->fontdesc = NULL; + + if ( add_object_to_slide(s, new) ) { + free_object(new); + return NULL; + } + s->object_seq++; + + return new; +} + + +void insert_text(struct object *o, char *t) +{ + char *tmp; + size_t tlen, olen; + int i; + + assert(o->type == TEXT); + tlen = strlen(t); + olen = strlen(o->text); + + if ( tlen + olen + 1 > o->text_len ) { + + char *try; + + try = realloc(o->text, o->text_len + tlen + 64); + if ( try == NULL ) return; /* Failed to insert */ + o->text = try; + o->text_len += 64; + o->text_len += tlen; + + } + + tmp = malloc(o->text_len); + if ( tmp == NULL ) return; + + for ( i=0; i<o->insertion_point; i++ ) { + tmp[i] = o->text[i]; + } + for ( i=0; i<tlen; i++ ) { + tmp[i+o->insertion_point] = t[i]; + } + for ( i=0; i<olen-o->insertion_point; i++ ) { + tmp[i+o->insertion_point+tlen] = o->text[i+o->insertion_point]; + } + tmp[olen+tlen] = '\0'; + memcpy(o->text, tmp, o->text_len); + free(tmp); + + o->insertion_point += tlen; + o->parent->object_seq++; + o->empty = 0; +} + + +void set_text_style(struct object *o, struct style *sty) +{ + assert(o->type == TEXT); + o->style = sty; + o->parent->object_seq++; +} + + +static int find_prev_index(const char *t, int p) +{ + int i, nback; + + if ( p == 0 ) return 0; + + if ( !(t[p-1] & 0x80) ) { + nback = 1; + } else { + nback = 0; + for ( i=1; i<=6; i++ ) { + if ( p-i == 0 ) return 0; + if ( !(t[p-i] & 0xC0) ) nback++; + } + } + + return p - nback; +} + + +static int find_next_index(const char *t, int p) +{ + int i, nfor; + + if ( t[p] == '\0' ) return p; + + if ( !(t[p+1] & 0x80) ) { + nfor = 1; + } else { + nfor = 0; + for ( i=1; i<=6; i++ ) { + if ( t[p+i] == '\0' ) return p+i; + if ( !(t[p+i] & 0xC0) ) nfor++; + } + } + + return p + nfor; +} + + +void handle_text_backspace(struct object *o) +{ + int prev_index; + + assert(o->type == TEXT); + + if ( o->insertion_point == 0 ) return; /* Nothing to delete */ + + prev_index = find_prev_index(o->text, o->insertion_point); + + memmove(o->text+prev_index, o->text+o->insertion_point, + o->text_len-o->insertion_point); + + o->insertion_point = prev_index; + + if ( strlen(o->text) == 0 ) o->empty = 1; + + o->parent->object_seq++; +} + + +void move_cursor_left(struct object *o) +{ + o->insertion_point = find_prev_index(o->text, o->insertion_point); +} + + +void move_cursor_right(struct object *o) +{ + o->insertion_point = find_next_index(o->text, o->insertion_point); +} + + +void position_caret(struct object *o, double x, double y) +{ + int idx, trail; + int xp, yp; + gboolean v; + + assert(o->type == TEXT); + + xp = (x - o->x)*PANGO_SCALE; + yp = (y - o->y)*PANGO_SCALE; + + v = pango_layout_xy_to_index(o->layout, xp, yp, &idx, &trail); + + o->insertion_point = idx+trail; +} diff --git a/src/tool_text.h b/src/tool_text.h new file mode 100644 index 0000000..cd190ae --- /dev/null +++ b/src/tool_text.h @@ -0,0 +1,39 @@ +/* + * tool_text.h + * + * Colloquium - A tiny presentation program + * + * Copyright (c) 2011 Thomas White <taw@bitwiz.org.uk> + * + * This program 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 TOOL_TEXT_H +#define TOOL_TEXT_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +extern struct object *add_text_object(struct slide *s, double x, double y, + struct style *sty); +extern void insert_text(struct object *o, char *t); +extern void handle_text_backspace(struct object *o); +extern void move_cursor_left(struct object *o); +extern void move_cursor_right(struct object *o); +extern void position_caret(struct object *o, double x, double y); + + +#endif /* TOOL_TEXT_H */ |