Keep 'run' out of struct slide_pos
authorThomas White <taw@bitwiz.me.uk>
Thu, 10 Oct 2019 18:33:59 +0000 (20:33 +0200)
committerThomas White <taw@bitwiz.me.uk>
Thu, 10 Oct 2019 18:33:59 +0000 (20:33 +0200)
libstorycode/gtk/gtkslideview.c
libstorycode/slide_render_cairo.c
libstorycode/slide_render_cairo.h
libstorycode/storycode.y

index 6c23cad..82f0a7f 100644 (file)
@@ -192,7 +192,7 @@ static int gtksv_get_cursor_pos(SlideItem *item, Stylesheet *stylesheet,
        slide_item_get_padding(item, stylesheet, &padl, &padr, &padt, &padb,
                               slide_w, slide_h);
 
-       offs = slide_pos_trail_to_offset(item, cpos.para, cpos.run, cpos.pos, cpos.trail);
+       offs = slide_pos_trail_to_offset(item, cpos.para, cpos.pos, cpos.trail);
        pango_layout_get_cursor_pos(item->paras[cpos.para].layout, offs, &rect, NULL);
        *x = pango_units_to_double(rect.x) + padl;
        *y = pango_units_to_double(rect.y) + gtksv_para_top(item, cpos.para) + padt;
index e68e51e..bbfc0f9 100644 (file)
@@ -65,17 +65,66 @@ static int slide_positions_equal(struct slide_pos a, struct slide_pos b)
 }
 
 
-size_t slide_pos_trail_to_offset(SlideItem *item, int para, int run,
-                                        size_t offs, int trail)
+static int slide_which_run(struct slide_text_paragraph *para, size_t item_offs,
+                           size_t *run_offs)
+{
+       int run;
+       size_t pos = 0;
+
+       assert(para->n_runs > 0);
+
+       for ( run=0; run<para->n_runs; run++ ) {
+               size_t npos = pos + strlen(para->runs[run].text);
+               if ( npos >= item_offs ) break;
+               pos = npos;
+       }
+       if ( run_offs != NULL ) {
+               *run_offs = item_offs - pos;
+       }
+       return run;
+}
+
+
+static int slide_item_is_text(SlideItem *item)
+{
+       switch ( item->type ) {
+
+               case SLIDE_ITEM_TEXT : return 1;
+               case SLIDE_ITEM_IMAGE : return 0;
+               case SLIDE_ITEM_FOOTER : return 0;
+               case SLIDE_ITEM_SLIDETITLE : return 1;
+               case SLIDE_ITEM_PRESTITLE : return 1;
+
+               default :
+               fprintf(stderr, "Please update slide_item_is_text\n");
+               return 0;
+       }
+}
+
+
+size_t slide_pos_trail_to_offset(SlideItem *item, int para_num, size_t offs, int trail)
 {
        glong char_offs;
        char *ptr;
+       int run;
+       size_t run_offs;
+       size_t prev_len;
+       int j;
+       struct slide_text_paragraph *para;
+
+       if ( !slide_item_is_text(item) ) return offs;
 
-       char_offs = g_utf8_pointer_to_offset(item->paras[para].runs[run].text,
-                                            item->paras[para].runs[run].text+offs);
+       para = &item->paras[para_num];
+       run = slide_which_run(para, offs, &run_offs);
+
+       char_offs = g_utf8_pointer_to_offset(para->runs[run].text,
+                                            para->runs[run].text+run_offs);
        char_offs += trail;
-       ptr = g_utf8_offset_to_pointer(item->paras[para].runs[run].text, char_offs);
-       return ptr - item->paras[para].runs[run].text;
+       ptr = g_utf8_offset_to_pointer(para->runs[run].text, char_offs);
+
+       prev_len = 0;
+       for ( j=0; j<run; j++ ) prev_len += strlen(para->runs[j].text);
+       return prev_len + ptr - para->runs[run].text;
 }
 
 
@@ -181,9 +230,9 @@ static void render_text(SlideItem *item, cairo_t *cr, PangoContext *pc,
        }
 
        if ( !slide_positions_equal(sel_start, sel_end) ) {
-               sel_s = slide_pos_trail_to_offset(item, sel_start.para, sel_start.run,
+               sel_s = slide_pos_trail_to_offset(item, sel_start.para,
                                                  sel_start.pos, sel_start.trail);
-               sel_e = slide_pos_trail_to_offset(item, sel_end.para, sel_end.run,
+               sel_e = slide_pos_trail_to_offset(item, sel_end.para,
                                                  sel_end.pos, sel_end.trail);
        } else {
                sel_s = 0;
index f90a27c..808b661 100644 (file)
@@ -33,7 +33,6 @@
 struct slide_pos
 {
        int para;    /* Paragraph number (corresponding to narrative items) */
-       int run;     /* Run number */
        int pos;     /* Byte position within run (yes, really)  */
        int trail;   /* 1 = end of character, 0 = before */
 };
@@ -45,6 +44,6 @@ extern int slide_render_cairo(Slide *s, cairo_t *cr, ImageStore *is, Stylesheet
 
 extern int render_slides_to_pdf(Narrative *n, ImageStore *is, const char *filename);
 
-extern size_t slide_pos_trail_to_offset(SlideItem *item, int para_num, int run, size_t offs, int trail);
+extern size_t slide_pos_trail_to_offset(SlideItem *item, int para_num, size_t offs, int trail);
 
 #endif /* RENDER_H */
index 587db4a..f3c2653 100644 (file)
@@ -268,10 +268,18 @@ struct text_run **combine_paras(struct parse_many_paragraphs mp, int **pn_runs)
     combined_paras = malloc(mp.n_paras * sizeof(struct text_run *));
     n_runs = malloc(mp.n_paras * sizeof(int));
     for ( i=0; i<mp.n_paras; i++ ) {
-        for ( int j=0; j<mp.paras[i].n_runs; j++ ) {
+        if ( mp.paras[i].n_runs > 0 ) {
+            combined_paras[i] = mp.paras[i].runs;
+            n_runs[i] = mp.paras[i].n_runs;
+        } else {
+            /* Create a single dummy run */
+            struct text_run *run;
+            run = malloc(sizeof(struct text_run));
+            run->text = strdup("");
+            run->type = TEXT_RUN_NORMAL;
+            combined_paras[i] = run;
+            n_runs[i] = 1;
         }
-        combined_paras[i] = mp.paras[i].runs;
-        n_runs[i] = mp.paras[i].n_runs;
     }
 
     *pn_runs = n_runs;