@@ -180,11 +180,11 @@
180 180 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
181 181 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
struct {
182 182 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
Blob all; /* array of footnotes */
183 183 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
int nLbled; /* number of labeled footnotes found during the first pass */
184 184 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
int nMarks; /* counts distinct indices found during the second pass */
185 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- struct footnote misref; /* nUsed counts misreferences, index must be -1 */
185 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ struct footnote misref; /* nUsed counts misreferences, iMark must be -1 */
186 186 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
} notes;
187 187 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
};
188 188 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
189 189 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/* html_tag -- structure for quick HTML tag search (inspired from discount) */
190 190 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
struct html_tag {
@@ -271,10 +271,28 @@
271 271 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
static int cmp_link_ref_sort(const void *a, const void *b){
272 272 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
struct link_ref *lra = (void *)a;
273 273 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
struct link_ref *lrb = (void *)b;
274 274 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return blob_compare(&lra->id, &lrb->id);
275 275 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
276 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
277 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* cmp_footnote_id -- comparison function for footnotes qsort.
278 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ * Empty IDs sort last (in undetermined order).
279 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ * Equal IDs are sorted in the REVERSED order of definition in the source */
280 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ static int cmp_footnote_id(const void *fna, const void *fnb){
281 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const struct footnote *a = fna, *b = fnb;
282 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const int szA = blob_size(&a->id), szB = blob_size(&b->id);
283 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( szA ){
284 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( szB ){
285 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int cmp = blob_compare(&a->id, &b->id);
286 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( cmp ) return cmp;
287 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else return -1;
288 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else return szB ? 1 : 0;
289 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* ids are equal and non-empty */
290 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( a->defno < b->defno ) return -1;
291 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( a->defno > b->defno ) return 1;
292 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return 0; /* should never reach here */
293 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
276 294 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
277 295 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/* cmp_footnote_sort -- comparison function for footnotes qsort.
278 296 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
* Unreferenced footnotes (when nUsed == 0) sort last and
279 297 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
* are sorted in the order of definition in the source */
280 298 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
static int cmp_footnote_sort(const void *fna, const void *fnb){
@@ -1053,13 +1071,13 @@
1053 1071 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_append(link, blob_buffer(&lr->link), blob_size(&lr->link));
1054 1072 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_append(title, blob_buffer(&lr->title), blob_size(&lr->title));
1055 1073 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return 0;
1056 1074 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
1057 1075 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
1058 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- /* get_footnote() is invoked during the second pass
1059 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- * on success: fill text and return positive footnote's index
1060 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- * on failure: return -1 */
1076 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* get_footnote() -- find a footnote by label, invoked during the 2nd pass.
1077 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ * On success returns a footnote (after incrementing its nUsed field),
1078 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ * otherwise returns NULL */
1061 1079 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
static const struct footnote* get_footnote(
1062 1080 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
struct render *rndr,
1063 1081 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *data,
1064 1082 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
size_t size
1065 1083 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
){
@@ -1081,10 +1099,11 @@
1081 1099 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
assert( fn->nUsed > 0 );
1082 1100 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
cleanup:
1083 1101 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
release_work_buffer( rndr, id );
1084 1102 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return fn;
1085 1103 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
1104 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1086 1105 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/* Adds unlabeled footnote to the rndr.
1087 1106 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
* If text is blank then returns 0,
1088 1107 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
* otherwise returns the address of the added footnote. */
1089 1108 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
static inline const struct footnote* add_inline_footnote(
1090 1109 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
struct render *rndr,
@@ -2538,29 +2557,71 @@
2538 2557 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
end += 1;
2539 2558 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
2540 2559 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
beg = end;
2541 2560 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
2542 2561 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
2543 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- assert( rndr.notes.nMarks==0 );
2562 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
2544 2563 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/* sorting the reference array */
2545 2564 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( blob_size(&rndr.refs) ){
2546 2565 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
qsort(blob_buffer(&rndr.refs),
2547 2566 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_size(&rndr.refs)/sizeof(struct link_ref),
2548 2567 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
sizeof(struct link_ref),
2549 2568 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
cmp_link_ref_sort);
2550 2569 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
2551 2570 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
rndr.notes.nLbled = COUNT_FOOTNOTES(&rndr.notes.all);
2552 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- /* sorting the footnotes array by id */
2553 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if( rndr.notes.nLbled ){
2571 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
2572 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* sort footnotes by ID and join duplicates */
2573 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( rndr.notes.nLbled > 1 ){
2554 2574 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
fn = CAST_AS_FOOTNOTES(&rndr.notes.all);
2555 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- qsort(fn, rndr.notes.nLbled, sizeof(struct footnote),
2556 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- cmp_link_ref_sort);
2557 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- for(i=0; i<rndr.notes.nLbled; i++){
2558 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- fn[i].index = i;
2575 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ qsort(fn, rndr.notes.nLbled, sizeof(struct footnote), cmp_footnote_id);
2576 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
2577 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* concatenate footnotes with equal labels */
2578 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for(i=0; i<rndr.notes.nLbled ;){
2579 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ struct footnote *x = fn + i;
2580 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ size_t j = i+1, k = blob_size(&x->text) + 64;
2581 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ while(j<rndr.notes.nLbled && !blob_compare(&x->id, &fn[j].id)){
2582 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ k += blob_size(&fn[j].text) + 10;
2583 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ j++;
2584 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2585 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( i+1<j ){
2586 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Blob tmp = empty_blob;
2587 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_reserve(&tmp, k);
2588 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append_string(&tmp, "<ul class='footnote-joined'>\n");
2589 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for(k=i; k<j; k++){
2590 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ struct footnote *y = fn + k;
2591 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append_string(&tmp, "<li>");
2592 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append(&tmp, blob_buffer(&y->text), blob_size(&y->text));
2593 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append_string(&tmp, "</li>\n");
2594 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
2595 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* free memory buffer */
2596 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_reset(&y->text);
2597 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( k!=i ){
2598 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_reset(&y->id);
2599 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* invalidate redundant elements (this is optional) */
2600 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ memset(y,0,sizeof(struct footnote));
2601 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ y->index = y->defno = y->iMark = y->nUsed = -42;
2602 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2603 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2604 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append_string(&tmp, "</ul>\n");
2605 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ x->text = tmp;
2606 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2607 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ i = j;
2559 2608 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
2560 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- /* FIXME: handle footnotes with duplicated labels */
2609 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
2610 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* move redundant elements to the end of array and truncate/resize */
2611 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ qsort(fn, rndr.notes.nLbled, sizeof(struct footnote), cmp_footnote_id);
2612 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ i = rndr.notes.nLbled;
2613 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ while( i && !blob_size(&fn[i-1].id) ){ i--; }
2614 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ rndr.notes.nLbled = i;
2615 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_truncate( &rndr.notes.all, i*sizeof(struct footnote) );
2616 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
2617 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ assert( COUNT_FOOTNOTES(&rndr.notes.all) == rndr.notes.nLbled );
2618 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fn = CAST_AS_FOOTNOTES(&rndr.notes.all);
2619 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for(i=0; i<rndr.notes.nLbled; i++){
2620 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fn[i].index = i;
2561 2621 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
2622 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ assert( rndr.notes.nMarks==0 );
2562 2623 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
2563 2624 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/* second pass: actual rendering */
2564 2625 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( rndr.make.prolog ) rndr.make.prolog(ob, rndr.make.opaque);
2565 2626 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
parse_block(ob, &rndr, blob_buffer(&text), blob_size(&text));
2566 2627 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
2567 2628 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!