static void definitionlist(Paragraph *p, MMIOT *f) { Line *tag; if ( p ) { Qstring("<dl>\n", f); for ( ; p ; p = p->next) { for ( tag = p->text; tag; tag = tag->next ) { Qstring("<dt>", f); ___mkd_reparse(T(tag->text), S(tag->text), 0, f); Qstring("</dt>\n", f); } // MK HACK if (p->down) { p->down->easyNewline = p->easyNewline; } htmlify(p->down, "dd", p->ident, f); Qchar('\n', f); } Qstring("</dl>", f); } }
static int splat(Line *p, char *block, Istring align, int force, MMIOT *f) { int first, idx = 0, colno = 0; Qstring("<tr>\n", f); while ( idx < S(p->text) ) { first = idx; if ( force && (colno >= S(align)-1) ) idx = S(p->text); else while ( (idx < S(p->text)) && (T(p->text)[idx] != '|') ) ++idx; Qprintf(f, "<%s%s>", block, alignments[ (colno < S(align)) ? T(align)[colno]:0 ]); ___mkd_reparse(T(p->text)+first, idx-first, 0, f); Qprintf(f, "</%s>\n", block); idx++; colno++; } if ( force ) while (colno < S(align) ) { Qprintf(f, "<%s></%s>\n", block, block); ++colno; } Qstring("</tr>\n", f); return colno; }
/* print out the start of an `img' or `a' tag, applying callbacks as needed. */ static void printlinkyref(MMIOT *f, linkytype *tag, char *link, int size) { char *edit; if ( f->flags & IS_LABEL ) return; Qstring(tag->link_pfx, f); if ( tag->kind & IS_URL ) { if ( f->cb && f->cb->e_url && (edit = (*f->cb->e_url)(link, size, f->cb->e_data)) ) { puturl(edit, strlen(edit), f, 0); if ( f->cb->e_free ) (*f->cb->e_free)(edit, f->cb->e_data); } else puturl(link + tag->szpat, size - tag->szpat, f, 0); } else ___mkd_reparse(link + tag->szpat, size - tag->szpat, MKD_TAGTEXT, f, 0); Qstring(tag->link_sfx, f); if ( f->cb && f->cb->e_flags && (edit = (*f->cb->e_flags)(link, size, f->cb->e_data)) ) { Qchar(' ', f); Qstring(edit, f); if ( f->cb->e_free ) (*f->cb->e_free)(edit, f->cb->e_data); } } /* printlinkyref */
/* delspan() -- write out a chunk of text, blocking with <del>...</del> */ static void delspan(MMIOT *f, int size) { Qstring("<del>", f); ___mkd_reparse(cursor(f)-1, size, 0, f); Qstring("</del>", f); }
static int printblock(Paragraph *pp, MMIOT *f) { Line *t = pp->text; static char *Begin[] = { "", "<p>", "<center>" }; static char *End[] = { "", "</p>","</center>" }; while (t) { if ( S(t->text) ) { if ( S(t->text) > 2 && T(t->text)[S(t->text)-2] == ' ' && T(t->text)[S(t->text)-1] == ' ') { push(T(t->text), S(t->text)-2, f); push("\003\n", 2, f); } else { ___mkd_tidy(&t->text); push(T(t->text), S(t->text), f); if ( t->next ) push("\n", 1, f); } } t = t->next; } Qstring(Begin[pp->align], f); text(f); Qstring(End[pp->align], f); return 1; }
/* * write out a url, escaping problematic characters */ static void puturl(char *s, int size, MMIOT *f, int display) { unsigned char c; while ( size-- > 0 ) { c = *s++; if ( c == '\\' && size-- > 0 ) { c = *s++; if ( !( ispunct(c) || isspace(c) ) ) Qchar('\\', f); } if ( c == '&' ) Qstring("&", f); else if ( c == '<' ) Qstring("<", f); else if ( c == '"' ) Qstring("%22", f); else if ( isalnum(c) || ispunct(c) || (display && isspace(c)) ) Qchar(c, f); else Qprintf(f, "%%%02X", c); } }
static int printblock(Paragraph *pp, MMIOT *f, int easyNewLine) { Line *t = pp->text; static char *Begin[] = { "", "<p>", "<p style=\"text-align:center;\">" }; static char *End[] = { "", "</p>","</p>" }; while (t) { if ( S(t->text) ) { if ( t->next && S(t->text) > 2 && T(t->text)[S(t->text)-2] == ' ' && T(t->text)[S(t->text)-1] == ' ' ) { push(T(t->text), S(t->text)-2, f); push("\003\n", 2, f); } else { ___mkd_tidy(&t->text); push(T(t->text), S(t->text), f); /* MK NEWLINE HACK */ if ( t->next ) if (easyNewLine) { push("\003\n", 2, f); } else { // Original push("\n", 1, f); } } } t = t->next; } Qstring(Begin[pp->align], f); text(f); Qstring(End[pp->align], f); return 1; }
/* print out a linky (or fail if it's Not Allowed) */ static int linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref) { linkytype *tag; if ( image ) tag = &imaget; else if ( tag = pseudo(ref->link) ) { if ( f->flags & (NO_PSEUDO_PROTO|SAFELINK) ) return 0; } else if ( (f->flags & SAFELINK) && T(ref->link) && (T(ref->link)[0] != '/') && !isautoprefix(T(ref->link)) ) /* if SAFELINK, only accept links that are local or * a well-known protocol */ return 0; else tag = &linkt; if ( f->flags & tag->flags ) return 0; if ( tag->link_pfx ) { Qstring(tag->link_pfx, f); if ( tag->kind & IS_URL ) { if ( f->base && T(ref->link) && (T(ref->link)[tag->szpat] == '/') ) puturl(f->base, strlen(f->base), f, 0); puturl(T(ref->link) + tag->szpat, S(ref->link) - tag->szpat, f, 0); } else ___mkd_reparse(T(ref->link) + tag->szpat, S(ref->link) - tag->szpat, INSIDE_TAG, f); Qstring(tag->link_sfx, f); if ( tag->WxH && ref->height && ref->width ) { Qprintf(f," height=\"%d\"", ref->height); Qprintf(f, " width=\"%d\"", ref->width); } if ( S(ref->title) ) { Qstring(" title=\"", f); ___mkd_reparse(T(ref->title), S(ref->title), INSIDE_TAG, f); Qchar('"', f); } Qstring(tag->text_pfx, f); ___mkd_reparse(T(text), S(text), tag->flags, f); Qstring(tag->text_sfx, f); } else Qwrite(T(ref->link) + tag->szpat, S(ref->link) - tag->szpat, f); return 1; } /* linkyformat */
/* write a character to output, doing text escapes ( & -> &, * > -> > < -> < ) */ static void cputc(int c, MMIOT *f) { switch (c) { case '&': Qstring("&", f); break; case '>': Qstring(">", f); break; case '<': Qstring("<", f); break; default : Qchar(c, f); break; } }
/* codespan() -- write out a chunk of text as code, trimming one * space off the front and/or back as appropriate. */ static void codespan(MMIOT *f, int size) { int i=0, c; if ( size > 1 && peek(f, size-1) == ' ' ) --size; if ( peek(f,i) == ' ' ) ++i, --size; Qstring("<code>", f); code(f, cursor(f)+(i-1), size); Qstring("</code>", f); } /* codespan */
/* print out a linky (or fail if it's Not Allowed) */ static int linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref) { linkytype *tag; if ( image ) tag = &imaget; else if ( tag = pseudo(ref->link) ) { if ( f->flags & (MKD_NO_EXT|MKD_SAFELINK) ) return 0; } else if ( (f->flags & MKD_SAFELINK) && T(ref->link) && (T(ref->link)[0] != '/') && !isautoprefix(T(ref->link), S(ref->link)) ) /* if MKD_SAFELINK, only accept links that are local or * a well-known protocol */ return 0; else tag = &linkt; if ( f->flags & tag->flags ) return 0; if ( f->flags & IS_LABEL ) ___mkd_reparse(T(text), S(text), tag->flags, f); else if ( tag->link_pfx ) { printlinkyref(f, tag, T(ref->link), S(ref->link)); if ( tag->WxH ) { if ( ref->height ) Qprintf(f," height=\"%d\"", ref->height); if ( ref->width ) Qprintf(f, " width=\"%d\"", ref->width); } if ( S(ref->title) ) { Qstring(" title=\"", f); ___mkd_reparse(T(ref->title), S(ref->title), MKD_TAGTEXT, f); Qchar('"', f); } Qstring(tag->text_pfx, f); ___mkd_reparse(T(text), S(text), tag->flags, f); Qstring(tag->text_sfx, f); } else Qwrite(T(ref->link) + tag->szpat, S(ref->link) - tag->szpat, f); return 1; } /* linkyformat */
/* * process embedded links and images */ static int linkylinky(int image, MMIOT *f) { int start = mmiottell(f); Footnote link; linkytype *tag; if ( !linkykey(image, &link, f) ) { mmiotseek(f, start); return 0; } if ( image ) tag = &imaget; else if ( (f->flags & NO_PSEUDO_PROTO) || (tag = extratag(link.link)) == 0 ) tag = &linkt; if ( f->flags & tag-> flags ) { mmiotseek(f, start); return 0; } if ( tag->link_pfx ) { Qstring(tag->link_pfx, f); if ( f->base && (T(link.link)[tag->szpat] == '/') ) puturl(f->base, strlen(f->base), f); puturl(T(link.link) + tag->szpat, S(link.link) - tag->szpat, f); Qstring(tag->link_sfx, f); if ( tag->WxH && link.height && link.width ) { Qprintf(f," height=\"%d\"", link.height); Qprintf(f, " width=\"%d\"", link.width); } if ( S(link.title) ) { Qstring(" title=\"", f); reparse(T(link.title), S(link.title), INSIDE_TAG, f); Qchar('"', f); } Qstring(tag->text_pfx, f); reparse(T(link.tag), S(link.tag), tag->flags, f); Qstring(tag->text_sfx, f); } else Qwrite(T(link.link) + tag->szpat, S(link.link) - tag->szpat, f); return 1; }
/* Smarty-pants-style chrome for quotes, -, ellipses, and (r)(c)(tm) */ static int smartypants(int c, int *flags, MMIOT *f) { int i; if ( f->flags & (DENY_SMARTY|INSIDE_TAG) ) return 0; for ( i=0; i < NRSMART; i++) if ( (c == smarties[i].c0) && islike(f, smarties[i].pat) ) { if ( smarties[i].entity ) Qprintf(f, "&%s;", smarties[i].entity); shift(f, smarties[i].shift); return 1; } switch (c) { case '<' : return 0; case '\'': if ( smartyquote(flags, 's', f) ) return 1; break; case '"': if ( smartyquote(flags, 'd', f) ) return 1; break; case '`': if ( peek(f, 1) == '`' ) { int j = 2; while ( (c=peek(f,j)) != EOF ) { if ( c == '\\' ) j += 2; else if ( c == '`' ) break; else if ( c == '\'' && peek(f, j+1) == '\'' ) { Qstring("“", f); ___mkd_reparse(cursor(f)+1, j-2, 0, f); Qstring("”", f); shift(f,j+1); return 1; } else ++j; } } break; } return 0; } /* smartypants */
/* * convert an email address to a string of nonsense */ static void mangle(char *s, int len, MMIOT *f) { while ( len-- > 0 ) { Qstring("&#", f); Qprintf(f, COINTOSS() ? "x%02x;" : "%02d;", *((unsigned char*)(s++)) ); } }
/* * write out a url, escaping problematic characters */ static void puturl(char *s, int size, MMIOT *f) { unsigned char c; while ( size-- > 0 ) { c = *s++; if ( c == '&' ) Qstring("&", f); else if ( c == '<' ) Qstring("<", f); else if ( isalnum(c) || ispunct(c) ) Qchar(c, f); else Qprintf(f, "%%%02X", c); } }
/* dump out a Paragraph in the desired manner */ static Paragraph* display(Paragraph *p, MMIOT *f) { if ( !p ) return 0; switch ( p->typ ) { case STYLE: case WHITESPACE: break; case HTML: printhtml(p->text, f); break; case CODE: printcode(p->text, f); break; case QUOTE: htmlify(p->down, p->ident ? "div" : "blockquote", p->ident, f); break; case UL: case OL: case AL: listdisplay(p->typ, p->down, f); break; #if DL_TAG_EXTENSION case DL: definitionlist(p->down, f); break; #endif case HR: Qstring("<hr />", f); break; case HDR: printheader(p, f); break; case TABLE: printtable(p, f); break; case SOURCE: htmlify(p->down, 0, 0, f); break; default: printblock(p, f); break; } return p->next; }
static void printcode(Line *t, MMIOT *f) { int blanks; Qstring("<pre><code>", f); for ( blanks = 0; t ; t = t->next ) { if ( S(t->text) > t->dle ) { while ( blanks ) { Qchar('\n', f); --blanks; } code(f, T(t->text), S(t->text)); Qchar('\n', f); } else blanks++; } Qstring("</code></pre>", f); }
/* Qprintf() */ static void Qprintf(MMIOT *f, char *fmt, ...) { char bfr[80]; va_list ptr; va_start(ptr,fmt); vsnprintf(bfr, sizeof bfr, fmt, ptr); va_end(ptr); Qstring(bfr, f); }
static void printcode(Line *t, MMIOT *f) { int blanks; for ( blanks = 0; t ; t = t->next ) if ( S(t->text) > t->dle ) { while ( blanks ) { push("\n", 1, f); --blanks; } push(T(t->text), S(t->text), f); push("\n", 1, f); } else blanks++; Qstring("<pre><code>", f); code(0, f); Qstring("</code></pre>", f); }
/* code() -- write a string out as code. The only characters that have * special meaning in a code block are * `<' and `&' , which * are /always/ expanded to < and & */ static void code(MMIOT *f, char *s, int length) { int i,c; for ( i=0; i < length; i++ ) if ( (c = s[i]) == 003) /* ^C: expand back to 2 spaces */ Qstring(" ", f); else cputc(c, f); } /* code */
static void definitionlist(Paragraph *p, MMIOT *f) { Line *tag; if ( p ) { Qstring("<dl>\n", f); for ( ; p ; p = p->next) { for ( tag = p->text; tag; tag = tag->next ) { Qstring("<dt>", f); reparse(T(tag->text), S(tag->text), 0, f); Qstring("</dt>\n", f); } htmlify(p->down, "dd", f); } Qstring("</dl>", f); } }
/* The size-length token at cursor(f) is either a mailto:, an * implicit mailto:, one of the approved url protocols, or just * plain old text. If it's a mailto: or an approved protocol, * linkify it, otherwise say "no" */ static int process_possible_link(MMIOT *f, int size) { int address= 0; int mailto = 0; char *text = cursor(f); if ( f->flags & DENY_A ) return 0; if ( (size > 7) && strncasecmp(text, "mailto:", 7) == 0 ) { /* if it says it's a mailto, it's a mailto -- who am * I to second-guess the user? */ address = 1; mailto = 7; /* 7 is the length of "mailto:"; we need this */ } else address = maybe_address(text, size); if ( address ) { Qstring("<a href=\"", f); if ( !mailto ) { /* supply a mailto: protocol if one wasn't attached */ mangle("mailto:", 7, f); } mangle(text, size, f); Qstring("\">", f); mangle(text+mailto, size-mailto, f); Qstring("</a>", f); return 1; } else if ( isautoprefix(text, size) ) { printlinkyref(f, &linkt, text, size); Qchar('>', f); puturl(text,size,f, 1); Qstring("</a>", f); return 1; } return 0; } /* process_possible_link */
static int printtable(Paragraph *pp, MMIOT *f) { /* header, dashes, then lines of content */ Line *hdr, *dash, *body; Istring align; int start; int hcols; char *p; if ( !(pp->text && pp->text->next && pp->text->next->next) ) return 0; hdr = pp->text; dash= hdr->next; body= dash->next; /* first figure out cell alignments */ CREATE(align); for (p=T(dash->text), start=0; start < S(dash->text); ) { char first, last; int end; last=first=0; for (end=start ; (end < S(dash->text)) && p[end] != '|'; ++ end ) { if ( !isspace(p[end]) ) { if ( !first) first = p[end]; last = p[end]; } } EXPAND(align) = ( first == ':' ) ? (( last == ':') ? CENTER : LEFT) : (( last == ':') ? RIGHT : 0 ); start = 1+end; } Qstring("<table>\n", f); Qstring("<thead>\n", f); hcols = splat(hdr, "th", align, 0, f); Qstring("</thead>\n", f); if ( hcols > S(align) ) S(align) = hcols; else while ( hcols > S(align) ) EXPAND(align) = 0; Qstring("<tbody>\n", f); for ( ; body; body = body->next) splat(body, "td", align, 1, f); Qstring("</tbody>\n", f); Qstring("</table>\n", f); DELETE(align); return 1; }
static void htmlify(Paragraph *p, char *block, MMIOT *f) { emblock(f); if ( block ) Qprintf(f, "<%s>", block); emblock(f); while (( p = display(p, f) )) { emblock(f); Qstring("\n\n", f); } if ( block ) Qprintf(f, "</%s>", block); emblock(f); }
static void htmlify(Paragraph *p, char *block, char *arguments, MMIOT *f) { ___mkd_emblock(f); if ( block ) Qprintf(f, arguments ? "<%s %s>" : "<%s>", block, arguments); ___mkd_emblock(f); while (( p = display(p, f) )) { ___mkd_emblock(f); Qstring("\n\n", f); } if ( block ) Qprintf(f, "</%s>", block); ___mkd_emblock(f); }
/* a < may be just a regular character, the start of an embedded html * tag, or the start of an <automatic link>. If it's an automatic * link, we also need to know if it's an email address because if it * is we need to mangle it in our futile attempt to cut down on the * spaminess of the rendered page. */ static int maybe_tag_or_link(MMIOT *f) { int c, size; int maybetag = 1; if ( f->flags & INSIDE_TAG ) return 0; for ( size=0; (c = peek(f, size+1)) != '>'; size++) { if ( c == EOF ) return 0; else if ( c == '\\' ) { maybetag=0; if ( peek(f, size+2) != EOF ) size++; } else if ( isspace(c) ) break; else if ( ! (c == '/' || isalnum(c) ) ) maybetag=0; } if ( size ) { if ( maybetag || (size >= 3 && strncmp(cursor(f), "!--", 3) == 0) ) { Qstring(forbidden_tag(f) ? "<" : "<", f); while ( ((c = peek(f, 1)) != EOF) && (c != '>') ) cputc(pull(f), f); return 1; } else if ( !isspace(c) && process_possible_link(f, size) ) { shift(f, size+1); return 1; } } return 0; }
/* dump out a Paragraph in the desired manner */ static Paragraph* display(Paragraph *p, MMIOT *f, int easyNewLine) { if ( !p ) return 0; switch ( p->typ ) { case STYLE: case WHITESPACE: break; case HTML: printhtml(p->text, f); break; case CODE: printcode(p->text, f); break; case QUOTE: if (p->down) { p->down->easyNewline = p->easyNewline; } htmlify(p->down, p->ident ? "div" : "blockquote", p->ident, f); break; case UL: case OL: case AL: listdisplay(p->typ, p->down, f); break; case DL: definitionlist(p->down, f); break; case HR: Qstring("<hr />", f); break; case HDR: printheader(p, f); break; case TABLE: printtable(p, f); break; case SOURCE: if (p->down) { p->down->easyNewline = p->easyNewline; } htmlify(p->down, 0, 0, f); break; default: printblock(p, f, easyNewLine); break; } // MK HACK, copy easyNewLine Paragraph *pNext = p->next; if (pNext) { pNext->easyNewline = p->easyNewline; } return pNext; }
static void text(MMIOT *f) { int c, j; int rep; int smartyflags = 0; while (1) { if ( (f->flags & AUTOLINK) && isalpha(peek(f,1)) ) maybe_autolink(f); c = pull(f); if (c == EOF) break; if ( smartypants(c, &smartyflags, f) ) continue; switch (c) { case 0: break; case 3: Qstring("<br/>", f); break; case '>': if ( tag_text(f) ) Qstring(">", f); else Qchar(c, f); break; case '"': if ( tag_text(f) ) Qstring(""", f); else Qchar(c, f); break; case '!': if ( peek(f,1) == '[' ) { pull(f); if ( tag_text(f) || !linkylinky(1, f) ) Qstring("![", f); } else Qchar(c, f); break; case '[': if ( tag_text(f) || !linkylinky(0, f) ) Qchar(c, f); break; #if SUPERSCRIPT /* A^B -> A<sup>B</sup> */ case '^': if ( (f->flags & (STRICT|INSIDE_TAG)) || isthisspace(f,-1) || isthisspace(f,1) ) Qchar(c,f); else { char *sup = cursor(f); int len = 0; Qstring("<sup>",f); while ( !isthisspace(f,1+len) ) { ++len; } shift(f,len); ___mkd_reparse(sup, len, 0, f); Qstring("</sup>", f); } break; #endif case '_': #if RELAXED_EMPHASIS /* Underscores don't count if they're in the middle of a word */ if ( !(f->flags & STRICT) && isthisalnum(f,-1) && isthisalnum(f,1) ) { Qchar(c, f); break; } #endif case '*': #if RELAXED_EMPHASIS /* Underscores & stars don't count if they're out in the middle * of whitespace */ if ( !(f->flags & STRICT) && isthisspace(f,-1) && isthisspace(f,1) ) { Qchar(c, f); break; } /* else fall into the regular old emphasis case */ #endif if ( tag_text(f) ) Qchar(c, f); else { for (rep = 1; peek(f,1) == c; pull(f) ) ++rep; Qem(f,c,rep); } break; case '`': if ( tag_text(f) || !iscodeblock(f) ) Qchar(c, f); else { Qstring("<code>", f); if ( peek(f, 1) == '`' ) { pull(f); code(2, f); } else code(1, f); Qstring("</code>", f); } break; case '\\': switch ( c = pull(f) ) { case '&': Qstring("&", f); break; case '<': Qstring("<", f); break; case '\\': case '>': case '#': case '.': case '-': case '+': case '{': case '}': case ']': case '(': case ')': case '"': case '\'': case '!': case '[': case '*': case '_': case '`': Qchar(c, f); break; default: Qchar('\\', f); if ( c != EOF ) shift(f,-1); break; } break; case '<': if ( !maybe_tag_or_link(f) ) Qstring("<", f); break; case '&': j = (peek(f,1) == '#' ) ? 2 : 1; while ( isthisalnum(f,j) ) ++j; if ( peek(f,j) != ';' ) Qstring("&", f); else Qchar(c, f); break; default: Qchar(c, f); break; } } /* truncate the input string after we've finished processing it */ S(f->in) = f->isp = 0; } /* text */
/* a < may be just a regular character, the start of an embedded html * tag, or the start of an <automatic link>. If it's an automatic * link, we also need to know if it's an email address because if it * is we need to mangle it in our futile attempt to cut down on the * spaminess of the rendered page. */ static int maybe_tag_or_link(MMIOT *f) { char *text; int c, size, i; int maybetag=1, maybeaddress=0; int mailto; if ( f->flags & INSIDE_TAG ) return 0; for ( size=0; ((c = peek(f,size+1)) != '>') && !isspace(c); size++ ) { if ( ! (c == '/' || isalnum(c) || c == '~') ) maybetag=0; if ( c == '@' ) maybeaddress=1; else if ( c == EOF ) return 0; } if ( size == 0 ) return 0; if ( maybetag || (size >= 3 && strncmp(cursor(f), "!--", 3) == 0) ) { Qstring(forbidden_tag(f) ? "<" : "<", f); while ( ((c = peek(f, 1)) != EOF) && (c != '>') ) cputc(pull(f), f); return 1; } if ( f->flags & DENY_A ) return 0; text = cursor(f); shift(f, size+1); for ( i=0; i < SZAUTOPREFIX; i++ ) if ( strncasecmp(text, autoprefix[i], strlen(autoprefix[i])) == 0 ) { Qstring("<a href=\"", f); puturl(text,size,f); Qstring("\">", f); puturl(text,size,f); Qstring("</a>", f); return 1; } if ( maybeaddress ) { Qstring("<a href=\"", f); if ( (size > 7) && strncasecmp(text, "mailto:", 7) == 0 ) mailto = 7; else { mailto = 0; /* supply a mailto: protocol if one wasn't attached */ mangle("mailto:", 7, f); } mangle(text, size, f); Qstring("\">", f); mangle(text+mailto, size-mailto, f); Qstring("</a>", f); return 1; } shift(f, -(size+1)); return 0; } /* maybe_tag_or_link */
static void text(MMIOT *f) { int c, j; int rep; int smartyflags = 0; while ( (c = pull(f)) != EOF ) { if ( smartypants(c, &smartyflags, f) ) continue; switch (c) { case 0: break; case '>': if ( tag_text(f) ) Qstring(">", f); else Qchar(c, f); break; case '"': if ( tag_text(f) ) Qstring(""", f); else Qchar(c, f); break; case '!': if ( peek(f,1) == '[' ) { pull(f); if ( tag_text(f) || !linkylinky(1, f) ) Qstring("![", f); } else Qchar(c, f); break; case '[': if ( tag_text(f) || !linkylinky(0, f) ) Qchar(c, f); break; #if SUPERSCRIPT case '^': if ( isthisspace(f,-1) || isthisspace(f,1) ) Qchar(c,f); else { char *sup = cursor(f); int len = 0; Qstring("<sup>",f); while ( !isthisspace(f,1+len) ) { ++len; } shift(f,len); reparse(sup, len, 0, f); Qstring("</sup>", f); } break; #endif case '_': #if RELAXED_EMPHASIS /* If RELAXED_EMPHASIS, underscores don't count when * they're in the middle of a word. */ if ( (isthisspace(f,-1) && isthisspace(f,1)) || (isalnum(peek(f,-1)) && isalnum(peek(f,1))) ) { Qchar(c, f); break; } /* else fall into the regular old emphasis case */ #endif case '*': if ( tag_text(f) ) Qchar(c, f); else { for (rep = 1; peek(f,1) == c; pull(f) ) ++rep; Qem(f,c,rep); } break; case '`': if ( tag_text(f) ) Qchar(c, f); else { Qstring("<code>", f); if ( peek(f, 1) == '`' ) { pull(f); code(2, f); } else code(1, f); Qstring("</code>", f); } break; case '\\': switch ( c = pull(f) ) { case '&': Qstring("&", f); break; case '<': Qstring("<", f); break; case '\\': case '>': case '#': case '.': case '-': case '+': case '{': case '}': case ']': case '(': case ')': case '"': case '\'': case '!': case '[': case '*': case '_': case '`': Qchar(c, f); break; default: Qchar('\\', f); if ( c != EOF ) shift(f,-1); break; } break; case '<': if ( !maybe_tag_or_link(f) ) Qstring("<", f); break; case '&': j = (peek(f,1) == '#' ) ? 2 : 1; while ( isalnum(peek(f,j)) ) ++j; if ( peek(f,j) != ';' ) Qstring("&", f); else Qchar(c, f); break; default: Qchar(c, f); break; } } } /* text */