b877d2cfcd 2009-05-08 robert: /* b877d2cfcd 2009-05-08 robert: ** Copyright (c) 2009 Robert Ledger b877d2cfcd 2009-05-08 robert: ** b877d2cfcd 2009-05-08 robert: ** {{{ License b877d2cfcd 2009-05-08 robert: ** b877d2cfcd 2009-05-08 robert: ** This program is free software; you can redistribute it and/or b877d2cfcd 2009-05-08 robert: ** modify it under the terms of the GNU General Public b877d2cfcd 2009-05-08 robert: ** License version 2 as published by the Free Software Foundation. b877d2cfcd 2009-05-08 robert: ** b877d2cfcd 2009-05-08 robert: ** This program is distributed in the hope that it will be useful, b877d2cfcd 2009-05-08 robert: ** but WITHOUT ANY WARRANTY; without even the implied warranty of b877d2cfcd 2009-05-08 robert: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU b877d2cfcd 2009-05-08 robert: ** General Public License for more details. b877d2cfcd 2009-05-08 robert: ** b877d2cfcd 2009-05-08 robert: ** You should have received a copy of the GNU General Public b877d2cfcd 2009-05-08 robert: ** License along with this library; if not, write to the b877d2cfcd 2009-05-08 robert: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, b877d2cfcd 2009-05-08 robert: ** Boston, MA 02111-1307, USA. b877d2cfcd 2009-05-08 robert: ** b877d2cfcd 2009-05-08 robert: ** Author contact information: b877d2cfcd 2009-05-08 robert: ** robert@pytrash.co.uk b877d2cfcd 2009-05-08 robert: ** http://pytrash.co.uk b877d2cfcd 2009-05-08 robert: **}}} b877d2cfcd 2009-05-08 robert: ******************************************************************************* b877d2cfcd 2009-05-08 robert: ** b877d2cfcd 2009-05-08 robert: ** This file contains code to render creole 1.0 formated text as html. b877d2cfcd 2009-05-08 robert: */ b877d2cfcd 2009-05-08 robert: #include <assert.h> b877d2cfcd 2009-05-08 robert: #include "config.h" b877d2cfcd 2009-05-08 robert: #include "creoleparser.h" b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: #if INTERFACE b877d2cfcd 2009-05-08 robert: #define HAVE_MACRO_EXTENSIONS 1 b877d2cfcd 2009-05-08 robert: #endif b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: //{{{ LOCAL INTERFACE b877d2cfcd 2009-05-08 robert: #if LOCAL_INTERFACE b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: #define POOL_CHUNK_SIZE 100 b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: #define KIND_ROOT 0x0000001 b877d2cfcd 2009-05-08 robert: #define KIND_HORIZONTAL_RULE 0x0000002 b877d2cfcd 2009-05-08 robert: #define KIND_HEADING 0x0000004 b877d2cfcd 2009-05-08 robert: #define KIND_ORDERED_LIST 0x0000008 b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: #define KIND_UNORDERED_LIST 0x0000010 b877d2cfcd 2009-05-08 robert: #define KIND_PARAGRAPH 0x0000020 b877d2cfcd 2009-05-08 robert: #define KIND_TABLE 0x0000040 b877d2cfcd 2009-05-08 robert: #define KIND_NO_WIKI_BLOCK 0x0000080 b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: #define KIND_PARA_BREAK 0x0000100 b877d2cfcd 2009-05-08 robert: #define KIND_END_WIKI_MARKER 0x0000200 b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: #define KIND_BOLD 0x0000400 b877d2cfcd 2009-05-08 robert: #define KIND_ITALIC 0x0000800 b877d2cfcd 2009-05-08 robert: #define KIND_SUPERSCRIPT 0x0001000 b877d2cfcd 2009-05-08 robert: #define KIND_SUBSCRIPT 0x0002000 b877d2cfcd 2009-05-08 robert: #define KIND_MONOSPACED 0x0004000 b877d2cfcd 2009-05-08 robert: #define KIND_BREAK 0x0008000 b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: #define KIND_TABLE_ROW 0x0010000 b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: #define KIND_MARKER b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: struct Node {//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char *start; b877d2cfcd 2009-05-08 robert: char *end; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: int kind; b877d2cfcd 2009-05-08 robert: int level; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: Node *parent; b877d2cfcd 2009-05-08 robert: Node *next; b877d2cfcd 2009-05-08 robert: Node *children; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: }; b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: struct NodePool {//{{{ b877d2cfcd 2009-05-08 robert: NodePool *next; b877d2cfcd 2009-05-08 robert: Node a[POOL_CHUNK_SIZE]; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: struct Parser {//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: Blob *pOut; /* Output appended to this blob */ b877d2cfcd 2009-05-08 robert: Renderer *r; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: NodePool *pool; b877d2cfcd 2009-05-08 robert: int nFree; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: Node *this; b877d2cfcd 2009-05-08 robert: Node *previous; b877d2cfcd 2009-05-08 robert: Node *list; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char *cursor; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: int lineWasBlank; b877d2cfcd 2009-05-08 robert: int charCount; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: Node *item; b877d2cfcd 2009-05-08 robert: Node *istack; b877d2cfcd 2009-05-08 robert: char *icursor; b877d2cfcd 2009-05-08 robert: char *iend; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: int inLink; b877d2cfcd 2009-05-08 robert: int inTable; b877d2cfcd 2009-05-08 robert: int iesc; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: Blob *iblob; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: }; b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: #endif b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: const int KIND_LIST = (KIND_UNORDERED_LIST | KIND_ORDERED_LIST); b877d2cfcd 2009-05-08 robert: const int KIND_LIST_OR_PARAGRAPH = (KIND_PARAGRAPH | KIND_UNORDERED_LIST | KIND_ORDERED_LIST); b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: //{{{ POOL MANAGEMENT b877d2cfcd 2009-05-08 robert: static Node *pool_new(Parser *p){ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if ( p->pool == NULL || p->nFree == 0){ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: NodePool *temp = p->pool; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->pool = malloc(sizeof(NodePool)); b877d2cfcd 2009-05-08 robert: if( p->pool == NULL ) fossil_panic("out of memory"); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->pool->next = temp; b877d2cfcd 2009-05-08 robert: p->nFree = POOL_CHUNK_SIZE; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: p->nFree -= 1; b877d2cfcd 2009-05-08 robert: Node *node = &(p->pool->a[p->nFree]); b877d2cfcd 2009-05-08 robert: memset(node, 0, sizeof(*node)); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: return node; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: static void pool_free(Parser *p){ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: NodePool *temp; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: while (p->pool != NULL){ b877d2cfcd 2009-05-08 robert: temp = p->pool; b877d2cfcd 2009-05-08 robert: p->pool = temp->next; b877d2cfcd 2009-05-08 robert: free(temp); b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: //{{{ Utility Methods b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: static char *cr_skipBlanks(Parser *p, char* z){//{{{ b877d2cfcd 2009-05-08 robert: char *s = z; b877d2cfcd 2009-05-08 robert: while (z[0] == ' ' || z[0] == '\t') z++; b877d2cfcd 2009-05-08 robert: p->charCount = z - s; b877d2cfcd 2009-05-08 robert: return z; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: static int cr_countBlanks(Parser *p, char* z){//{{{ b877d2cfcd 2009-05-08 robert: cr_skipBlanks(p, z); b877d2cfcd 2009-05-08 robert: return p->charCount; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: static char *cr_skipChars(Parser *p, char *z, char c){//{{{ b877d2cfcd 2009-05-08 robert: char *s = z; b877d2cfcd 2009-05-08 robert: while (z[0] == c) z++; b877d2cfcd 2009-05-08 robert: p->charCount = z - s; b877d2cfcd 2009-05-08 robert: return z; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: static int cr_countChars(Parser *p, char *z, char c){//{{{ b877d2cfcd 2009-05-08 robert: cr_skipChars(p, z, c); b877d2cfcd 2009-05-08 robert: return p->charCount; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: static char *cr_nextLine(Parser *p, char *z){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->lineWasBlank = 1; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: while (1){ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: switch (z[0]){ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case '\r': b877d2cfcd 2009-05-08 robert: if (z[1] == '\n') { b877d2cfcd 2009-05-08 robert: z[0] = ' '; b877d2cfcd 2009-05-08 robert: return z + 2; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: z[0] = '\n'; b877d2cfcd 2009-05-08 robert: return z + 1; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case'\n': b877d2cfcd 2009-05-08 robert: return z + 1; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case '\t': b877d2cfcd 2009-05-08 robert: z[0] = ' '; b877d2cfcd 2009-05-08 robert: z++; b877d2cfcd 2009-05-08 robert: break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case ' ': b877d2cfcd 2009-05-08 robert: z++; b877d2cfcd 2009-05-08 robert: break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case '\0': b877d2cfcd 2009-05-08 robert: return z; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: default: b877d2cfcd 2009-05-08 robert: p->lineWasBlank = 0; b877d2cfcd 2009-05-08 robert: z++; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: //{{{ INLINE PARSER b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: static int cr_isEsc(Parser *p){//{{{ b877d2cfcd 2009-05-08 robert: if (p->iesc){ b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, p->icursor, 1); b877d2cfcd 2009-05-08 robert: p->iesc = 0; b877d2cfcd 2009-05-08 robert: p->icursor += 1; b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: return 0; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: static int cr_iOpen(Parser *p, int kind){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: switch (kind){ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case KIND_BOLD: b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "<strong>", 8); b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case KIND_ITALIC: b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "<em>", 4); b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case KIND_SUPERSCRIPT: b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "<sup>", 5); b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case KIND_SUBSCRIPT: b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "<sub>", 5); b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case KIND_MONOSPACED: b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "<tt>", 4); b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: return 0; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: static int cr_iClose(Parser *p, int kind){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: switch (kind){ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case KIND_BOLD: b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "</strong>", 9); b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case KIND_ITALIC: b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "</em>", 5); b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case KIND_SUPERSCRIPT: b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "</sup>", 6); b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case KIND_SUBSCRIPT: b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "</sub>", 6); b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case KIND_MONOSPACED: b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "</tt>", 5); b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: return 0; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: static void cr_iMarkup(Parser *p, int kind){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (p->iesc) { b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, p->icursor, 1); b877d2cfcd 2009-05-08 robert: p->icursor +=1; b877d2cfcd 2009-05-08 robert: p->iesc =0; b877d2cfcd 2009-05-08 robert: return; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (p->icursor[1] != p->icursor[0]) { b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, p->icursor, 1); b877d2cfcd 2009-05-08 robert: p->icursor +=1; b877d2cfcd 2009-05-08 robert: return; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->icursor += 2; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (kind & KIND_BREAK) { b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "<br />", 6); b877d2cfcd 2009-05-08 robert: return; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (kind & KIND_ITALIC && p->icursor[-3] == ':'){ b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "//", 2); b877d2cfcd 2009-05-08 robert: return; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: Node *n = p->istack; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: int found = 0; b877d2cfcd 2009-05-08 robert: while (n) { b877d2cfcd 2009-05-08 robert: if (n->kind & kind) { b877d2cfcd 2009-05-08 robert: found = 1; b877d2cfcd 2009-05-08 robert: break; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: n = n->next; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (!found) { b877d2cfcd 2009-05-08 robert: n = pool_new(p); b877d2cfcd 2009-05-08 robert: n->kind = kind; b877d2cfcd 2009-05-08 robert: n->next = p->istack; b877d2cfcd 2009-05-08 robert: p->istack = n; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: assert(cr_iOpen(p, kind)); b877d2cfcd 2009-05-08 robert: return; b877d2cfcd 2009-05-08 robert: }; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: n= p->istack; b877d2cfcd 2009-05-08 robert: while (n){ b877d2cfcd 2009-05-08 robert: p->istack = n->next; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: assert(cr_iClose(p, n->kind)); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (kind == n->kind) return; b877d2cfcd 2009-05-08 robert: n = p->istack; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: static int cr_iNoWiki(Parser *p){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if ((p->iend - p->icursor)<6) return 0; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (p->icursor[1]!='{' || p->icursor[2]!='{') b877d2cfcd 2009-05-08 robert: return 0; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char *s = p->icursor + 3; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: int count = p->iend - p->icursor - 6; b877d2cfcd 2009-05-08 robert: while (count--){ b877d2cfcd 2009-05-08 robert: if (s[0]=='}' && s[1]=='}' && s[2]=='}' && s[3]!='}'){ b877d2cfcd 2009-05-08 robert: blob_appendf(p->iblob, "<tt style='background:yellow'>%s</tt>", htmlize(p->icursor + 3, s - p->icursor-3)); b877d2cfcd 2009-05-08 robert: p->icursor = s + 3; b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: s++; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: return 0; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: static int cr_iImage(Parser *p){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if ((p->iend - p->icursor)<4) return 0; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (p->icursor[1]!='{') b877d2cfcd 2009-05-08 robert: return 0; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char *s = p->icursor + 2; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: int count = p->iend - p->icursor - 4; b877d2cfcd 2009-05-08 robert: while (count--){ b877d2cfcd 2009-05-08 robert: if (s[0]=='}' && s[1]=='}'){ b877d2cfcd 2009-05-08 robert: blob_appendf(p->iblob, "<span style='color:blue;'>%s</span>", htmlize(p->icursor+2, s - p->icursor-2)); b877d2cfcd 2009-05-08 robert: p->icursor = s + 2; b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: s++; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: return 0; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: static int cr_iMacro(Parser *p){//{{{ b877d2cfcd 2009-05-08 robert: return 0; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: static void cr_renderLink(Parser *p, char *s, char *bar, char *e){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: int tsize = bar-s; b877d2cfcd 2009-05-08 robert: int dsize = e - bar-1; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (tsize < 1) return; b877d2cfcd 2009-05-08 robert: if (dsize < 1) dsize = 0; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char zTarget[tsize + 1]; b877d2cfcd 2009-05-08 robert: memcpy(zTarget, s, tsize); b877d2cfcd 2009-05-08 robert: zTarget[tsize] = '\0'; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char zClose[20]; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: Blob *pOut = p->r->pOut; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->r->pOut = p->iblob; b877d2cfcd 2009-05-08 robert: wf_openHyperlink(p->r, zTarget, zClose, sizeof(zClose)); b877d2cfcd 2009-05-08 robert: p->r->pOut = pOut; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (dsize) b877d2cfcd 2009-05-08 robert: cr_parseInline(p, bar+1, e) ; b877d2cfcd 2009-05-08 robert: else b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, htmlize(s, tsize), -1); b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, zClose, -1); b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: static int cr_iLink(Parser *p){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (p->inLink) return 0; b877d2cfcd 2009-05-08 robert: if ((p->iend - p->icursor)<3) return 0; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (p->icursor[1]!='[') return 0; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char *s = p->icursor + 2; b877d2cfcd 2009-05-08 robert: char *bar = NULL; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: int count = p->iend - p->icursor -3; b877d2cfcd 2009-05-08 robert: while (count--){ b877d2cfcd 2009-05-08 robert: if (s[0]==']' && s[1]==']'){ b877d2cfcd 2009-05-08 robert: if (!bar) bar = s; b877d2cfcd 2009-05-08 robert: p->inLink = 1; b877d2cfcd 2009-05-08 robert: cr_renderLink(p, p->icursor+2, bar, s); b877d2cfcd 2009-05-08 robert: p->inLink = 0; b877d2cfcd 2009-05-08 robert: p->icursor = s + 2; b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: if (!bar && s[0]=='|') bar=s; b877d2cfcd 2009-05-08 robert: s++; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: return 0; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: LOCAL char *cr_parseInline(Parser *p, char *s, char *e){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: int save_iesc = p->iesc; b877d2cfcd 2009-05-08 robert: char *save_iend = p->iend; b877d2cfcd 2009-05-08 robert: Node *save_istack = p->istack; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->iesc = 0; b877d2cfcd 2009-05-08 robert: p->iend = e; b877d2cfcd 2009-05-08 robert: p->istack = NULL; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->icursor = s; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char *eof = NULL; b877d2cfcd 2009-05-08 robert: while (!eof && p->icursor < p->iend ){ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: switch (*p->icursor) {//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case '~': b877d2cfcd 2009-05-08 robert: if (p->iesc) { b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "~", 1); b877d2cfcd 2009-05-08 robert: p->iesc = 0; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: p->iesc = !p->iesc; b877d2cfcd 2009-05-08 robert: p->icursor+=1; b877d2cfcd 2009-05-08 robert: break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case '*': b877d2cfcd 2009-05-08 robert: cr_iMarkup(p, KIND_BOLD); b877d2cfcd 2009-05-08 robert: break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case '/': b877d2cfcd 2009-05-08 robert: cr_iMarkup(p, KIND_ITALIC); b877d2cfcd 2009-05-08 robert: break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case '^': b877d2cfcd 2009-05-08 robert: cr_iMarkup(p, KIND_SUPERSCRIPT); b877d2cfcd 2009-05-08 robert: break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case ',': b877d2cfcd 2009-05-08 robert: cr_iMarkup(p, KIND_SUBSCRIPT); b877d2cfcd 2009-05-08 robert: break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case '#': b877d2cfcd 2009-05-08 robert: cr_iMarkup(p, KIND_MONOSPACED); b877d2cfcd 2009-05-08 robert: break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case '\\': b877d2cfcd 2009-05-08 robert: cr_iMarkup(p, KIND_BREAK); b877d2cfcd 2009-05-08 robert: break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case '{': b877d2cfcd 2009-05-08 robert: if (cr_isEsc(p)) break; b877d2cfcd 2009-05-08 robert: if (cr_iNoWiki(p)) break; b877d2cfcd 2009-05-08 robert: if (cr_iImage(p)) break; b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, p->icursor, 1); b877d2cfcd 2009-05-08 robert: p->icursor += 1; b877d2cfcd 2009-05-08 robert: break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case '[': b877d2cfcd 2009-05-08 robert: if (cr_isEsc(p)) break; b877d2cfcd 2009-05-08 robert: if (cr_iLink(p)) break; b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, p->icursor, 1); b877d2cfcd 2009-05-08 robert: p->icursor += 1; b877d2cfcd 2009-05-08 robert: break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case '<': b877d2cfcd 2009-05-08 robert: if (cr_isEsc(p)) break; b877d2cfcd 2009-05-08 robert: if (cr_iMacro(p)) break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "<", 4); b877d2cfcd 2009-05-08 robert: p->icursor += 1; b877d2cfcd 2009-05-08 robert: break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case '>': b877d2cfcd 2009-05-08 robert: if (p->iesc) { b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "~", 1); b877d2cfcd 2009-05-08 robert: p->iesc = 0; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, ">", 4); b877d2cfcd 2009-05-08 robert: p->icursor += 1; b877d2cfcd 2009-05-08 robert: break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case '&': b877d2cfcd 2009-05-08 robert: if (p->iesc) { b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "~", 1); b877d2cfcd 2009-05-08 robert: p->iesc = 0; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "&", 5); b877d2cfcd 2009-05-08 robert: p->icursor += 1; b877d2cfcd 2009-05-08 robert: break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: case '|': b877d2cfcd 2009-05-08 robert: if (p->inTable){ b877d2cfcd 2009-05-08 robert: if (p->iesc) { b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, p->icursor, 1); b877d2cfcd 2009-05-08 robert: p->iesc = 0; b877d2cfcd 2009-05-08 robert: p->icursor += 1; b877d2cfcd 2009-05-08 robert: break; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: eof = p->icursor + 1; b877d2cfcd 2009-05-08 robert: break; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: // fall through to default b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: default: b877d2cfcd 2009-05-08 robert: if (p->iesc) { b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "~", 1); b877d2cfcd 2009-05-08 robert: p->iesc = 0; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, p->icursor, 1); b877d2cfcd 2009-05-08 robert: p->icursor +=1; b877d2cfcd 2009-05-08 robert: }//}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: while (p->istack){ b877d2cfcd 2009-05-08 robert: cr_iClose(p, p->istack->kind); b877d2cfcd 2009-05-08 robert: p->istack = p->istack->next; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->iesc = save_iesc; b877d2cfcd 2009-05-08 robert: p->iend = save_iend; b877d2cfcd 2009-05-08 robert: p->istack = save_istack; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: return eof; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: static void cr_renderListItem(Parser *p, Node *n){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "<li>", 4); b877d2cfcd 2009-05-08 robert: cr_parseInline(p, n->start, n->end); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (n->children){ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: int ord = (n->children->kind & KIND_ORDERED_LIST); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (ord) blob_append(p->iblob, "<ol>", 4); b877d2cfcd 2009-05-08 robert: else blob_append(p->iblob, "<ul>", 4); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: n = n->children; b877d2cfcd 2009-05-08 robert: while (n){ b877d2cfcd 2009-05-08 robert: cr_renderListItem(p, n); b877d2cfcd 2009-05-08 robert: n = n->next; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (ord) blob_append(p->iblob, "</ol>", 5); b877d2cfcd 2009-05-08 robert: else blob_append(p->iblob, "</ul>", 5); b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "</li>", 5); b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: static void cr_renderList(Parser *p){ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: Node *n = p->list; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: while (n->parent !=n) n = n->parent; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: int ord = (n->kind & KIND_ORDERED_LIST); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (ord) blob_append(p->iblob, "\n\n<ol>", -1); b877d2cfcd 2009-05-08 robert: else blob_append(p->iblob, "\n\n<ul>", -1); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: while (n) { b877d2cfcd 2009-05-08 robert: cr_renderListItem(p, n); b877d2cfcd 2009-05-08 robert: n = n->next; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (ord) blob_append(p->iblob, "</ol>", 5); b877d2cfcd 2009-05-08 robert: else blob_append(p->iblob, "</ul>", 5); b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: static void cr_renderTableRow(Parser *p, Node *row){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char *s = row->start; b877d2cfcd 2009-05-08 robert: int th; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "\n<tr>", -1); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: while (s && s < row->end){ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if ((th = *s == '=')) { b877d2cfcd 2009-05-08 robert: s++; b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "<th>", -1); b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: else { b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "<td>", -1); b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: s = cr_parseInline(p, s, row->end); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (th) b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "</th>\n", -1); b877d2cfcd 2009-05-08 robert: else b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "</td>\n", -1); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (!s) break; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "</tr>", 5); b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: static void cr_renderTable(Parser *p, Node *n){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: Node *row = n->children; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "<table class='creoletable'>", -1); b877d2cfcd 2009-05-08 robert: p->inTable = 1; b877d2cfcd 2009-05-08 robert: while (row){ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: cr_renderTableRow(p, row); b877d2cfcd 2009-05-08 robert: row = row->next; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "</table>", -1); b877d2cfcd 2009-05-08 robert: p->inTable = 0; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: static void cr_render(Parser *p, Node *node){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (node->kind & KIND_PARAGRAPH){ b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "\n<p>", -1); b877d2cfcd 2009-05-08 robert: cr_parseInline(p, node->start, node->end ); b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "</p>\n", -1 ); b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (node->kind & KIND_HEADING){ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: blob_appendf(p->iblob, b877d2cfcd 2009-05-08 robert: "\n<h%d>%s</h%d>\n", b877d2cfcd 2009-05-08 robert: node->level, b877d2cfcd 2009-05-08 robert: htmlize(node->start, node->end - node->start), b877d2cfcd 2009-05-08 robert: node->level b877d2cfcd 2009-05-08 robert: ); b877d2cfcd 2009-05-08 robert: return; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (node->kind & KIND_HORIZONTAL_RULE){ b877d2cfcd 2009-05-08 robert: blob_append(p->iblob, "<hr />", -1); b877d2cfcd 2009-05-08 robert: return; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (node->kind & KIND_LIST){ b877d2cfcd 2009-05-08 robert: cr_renderList(p); b877d2cfcd 2009-05-08 robert: p->list = NULL; b877d2cfcd 2009-05-08 robert: return; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (node->kind & KIND_TABLE){ b877d2cfcd 2009-05-08 robert: cr_renderTable(p, node); b877d2cfcd 2009-05-08 robert: return; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (node->kind & KIND_NO_WIKI_BLOCK){ b877d2cfcd 2009-05-08 robert: blob_appendf(p->iblob, b877d2cfcd 2009-05-08 robert: "\n<blockquote style='background:oldlace'><pre>%s</pre></blockquote>\n", b877d2cfcd 2009-05-08 robert: htmlize( node->start, node->end - node->start) b877d2cfcd 2009-05-08 robert: ); b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: static char *cr_findEndOfBlock(Parser *p, char *s, char c){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char *end; b877d2cfcd 2009-05-08 robert: while (s[0]){ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: end = s; b877d2cfcd 2009-05-08 robert: if (s[0] == c && s[0] == c && s[0] == c) { b877d2cfcd 2009-05-08 robert: s = cr_nextLine(p, s + 3); b877d2cfcd 2009-05-08 robert: if (p->lineWasBlank) { b877d2cfcd 2009-05-08 robert: p->cursor = s; b877d2cfcd 2009-05-08 robert: return end; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: else { b877d2cfcd 2009-05-08 robert: s = cr_nextLine(p, s); b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: return 0; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: static int cr_addListItem(Parser *p, Node *n){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: n->parent = n; b877d2cfcd 2009-05-08 robert: n->next = n->children = NULL; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (!p->list) { b877d2cfcd 2009-05-08 robert: if (n->level != 1) return 0; b877d2cfcd 2009-05-08 robert: p->list = n; b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: Node *list = p->list; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: while (n->level < list->level){ b877d2cfcd 2009-05-08 robert: list = list->parent; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (n->level == list->level){ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (n->kind != list->kind){ b877d2cfcd 2009-05-08 robert: if (n->level>1) return 0; b877d2cfcd 2009-05-08 robert: cr_renderList(p); b877d2cfcd 2009-05-08 robert: p->list = n; b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: n->parent = list->parent; b877d2cfcd 2009-05-08 robert: p->list = list->next = n; b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if ( (n->level - list->level) > 1 ) return 0; b877d2cfcd 2009-05-08 robert: n->parent = p->list; b877d2cfcd 2009-05-08 robert: p->list->children = n; b877d2cfcd 2009-05-08 robert: p->list = n; b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: static int isEndWikiMarker(Parser *p){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char *s = p->cursor; b877d2cfcd 2009-05-08 robert: if (memcmp(s, "<<fossil>>", 10)) return 0; b877d2cfcd 2009-05-08 robert: p->this->start = s; b877d2cfcd 2009-05-08 robert: p->this->kind = KIND_END_WIKI_MARKER; b877d2cfcd 2009-05-08 robert: p->cursor += 10; b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: ///}}} b877d2cfcd 2009-05-08 robert: static int isNoWikiBlock(Parser *p){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char *s = p->cursor; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (s[0] != '{') return 0; s++; b877d2cfcd 2009-05-08 robert: if (s[0] != '{') return 0; s++; b877d2cfcd 2009-05-08 robert: if (s[0] != '{') return 0; s++; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: s = cr_nextLine(p, s); b877d2cfcd 2009-05-08 robert: if (!p->lineWasBlank) return 0; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->this->start = s; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: s = cr_findEndOfBlock(p, s, '}'); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (!s) return 0; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: // p->cursor was set by findEndOfBlock b877d2cfcd 2009-05-08 robert: p->this->kind = KIND_NO_WIKI_BLOCK; b877d2cfcd 2009-05-08 robert: p->this->end = s; b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: static int isParaBreak(Parser *p){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char *s = cr_nextLine(p, p->cursor); b877d2cfcd 2009-05-08 robert: if (!p->lineWasBlank) return 0; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->cursor = s; b877d2cfcd 2009-05-08 robert: p->this->kind = KIND_PARA_BREAK; b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: static int isHeading(Parser *p){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char *s = cr_skipBlanks(p, p->cursor); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: int level = cr_countChars(p, s, '='); b877d2cfcd 2009-05-08 robert: if (!level) return 0; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: s = cr_skipBlanks(p, s + level); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->this->start = s; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: s = cr_nextLine(p, s); b877d2cfcd 2009-05-08 robert: char *z = s; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (s[-1] == '\n') s--; b877d2cfcd 2009-05-08 robert: while(s[-1] == ' ' || s[-1]=='\t') s--; b877d2cfcd 2009-05-08 robert: while(s[-1] == '=' ) s--; b877d2cfcd 2009-05-08 robert: if (p->this->start < s){ b877d2cfcd 2009-05-08 robert: p->cursor = z; b877d2cfcd 2009-05-08 robert: p->this->kind = KIND_HEADING; b877d2cfcd 2009-05-08 robert: p->this->end = s; b877d2cfcd 2009-05-08 robert: p->this->level = level; b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: return 0; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: static int isHorizontalRule(Parser *p){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char *s = cr_skipBlanks(p, p->cursor); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: int level = cr_countChars(p, s, '-'); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (level < 4) return 0; b877d2cfcd 2009-05-08 robert: s = cr_nextLine(p, s + level); b877d2cfcd 2009-05-08 robert: if (!p->lineWasBlank) return 0; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->cursor = s; b877d2cfcd 2009-05-08 robert: p->this->kind = KIND_HORIZONTAL_RULE; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: static int isListItem(Parser *p){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char *s = cr_skipBlanks(p, p->cursor); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: int level = cr_countChars(p, s, '#'); b877d2cfcd 2009-05-08 robert: if (!level) level = cr_countChars(p, s, '*'); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if ( !level) return 0; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->this->kind = (s[0] == '#') ? KIND_ORDERED_LIST : KIND_UNORDERED_LIST; b877d2cfcd 2009-05-08 robert: p->this->level = level; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: s = cr_skipBlanks(p, s + level); b877d2cfcd 2009-05-08 robert: p->this->start = s; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: s = cr_nextLine(p, s); b877d2cfcd 2009-05-08 robert: if (p->lineWasBlank) return 0; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (cr_addListItem(p, p->this)){ b877d2cfcd 2009-05-08 robert: p->cursor = p->this->end = s; b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: p->this->kind = 0; b877d2cfcd 2009-05-08 robert: return 0; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: static int isTable(Parser *p){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->this->start = p->cursor; b877d2cfcd 2009-05-08 robert: char *s = cr_skipBlanks(p, p->cursor); b877d2cfcd 2009-05-08 robert: if (s[0] != '|') return 0; b877d2cfcd 2009-05-08 robert: s +=1; b877d2cfcd 2009-05-08 robert: p->this->kind = KIND_TABLE; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: //p->cursor = p->this->end = cr_nextLine(p, s); b877d2cfcd 2009-05-08 robert: Node *row; b877d2cfcd 2009-05-08 robert: Node *tail = NULL; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: while (1) { b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: row = pool_new(p); b877d2cfcd 2009-05-08 robert: row->kind = KIND_TABLE_ROW; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (tail) tail = tail->next = row; b877d2cfcd 2009-05-08 robert: else p->this->children = tail = row; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: row->start = s; b877d2cfcd 2009-05-08 robert: p->cursor = s = row->end = p->this->end = cr_nextLine(p, s); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (row->end[-1] == '\n') row->end -= 1; b877d2cfcd 2009-05-08 robert: while(row->end[-1] == ' ' ) row->end -= 1; b877d2cfcd 2009-05-08 robert: if (row->end[-1] == '|') row->end -= 1; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (!*s) break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: // blanks *not* normalized b877d2cfcd 2009-05-08 robert: s = cr_skipBlanks(p, p->cursor); b877d2cfcd 2009-05-08 robert: if (s[0] != '|') break; b877d2cfcd 2009-05-08 robert: s++; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: }; b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: static int isParagraph(Parser *p){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char *s = p->cursor; b877d2cfcd 2009-05-08 robert: p->this->start = s; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: s = cr_nextLine(p, s); b877d2cfcd 2009-05-08 robert: p->cursor = p->this->end = s; b877d2cfcd 2009-05-08 robert: p->this->kind = KIND_PARAGRAPH; b877d2cfcd 2009-05-08 robert: return 1; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: static void cr_parse(Parser *p, char* z){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->previous = pool_new(p); b877d2cfcd 2009-05-08 robert: p->previous->kind = KIND_PARA_BREAK; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->this = pool_new(p); b877d2cfcd 2009-05-08 robert: p->this->kind = KIND_PARA_BREAK; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->inLink = 0; b877d2cfcd 2009-05-08 robert: p->inTable = 0; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->cursor = z; b877d2cfcd 2009-05-08 robert: p->list = NULL; b877d2cfcd 2009-05-08 robert: p->istack = NULL; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: while (p->cursor[0]) { b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: while (1){ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: // must be first b877d2cfcd 2009-05-08 robert: if (isNoWikiBlock(p)) break; b877d2cfcd 2009-05-08 robert: if (isParaBreak(p)) break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: // order not important b877d2cfcd 2009-05-08 robert: if (isHeading(p)) break; b877d2cfcd 2009-05-08 robert: if (isHorizontalRule(p)) break; b877d2cfcd 2009-05-08 robert: if (isListItem(p)) break; b877d2cfcd 2009-05-08 robert: if (isTable(p)) break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: // here for efficiency? b877d2cfcd 2009-05-08 robert: if (isEndWikiMarker(p)) break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: // must be last b877d2cfcd 2009-05-08 robert: if (isParagraph(p)); break; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: // doh! b877d2cfcd 2009-05-08 robert: assert(0); b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: int kind = p->this->kind; b877d2cfcd 2009-05-08 robert: int prev = p->previous->kind; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (kind & KIND_END_WIKI_MARKER) return; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if (kind == KIND_PARAGRAPH && prev & KIND_LIST_OR_PARAGRAPH) { b877d2cfcd 2009-05-08 robert: p->previous->end = p->this->end; b877d2cfcd 2009-05-08 robert: p->this = pool_new(p); b877d2cfcd 2009-05-08 robert: continue; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: if ( !(kind & KIND_LIST && prev & KIND_LIST) ) b877d2cfcd 2009-05-08 robert: cr_render(p, p->previous); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->previous = p->this; b877d2cfcd 2009-05-08 robert: p->this = pool_new(p); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char *wiki_render_creole(Renderer *r, char *z){//{{{ b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: Parser parser; b877d2cfcd 2009-05-08 robert: Parser *p = &parser; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->r = r; b877d2cfcd 2009-05-08 robert: p->iblob = r->pOut; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: p->nFree = 0; b877d2cfcd 2009-05-08 robert: p->pool = NULL; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: cr_parse(p, z); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: cr_render(p, p->previous); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: pool_free(p); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: return p->cursor; b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: //}}} b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: char *wiki_render_macro(Renderer *p, char *z, int *tokenType){ b877d2cfcd 2009-05-08 robert: if (!memcmp(z, "<<fossil>>", 9)){ b877d2cfcd 2009-05-08 robert: *tokenType = 1; b877d2cfcd 2009-05-08 robert: return z + 10; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: if (memcmp(z, "<<creole>>", 9)) { b877d2cfcd 2009-05-08 robert: *tokenType = 0; b877d2cfcd 2009-05-08 robert: return z; b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: *tokenType = 1; b877d2cfcd 2009-05-08 robert: return wiki_render_creole(p, z+10); b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: } b877d2cfcd 2009-05-08 robert: b877d2cfcd 2009-05-08 robert: /* :folding=explicit:collapseFolds=1:tabSize=2:indentSize=2:noTabs=false: */