aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.org.uk>2016-03-28 22:28:21 +0200
committerThomas White <taw@bitwiz.org.uk>2016-03-28 22:51:11 +0200
commitd4de5d06c2ac66b15aa01da3f29dbb33ea270249 (patch)
treef8d1735975c4e0df11fc57304e94053958ea8c85
parent4def920737575625a8336a41a4310cc52052ce01 (diff)
Cursor stuff
-rw-r--r--src/frame.c118
-rw-r--r--src/frame.h14
-rw-r--r--src/sc_editor.c74
-rw-r--r--src/sc_editor.h1
4 files changed, 155 insertions, 52 deletions
diff --git a/src/frame.c b/src/frame.c
index a541999..591dafd 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -523,3 +523,121 @@ void render_paragraph(cairo_t *cr, Paragraph *para, ImageStore *is,
}
}
+
+
+size_t end_offset_of_para(struct frame *fr, int pn)
+{
+ int i;
+ size_t total = 0;
+ for ( i=0; i<fr->paras[pn]->n_runs; i++ ) {
+ total += fr->paras[pn]->runs[i].len_bytes;
+ }
+ return total;
+}
+
+
+/* Local x,y in paragraph -> text offset */
+static int text_para_pos(Paragraph *para, double x, double y, int *ptrail)
+{
+ int idx;
+ pango_layout_xy_to_index(para->layout, pango_units_from_double(x),
+ pango_units_from_double(y), &idx, ptrail);
+ return idx;
+}
+
+
+int find_cursor(struct frame *fr, double x, double y,
+ int *ppara, int *ppos, int *ptrail)
+{
+ double pos = fr->pad_t;
+ int i;
+
+ for ( i=0; i<fr->n_paras; i++ ) {
+ double npos = pos + fr->paras[i]->height;
+ if ( npos > y ) {
+ *ppara = i;
+ if ( fr->paras[i]->type == PARA_TYPE_TEXT ) {
+ *ppos = text_para_pos(fr->paras[i], x-fr->pad_l,
+ y-pos, ptrail);
+ } else {
+ *ppos = 0;
+ }
+ return 0;
+ }
+ pos = npos;
+ }
+
+ /* Pretend it's in the last paragraph */
+ pos -= fr->paras[fr->n_paras-1]->height;
+ *ppara = fr->n_paras - 1;
+ *ppos = text_para_pos(fr->paras[i], x - fr->pad_l, y - pos, ptrail);
+ return 0;
+}
+
+
+int get_cursor_pos(struct frame *fr, int cursor_para, int cursor_pos,
+ double *cx, double *cy, double *ch)
+{
+ Paragraph *para;
+ PangoRectangle rect;
+ int i;
+ double py = 0.0;
+
+ if ( cursor_para > fr->n_paras ) {
+ fprintf(stderr, "Cursor paragraph number is too high!\n");
+ return 1;
+ }
+
+ para = fr->paras[cursor_para];
+
+ if ( para->type != PARA_TYPE_TEXT ) return 1;
+
+ pango_layout_get_cursor_pos(para->layout, cursor_pos, &rect, NULL);
+
+ for ( i=0; i<cursor_para; i++ ) {
+ py += fr->paras[i]->height;
+ }
+ *cx = pango_units_to_double(rect.x) + fr->pad_l;
+ *cy = pango_units_to_double(rect.y) + fr->pad_t + py;
+ *ch = pango_units_to_double(rect.height);
+ return 0;
+}
+
+
+void cursor_moveh(struct frame *fr, int *cpara, int *cpos, int *ctrail,
+ signed int dir)
+{
+ Paragraph *para = fr->paras[*cpara];
+
+ if ( (*cpos+*ctrail == end_offset_of_para(fr, *cpara)) && (dir > 0) ) {
+ if ( *cpara < fr->n_paras-1 ) {
+ (*cpara)++;
+ *cpos = 0;
+ *ctrail = 0;
+ return;
+ } else {
+ /* Can't move any further */
+ return;
+ }
+ }
+
+ if ( (*cpos+*ctrail == 0) && (dir < 0) ) {
+ if ( *cpara > 0 ) {
+ (*cpara)--;
+ *cpos = end_offset_of_para(fr, *cpara) - 1;
+ *ctrail = 1;
+ return;
+ } else {
+ /* Can't move any further */
+ return;
+ }
+ }
+ pango_layout_move_cursor_visually(para->layout, 1, *cpos, *ctrail,
+ dir, cpos, ctrail);
+}
+
+
+void cursor_movev(struct frame *fr, int *cpara, int *cpos, int *ctrail,
+ signed int dir)
+{
+}
diff --git a/src/frame.h b/src/frame.h
index b300c8d..39fe13f 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -125,4 +125,18 @@ extern void add_image_para(struct frame *fr, const char *filename,
extern void wrap_paragraph(Paragraph *para, PangoContext *pc, double w);
+extern size_t end_offset_of_para(struct frame *fr, int pn);
+
+extern int find_cursor(struct frame *fr, double x, double y,
+ int *ppara, int *ppos, int *ptrail);
+
+extern int get_cursor_pos(struct frame *fr, int cursor_para, int cursor_pos,
+ double *cx, double *cy, double *ch);
+
+extern void cursor_moveh(struct frame *fr, int *cpara, int *cpos, int *ctrail,
+ signed int dir);
+
+extern void cursor_movev(struct frame *fr, int *cpara, int *cpos, int *ctrail,
+ signed int dir);
+
#endif /* FRAME_H */
diff --git a/src/sc_editor.c b/src/sc_editor.c
index 1658122..c61c51a 100644
--- a/src/sc_editor.c
+++ b/src/sc_editor.c
@@ -362,27 +362,6 @@ void sc_editor_delete_selected_frame(SCEditor *e)
}
-static int find_cursor(struct frame *fr, double x, double y,
- int *ppara, int *ppos)
-{
- *ppara = 0;
- *ppos = 0;
- return 0;
-}
-
-
-static void move_cursor_back(SCEditor *e)
-{
- /* FIXME */
-}
-
-
-void advance_cursor(SCEditor *e)
-{
- /* FIXME */
-}
-
-
static gint destroy_sig(GtkWidget *window, SCEditor *e)
{
return 0;
@@ -420,23 +399,19 @@ static void draw_editing_box(cairo_t *cr, struct frame *fr)
}
-static void draw_caret(cairo_t *cr, struct frame *fr)
+static void draw_caret(cairo_t *cr, struct frame *fr, int cursor_para,
+ size_t cursor_pos, int cursor_trail)
{
-#if 0
- double xposd, yposd, cx;
- double clow, chigh;
- PangoRectangle pos;
+ double cx, clow, chigh, h;
const double t = 1.8;
- pango_layout_get_cursor_pos(o->layout,
- o->insertion_point+o->insertion_trail,
- &pos, NULL);
+ if ( get_cursor_pos(fr, cursor_para, cursor_pos+cursor_trail,
+ &cx, &clow, &h) )
+ {
+ return;
+ }
- xposd = pos.x/PANGO_SCALE;
- cx = o->base.x - o->offs_x + xposd;
- yposd = pos.y/PANGO_SCALE;
- clow = o->base.y - o->offs_y + yposd;
- chigh = clow + (pos.height/PANGO_SCALE);
+ chigh = clow + h;
cairo_move_to(cr, cx, clow);
cairo_line_to(cr, cx, chigh);
@@ -454,7 +429,6 @@ static void draw_caret(cairo_t *cr, struct frame *fr)
cairo_set_source_rgb(cr, 0.86, 0.0, 0.0);
cairo_set_line_width(cr, 1.0);
cairo_stroke(cr);
-#endif
}
@@ -488,7 +462,8 @@ static void draw_overlay(cairo_t *cr, SCEditor *e)
draw_resize_handle(cr, x+w-20.0, y+h-20.0);
}
- draw_caret(cr, e->cursor_frame);
+ draw_caret(cr, e->cursor_frame, e->cursor_para, e->cursor_pos,
+ e->cursor_trail);
}
@@ -561,16 +536,6 @@ static gboolean draw_sig(GtkWidget *da, cairo_t *cr, SCEditor *e)
}
-static void move_cursor(SCEditor *e, signed int x, signed int y)
-{
- if ( x > 0 ) {
- advance_cursor(e);
- } else {
- move_cursor_back(e);
- }
-}
-
-
void insert_scblock(SCBlock *scblock, SCEditor *e)
{
#if 0
@@ -881,7 +846,8 @@ static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event,
e->cursor_frame = clicked;
find_cursor(clicked, x-fr->x, y-fr->y,
- &e->cursor_para, &e->cursor_pos);
+ &e->cursor_para, &e->cursor_pos,
+ &e->cursor_trail);
e->start_corner_x = event->x - e->border_offs_x;
e->start_corner_y = event->y - e->border_offs_y;
@@ -914,7 +880,7 @@ static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event,
e->selection = clicked;
e->cursor_frame = clicked;
find_cursor(clicked, x-clicked->x, y-clicked->y,
- &e->cursor_para, &e->cursor_pos);
+ &e->cursor_para, &e->cursor_pos, &e->cursor_trail);
}
@@ -1122,7 +1088,8 @@ static gboolean key_press_sig(GtkWidget *da, GdkEventKey *event,
case GDK_KEY_Left :
if ( e->selection != NULL ) {
- move_cursor(e, -1, 0);
+ cursor_moveh(e->cursor_frame, &e->cursor_para,
+ &e->cursor_pos, &e->cursor_trail, -1);
sc_editor_redraw(e);
}
claim = 1;
@@ -1130,7 +1097,8 @@ static gboolean key_press_sig(GtkWidget *da, GdkEventKey *event,
case GDK_KEY_Right :
if ( e->selection != NULL ) {
- move_cursor(e, +1, 0);
+ cursor_moveh(e->cursor_frame, &e->cursor_para,
+ &e->cursor_pos, &e->cursor_trail, +1);
sc_editor_redraw(e);
}
claim = 1;
@@ -1138,7 +1106,8 @@ static gboolean key_press_sig(GtkWidget *da, GdkEventKey *event,
case GDK_KEY_Up :
if ( e->selection != NULL ) {
- move_cursor(e, 0, -1);
+ cursor_movev(e->cursor_frame, &e->cursor_para,
+ &e->cursor_pos, &e->cursor_trail, -1);
sc_editor_redraw(e);
}
claim = 1;
@@ -1146,7 +1115,8 @@ static gboolean key_press_sig(GtkWidget *da, GdkEventKey *event,
case GDK_KEY_Down :
if ( e->selection != NULL ) {
- move_cursor(e, 0, +1);
+ cursor_movev(e->cursor_frame, &e->cursor_para,
+ &e->cursor_pos, &e->cursor_trail, +1);
sc_editor_redraw(e);
}
claim = 1;
diff --git a/src/sc_editor.h b/src/sc_editor.h
index 99afa50..eaa7f41 100644
--- a/src/sc_editor.h
+++ b/src/sc_editor.h
@@ -119,6 +119,7 @@ struct _sceditor
struct frame *cursor_frame;
int cursor_para; /* paragraph index */
int cursor_pos; /* character offset into paragraph */
+ int cursor_trail;
/* Border surrounding actual slide within drawingarea */
double border_offs_x;