File indexing completed on 2024-04-21 11:14:28
0001 /* 0002 * toc -- spit out a table of contents based on header blocks 0003 * 0004 * Copyright (C) 2008 Jjgod Jiang, David L Parsons 0005 * portions Copyright (C) 2011 Stefano D'Angelo 0006 * The redistribution terms are provided in the COPYRIGHT file that must 0007 * be distributed with this source code. 0008 */ 0009 #include "config.h" 0010 #include <stdio.h> 0011 #include <stdlib.h> 0012 #include <ctype.h> 0013 0014 #include "cstring.h" 0015 #include "markdown.h" 0016 #include "amalloc.h" 0017 0018 /* write an header index 0019 */ 0020 int 0021 mkd_toc(Document *p, char **doc) 0022 { 0023 Paragraph *tp, *srcp; 0024 int last_hnumber = 0; 0025 Cstring res; 0026 int size; 0027 int first = 1; 0028 extern void Csreparse(Cstring *, char *, int, mkd_flag_t); 0029 0030 0031 if ( !(doc && p && p->ctx) ) return -1; 0032 0033 *doc = 0; 0034 0035 if ( ! is_flag_set(p->ctx->flags, MKD_TOC) ) return 0; 0036 0037 CREATE(res); 0038 RESERVE(res, 100); 0039 0040 for ( tp = p->code; tp ; tp = tp->next ) { 0041 if ( tp->typ == SOURCE ) { 0042 for ( srcp = tp->down; srcp; srcp = srcp->next ) { 0043 if ( (srcp->typ == HDR) && srcp->text ) { 0044 0045 while ( last_hnumber > srcp->hnumber ) { 0046 if ( (last_hnumber - srcp->hnumber) > 1 ) 0047 Csprintf(&res, "\n"); 0048 Csprintf(&res, "</li>\n%*s</ul>\n%*s", 0049 last_hnumber-1, "", last_hnumber-1, ""); 0050 --last_hnumber; 0051 } 0052 0053 if ( last_hnumber == srcp->hnumber ) 0054 Csprintf(&res, "</li>\n"); 0055 else if ( (srcp->hnumber > last_hnumber) && !first ) 0056 Csprintf(&res, "\n"); 0057 0058 while ( srcp->hnumber > last_hnumber ) { 0059 Csprintf(&res, "%*s<ul>\n", last_hnumber, ""); 0060 if ( (srcp->hnumber - last_hnumber) > 1 ) 0061 Csprintf(&res, "%*s<li>\n", last_hnumber+1, ""); 0062 ++last_hnumber; 0063 } 0064 Csprintf(&res, "%*s<li><a href=\"#", srcp->hnumber, ""); 0065 mkd_string_to_anchor(T(srcp->text->text), 0066 S(srcp->text->text), 0067 (mkd_sta_function_t)Csputc, 0068 &res,1,p->ctx); 0069 Csprintf(&res, "\">"); 0070 Csreparse(&res, T(srcp->text->text), 0071 S(srcp->text->text), IS_LABEL); 0072 Csprintf(&res, "</a>"); 0073 0074 first = 0; 0075 } 0076 } 0077 } 0078 } 0079 0080 while ( last_hnumber > 0 ) { 0081 --last_hnumber; 0082 Csprintf(&res, "</li>\n%*s</ul>\n%*s", 0083 last_hnumber, "", last_hnumber, ""); 0084 } 0085 0086 if ( (size = S(res)) > 0 ) { 0087 /* null-terminate & strdup into a free()able memory chunk 0088 */ 0089 EXPAND(res) = 0; 0090 *doc = strdup(T(res)); 0091 } 0092 DELETE(res); 0093 return size; 0094 } 0095 0096 0097 /* write an header index 0098 */ 0099 int 0100 mkd_generatetoc(Document *p, FILE *out) 0101 { 0102 char *buf = 0; 0103 int sz = mkd_toc(p, &buf); 0104 int ret = EOF; 0105 0106 if ( sz > 0 ) 0107 ret = fwrite(buf, 1, sz, out); 0108 0109 if ( buf ) free(buf); 0110 0111 return (ret == sz) ? ret : EOF; 0112 }