Fossil

Diff
Login

Differences From Artifact [954e6b45cb]:

To Artifact [84dbba2fcd]:


178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
  int nBlobCache;                /* Number of entries in aBlobCache */
  struct Blob *aBlobCache[20];   /* Cache of Blobs available for reuse */

  struct {
    Blob all;    /* array of footnotes */
    int nLbled;  /* number of labeled footnotes found during the first pass */
    int nMarks;  /* counts distinct indices found during the second pass    */
    struct footnote misref; /* nUsed counts misreferences, index must be -1 */
  } notes;
};

/* html_tag -- structure for quick HTML tag search (inspired from discount) */
struct html_tag {
  const char *text;
  int size;







|







178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
  int nBlobCache;                /* Number of entries in aBlobCache */
  struct Blob *aBlobCache[20];   /* Cache of Blobs available for reuse */

  struct {
    Blob all;    /* array of footnotes */
    int nLbled;  /* number of labeled footnotes found during the first pass */
    int nMarks;  /* counts distinct indices found during the second pass    */
    struct footnote misref; /* nUsed counts misreferences, iMark must be -1 */
  } notes;
};

/* html_tag -- structure for quick HTML tag search (inspired from discount) */
struct html_tag {
  const char *text;
  int size;
269
270
271
272
273
274
275


















276
277
278
279
280
281
282

/* cmp_link_ref_sort -- comparison function for link_ref qsort */
static int cmp_link_ref_sort(const void *a, const void *b){
  struct link_ref *lra = (void *)a;
  struct link_ref *lrb = (void *)b;
  return blob_compare(&lra->id, &lrb->id);
}



















/* cmp_footnote_sort -- comparison function for footnotes qsort.
 * Unreferenced footnotes (when nUsed == 0) sort last and
 * are sorted in the order of definition in the source */
static int cmp_footnote_sort(const void *fna, const void *fnb){
  const struct footnote *a = fna, *b = fnb;
  int i, j;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300

/* cmp_link_ref_sort -- comparison function for link_ref qsort */
static int cmp_link_ref_sort(const void *a, const void *b){
  struct link_ref *lra = (void *)a;
  struct link_ref *lrb = (void *)b;
  return blob_compare(&lra->id, &lrb->id);
}

/* cmp_footnote_id -- comparison function for footnotes qsort.
 * Empty IDs sort last (in undetermined order).
 * Equal IDs are sorted in the REVERSED order of definition in the source */
static int cmp_footnote_id(const void *fna, const void *fnb){
  const struct footnote *a = fna, *b = fnb;
  const int szA = blob_size(&a->id), szB = blob_size(&b->id);
  if( szA ){
    if( szB ){
      int cmp = blob_compare(&a->id, &b->id);
      if( cmp ) return cmp;
    }else return -1;
  }else return szB ? 1 : 0;
  /* ids are equal and non-empty */
  if( a->defno < b->defno ) return -1;
  if( a->defno > b->defno ) return  1;
  return 0; /* should never reach here */
}

/* cmp_footnote_sort -- comparison function for footnotes qsort.
 * Unreferenced footnotes (when nUsed == 0) sort last and
 * are sorted in the order of definition in the source */
static int cmp_footnote_sort(const void *fna, const void *fnb){
  const struct footnote *a = fna, *b = fnb;
  int i, j;
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
  blob_reset(link);
  blob_reset(title);
  blob_append(link, blob_buffer(&lr->link), blob_size(&lr->link));
  blob_append(title, blob_buffer(&lr->title), blob_size(&lr->title));
  return 0;
}

/* get_footnote() is invoked during the second pass
 * on success: fill text and return positive footnote's index
 * on failure: return -1 */
static const struct footnote* get_footnote(
  struct render *rndr,
  const char *data,
  size_t size
){
  struct footnote *fn = NULL;
  struct Blob *id = new_work_buffer(rndr);







|
|
|







1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
  blob_reset(link);
  blob_reset(title);
  blob_append(link, blob_buffer(&lr->link), blob_size(&lr->link));
  blob_append(title, blob_buffer(&lr->title), blob_size(&lr->title));
  return 0;
}

/* get_footnote() -- find a footnote by label, invoked during the 2nd pass.
 * On success returns a footnote (after incrementing its nUsed field),
 * otherwise returns NULL */
static const struct footnote* get_footnote(
  struct render *rndr,
  const char *data,
  size_t size
){
  struct footnote *fn = NULL;
  struct Blob *id = new_work_buffer(rndr);
1079
1080
1081
1082
1083
1084
1085

1086
1087
1088
1089
1090
1091
1092
  fn->nUsed++;
  assert( fn->iMark > 0 );
  assert( fn->nUsed > 0 );
cleanup:
  release_work_buffer( rndr, id );
  return fn;
}

/* Adds unlabeled footnote to the rndr.
 * If text is blank then returns 0,
 * otherwise returns the address of the added footnote. */
static inline const struct footnote* add_inline_footnote(
  struct render *rndr,
  const char *text,
  size_t size







>







1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
  fn->nUsed++;
  assert( fn->iMark > 0 );
  assert( fn->nUsed > 0 );
cleanup:
  release_work_buffer( rndr, id );
  return fn;
}

/* Adds unlabeled footnote to the rndr.
 * If text is blank then returns 0,
 * otherwise returns the address of the added footnote. */
static inline const struct footnote* add_inline_footnote(
  struct render *rndr,
  const char *text,
  size_t size
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552

2553
2554
2555
2556

2557















2558







2559






2560






2561






2562
2563
2564
2565
2566
2567
2568
          blob_append_char(&text, '\n');
        }
        end += 1;
      }
      beg = end;
    }
  }
  assert( rndr.notes.nMarks==0 );
  /* sorting the reference array */
  if( blob_size(&rndr.refs) ){
    qsort(blob_buffer(&rndr.refs),
          blob_size(&rndr.refs)/sizeof(struct link_ref),
          sizeof(struct link_ref),
          cmp_link_ref_sort);
  }
  rndr.notes.nLbled = COUNT_FOOTNOTES(&rndr.notes.all);
  /* sorting the footnotes array by id */

  if( rndr.notes.nLbled ){
    fn = CAST_AS_FOOTNOTES(&rndr.notes.all);
    qsort(fn, rndr.notes.nLbled, sizeof(struct footnote),
          cmp_link_ref_sort);

    for(i=0; i<rndr.notes.nLbled; i++){















      fn[i].index = i;







    }






    /* FIXME: handle footnotes with duplicated labels */






  }







  /* second pass: actual rendering */
  if( rndr.make.prolog ) rndr.make.prolog(ob, rndr.make.opaque);
  parse_block(ob, &rndr, blob_buffer(&text), blob_size(&text));

  if( (blob_size(&rndr.notes.all) || rndr.notes.misref.nUsed) ){








|








|
>
|

|
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>

>
>
>
>
>
>







2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
          blob_append_char(&text, '\n');
        }
        end += 1;
      }
      beg = end;
    }
  }

  /* sorting the reference array */
  if( blob_size(&rndr.refs) ){
    qsort(blob_buffer(&rndr.refs),
          blob_size(&rndr.refs)/sizeof(struct link_ref),
          sizeof(struct link_ref),
          cmp_link_ref_sort);
  }
  rndr.notes.nLbled = COUNT_FOOTNOTES(&rndr.notes.all);

  /* sort footnotes by ID and join duplicates */
  if( rndr.notes.nLbled > 1 ){
    fn = CAST_AS_FOOTNOTES(&rndr.notes.all);
    qsort(fn, rndr.notes.nLbled, sizeof(struct footnote), cmp_footnote_id);

    /* concatenate footnotes with equal labels */
    for(i=0; i<rndr.notes.nLbled ;){
      struct footnote *x = fn + i;
      size_t j = i+1, k = blob_size(&x->text) + 64;
      while(j<rndr.notes.nLbled && !blob_compare(&x->id, &fn[j].id)){
        k += blob_size(&fn[j].text) + 10;
        j++;
      }
      if( i+1<j ){
        Blob tmp = empty_blob;
        blob_reserve(&tmp, k);
        blob_append_string(&tmp, "<ul class='footnote-joined'>\n");
        for(k=i; k<j; k++){
          struct footnote *y = fn + k;
          blob_append_string(&tmp, "<li>");
          blob_append(&tmp, blob_buffer(&y->text), blob_size(&y->text));
          blob_append_string(&tmp, "</li>\n");

          /* free memory buffer */
          blob_reset(&y->text);
          if( k!=i ){
            blob_reset(&y->id);
            /* invalidate redundant elements (this is optional) */
            memset(y,0,sizeof(struct footnote));
            y->index = y->defno = y->iMark = y->nUsed = -42;
          }
        }
        blob_append_string(&tmp, "</ul>\n");
        x->text = tmp;
      }
      i = j;
    }

    /* move redundant elements to the end of array and truncate/resize */
    qsort(fn, rndr.notes.nLbled, sizeof(struct footnote), cmp_footnote_id);
    i = rndr.notes.nLbled;
    while( i && !blob_size(&fn[i-1].id) ){ i--; }
    rndr.notes.nLbled = i;
    blob_truncate( &rndr.notes.all, i*sizeof(struct footnote) );
  }
  assert( COUNT_FOOTNOTES(&rndr.notes.all) == rndr.notes.nLbled );
  fn = CAST_AS_FOOTNOTES(&rndr.notes.all);
  for(i=0; i<rndr.notes.nLbled; i++){
    fn[i].index = i;
  }
  assert( rndr.notes.nMarks==0 );

  /* second pass: actual rendering */
  if( rndr.make.prolog ) rndr.make.prolog(ob, rndr.make.opaque);
  parse_block(ob, &rndr, blob_buffer(&text), blob_size(&text));

  if( (blob_size(&rndr.notes.all) || rndr.notes.misref.nUsed) ){