File Annotation
Not logged in
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
7a39dde24b 2009-09-26    robert: #define HAVE_CREOLE_MACRO 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: 
26af399a5c 2009-05-09    robert: //{{{ KIND
26af399a5c 2009-05-09    robert: #define KIND_ROOT            0x0000001
26af399a5c 2009-05-09    robert: #define KIND_HORIZONTAL_RULE 0x0000002
26af399a5c 2009-05-09    robert: #define KIND_HEADING         0x0000004
26af399a5c 2009-05-09    robert: #define KIND_ORDERED_LIST    0x0000008
26af399a5c 2009-05-09    robert: 
26af399a5c 2009-05-09    robert: #define KIND_UNORDERED_LIST  0x0000010
26af399a5c 2009-05-09    robert: #define KIND_PARAGRAPH       0x0000020
26af399a5c 2009-05-09    robert: #define KIND_TABLE           0x0000040
26af399a5c 2009-05-09    robert: #define KIND_NO_WIKI_BLOCK   0x0000080
26af399a5c 2009-05-09    robert: 
26af399a5c 2009-05-09    robert: #define KIND_PARA_BREAK      0x0000100
26af399a5c 2009-05-09    robert: #define KIND_END_WIKI_MARKER 0x0000200
26af399a5c 2009-05-09    robert: 
26af399a5c 2009-05-09    robert: #define KIND_BOLD            0x0000400
26af399a5c 2009-05-09    robert: #define KIND_ITALIC          0x0000800
26af399a5c 2009-05-09    robert: #define KIND_SUPERSCRIPT     0x0001000
26af399a5c 2009-05-09    robert: #define KIND_SUBSCRIPT       0x0002000
26af399a5c 2009-05-09    robert: #define KIND_MONOSPACED      0x0004000
26af399a5c 2009-05-09    robert: #define KIND_BREAK           0x0008000
26af399a5c 2009-05-09    robert: 
26af399a5c 2009-05-09    robert: #define KIND_TABLE_ROW       0x0010000
26af399a5c 2009-05-09    robert: //}}}
26af399a5c 2009-05-09    robert: //{{{ FLAG
26af399a5c 2009-05-09    robert: // keep first four bits free
7a39dde24b 2009-09-26    robert: #define FLAG_CENTER   0x0000100
26af399a5c 2009-05-09    robert: //}}}
b877d2cfcd 2009-05-08    robert: struct Node {//{{{
b877d2cfcd 2009-05-08    robert: 
7a39dde24b 2009-09-26    robert:   char *start;
7a39dde24b 2009-09-26    robert:   char *end;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   int kind;
7a39dde24b 2009-09-26    robert:   int level;
7a39dde24b 2009-09-26    robert:   int flags;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   Node *parent;
7a39dde24b 2009-09-26    robert:   Node *next;
7a39dde24b 2009-09-26    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 {//{{{
7a39dde24b 2009-09-26    robert:   NodePool *next;
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   Blob *pOut;                 /* Output appended to this blob */
7a39dde24b 2009-09-26    robert:   Renderer *r;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   NodePool *pool;
7a39dde24b 2009-09-26    robert:   int nFree;
b877d2cfcd 2009-05-08    robert: 
b877d2cfcd 2009-05-08    robert:   Node *this;
7a39dde24b 2009-09-26    robert:   Node *previous;
7a39dde24b 2009-09-26    robert:   Node *list;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   char *cursor;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   int lineWasBlank;
7a39dde24b 2009-09-26    robert:   int charCount;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   Node *item;
7a39dde24b 2009-09-26    robert:   Node *istack;
7a39dde24b 2009-09-26    robert:   char *icursor;
7a39dde24b 2009-09-26    robert:   char *iend;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   int inLink;
7a39dde24b 2009-09-26    robert:   int inTable;
7a39dde24b 2009-09-26    robert:   int iesc;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   Blob *iblob;
26af399a5c 2009-05-09    robert: 
26af399a5c 2009-05-09    robert: 
26af399a5c 2009-05-09    robert: 
26af399a5c 2009-05-09    robert: 
26af399a5c 2009-05-09    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: 
7a39dde24b 2009-09-26    robert:   if ( p->pool == NULL || p->nFree == 0){
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     NodePool *temp = p->pool;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     p->pool = malloc(sizeof(NodePool));
7a39dde24b 2009-09-26    robert:     if( p->pool == NULL ) fossil_panic("out of memory");
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     p->pool->next = temp;
7a39dde24b 2009-09-26    robert:     p->nFree = POOL_CHUNK_SIZE;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert:   p->nFree -= 1;
7a39dde24b 2009-09-26    robert:   Node *node = &(p->pool->a[p->nFree]);
7a39dde24b 2009-09-26    robert:   memset(node, 0, sizeof(*node));
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   NodePool *temp;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   while (p->pool != NULL){
7a39dde24b 2009-09-26    robert:     temp = p->pool;
7a39dde24b 2009-09-26    robert:     p->pool = temp->next;
7a39dde24b 2009-09-26    robert:     free(temp);
7a39dde24b 2009-09-26    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){//{{{
7a39dde24b 2009-09-26    robert:   char *s = z;
7a39dde24b 2009-09-26    robert:   while (z[0] == ' ' || z[0] == '\t') z++;
7a39dde24b 2009-09-26    robert:   p->charCount = z - s;
7a39dde24b 2009-09-26    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){//{{{
7a39dde24b 2009-09-26    robert:   cr_skipBlanks(p, z);
7a39dde24b 2009-09-26    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){//{{{
7a39dde24b 2009-09-26    robert:   char *s = z;
7a39dde24b 2009-09-26    robert:   while (z[0] == c) z++;
7a39dde24b 2009-09-26    robert:   p->charCount = z - s;
7a39dde24b 2009-09-26    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){//{{{
7a39dde24b 2009-09-26    robert:   cr_skipChars(p, z, c);
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   p->lineWasBlank = 1;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   while (1){
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     switch (z[0]){
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       case '\r':
7a39dde24b 2009-09-26    robert:         if (z[1] == '\n') {
7a39dde24b 2009-09-26    robert:           z[0] = ' ';
7a39dde24b 2009-09-26    robert:           return z + 2;
7a39dde24b 2009-09-26    robert:         }
7a39dde24b 2009-09-26    robert:         z[0] = '\n';
7a39dde24b 2009-09-26    robert:         return z + 1;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       case'\n':
7a39dde24b 2009-09-26    robert:         return z + 1;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       case '\t':
7a39dde24b 2009-09-26    robert:         z[0] = ' ';
7a39dde24b 2009-09-26    robert:         z++;
7a39dde24b 2009-09-26    robert:         break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       case ' ':
7a39dde24b 2009-09-26    robert:         z++;
7a39dde24b 2009-09-26    robert:         break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       case '\0':
7a39dde24b 2009-09-26    robert:         return z;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       default:
7a39dde24b 2009-09-26    robert:         p->lineWasBlank = 0;
7a39dde24b 2009-09-26    robert:         z++;
7a39dde24b 2009-09-26    robert:     }
7a39dde24b 2009-09-26    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){//{{{
7a39dde24b 2009-09-26    robert:   if (p->iesc){
7a39dde24b 2009-09-26    robert:     blob_append(p->iblob, p->icursor, 1);
7a39dde24b 2009-09-26    robert:     p->iesc = 0;
7a39dde24b 2009-09-26    robert:     p->icursor += 1;
7a39dde24b 2009-09-26    robert:     return 1;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   switch (kind){
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     case KIND_BOLD:
7a39dde24b 2009-09-26    robert:       blob_append(p->iblob, "<strong>", 8);
7a39dde24b 2009-09-26    robert:       return 1;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     case KIND_ITALIC:
7a39dde24b 2009-09-26    robert:       blob_append(p->iblob, "<em>", 4);
7a39dde24b 2009-09-26    robert:       return 1;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     case KIND_SUPERSCRIPT:
7a39dde24b 2009-09-26    robert:       blob_append(p->iblob, "<sup>", 5);
7a39dde24b 2009-09-26    robert:       return 1;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     case KIND_SUBSCRIPT:
7a39dde24b 2009-09-26    robert:       blob_append(p->iblob, "<sub>", 5);
7a39dde24b 2009-09-26    robert:       return 1;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     case KIND_MONOSPACED:
7a39dde24b 2009-09-26    robert:       blob_append(p->iblob, "<tt>", 4);
7a39dde24b 2009-09-26    robert:       return 1;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   switch (kind){
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     case KIND_BOLD:
7a39dde24b 2009-09-26    robert:       blob_append(p->iblob, "</strong>", 9);
7a39dde24b 2009-09-26    robert:       return 1;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     case KIND_ITALIC:
7a39dde24b 2009-09-26    robert:       blob_append(p->iblob, "</em>", 5);
7a39dde24b 2009-09-26    robert:       return 1;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     case KIND_SUPERSCRIPT:
7a39dde24b 2009-09-26    robert:       blob_append(p->iblob, "</sup>", 6);
7a39dde24b 2009-09-26    robert:       return 1;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     case KIND_SUBSCRIPT:
7a39dde24b 2009-09-26    robert:       blob_append(p->iblob, "</sub>", 6);
7a39dde24b 2009-09-26    robert:       return 1;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     case KIND_MONOSPACED:
7a39dde24b 2009-09-26    robert:       blob_append(p->iblob, "</tt>", 5);
7a39dde24b 2009-09-26    robert:       return 1;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   if (p->iesc) {
7a39dde24b 2009-09-26    robert:     blob_append(p->iblob, p->icursor, 1);
7a39dde24b 2009-09-26    robert:     p->icursor +=1;
7a39dde24b 2009-09-26    robert:     p->iesc =0;
7a39dde24b 2009-09-26    robert:     return;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (p->icursor[1] != p->icursor[0]) {
7a39dde24b 2009-09-26    robert:     blob_append(p->iblob, p->icursor, 1);
7a39dde24b 2009-09-26    robert:     p->icursor +=1;
7a39dde24b 2009-09-26    robert:     return;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   p->icursor += 2;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (kind & KIND_BREAK) {
7a39dde24b 2009-09-26    robert:       blob_append(p->iblob, "<br />", 6);
7a39dde24b 2009-09-26    robert:       return;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (kind & KIND_ITALIC && p->icursor[-3] == ':'){
7a39dde24b 2009-09-26    robert:         blob_append(p->iblob, "//", 2);
7a39dde24b 2009-09-26    robert:         return;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   Node *n = p->istack;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   int found = 0;
7a39dde24b 2009-09-26    robert:   while (n) {
7a39dde24b 2009-09-26    robert:     if (n->kind & kind) {
7a39dde24b 2009-09-26    robert:       found = 1;
7a39dde24b 2009-09-26    robert:       break;
7a39dde24b 2009-09-26    robert:     }
7a39dde24b 2009-09-26    robert:     n = n->next;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (!found) {
7a39dde24b 2009-09-26    robert:     n = pool_new(p);
7a39dde24b 2009-09-26    robert:     n->kind = kind;
7a39dde24b 2009-09-26    robert:     n->next = p->istack;
7a39dde24b 2009-09-26    robert:     p->istack = n;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     assert(cr_iOpen(p, kind));
7a39dde24b 2009-09-26    robert:     return;
7a39dde24b 2009-09-26    robert:   };
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   n= p->istack;
7a39dde24b 2009-09-26    robert:   while (n){
7a39dde24b 2009-09-26    robert:     p->istack = n->next;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     assert(cr_iClose(p, n->kind));
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     if (kind == n->kind) return;
7a39dde24b 2009-09-26    robert:     n = p->istack;
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   if ((p->iend - p->icursor)<6) return 0;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (p->icursor[1]!='{' || p->icursor[2]!='{')
7a39dde24b 2009-09-26    robert:     return 0;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   char *s = p->icursor + 3;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   int count = p->iend - p->icursor - 6;
7a39dde24b 2009-09-26    robert:   while (count--){
7a39dde24b 2009-09-26    robert:     if (s[0]=='}' && s[1]=='}' && s[2]=='}' && s[3]!='}'){
cacb8db398 2009-09-26    robert:       blob_appendf(p->iblob, "<tt class='creole-inline-nowiki'>%s</tt>", htmlize(p->icursor + 3, s - p->icursor-3));
7a39dde24b 2009-09-26    robert:       p->icursor = s + 3;
7a39dde24b 2009-09-26    robert:       return 1;
7a39dde24b 2009-09-26    robert:     }
7a39dde24b 2009-09-26    robert:     s++;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   if (p->inLink) return 0;
7a39dde24b 2009-09-26    robert:   if ((p->iend - p->icursor)<3) return 0;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (p->icursor[1]!='{') return 0;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   char *s = p->icursor + 2;
7a39dde24b 2009-09-26    robert:   char *bar = NULL;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   int count = p->iend - p->icursor - 4;
7a39dde24b 2009-09-26    robert:   while (count--){
7a39dde24b 2009-09-26    robert:     if (s[0]=='}' && s[1]=='}'){
7a39dde24b 2009-09-26    robert:       if (!bar) bar = p->icursor + 2;
cacb8db398 2009-09-26    robert:       blob_appendf(p->iblob, "<span class='creole-noimage'>%s</span>", htmlize(bar, s - bar ));
7a39dde24b 2009-09-26    robert:       p->icursor = s + 2;
7a39dde24b 2009-09-26    robert:       return 1;
7a39dde24b 2009-09-26    robert:     }
7a39dde24b 2009-09-26    robert:     if (!bar && s[0]=='|') bar=s+1;
7a39dde24b 2009-09-26    robert:     s++;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert:   return 0;
b877d2cfcd 2009-05-08    robert: }
b877d2cfcd 2009-05-08    robert: //}}}
b877d2cfcd 2009-05-08    robert: static int cr_iMacro(Parser *p){//{{{
26af399a5c 2009-05-09    robert: 
7a39dde24b 2009-09-26    robert:   if (p->inLink) return 0;
7a39dde24b 2009-09-26    robert:   if ((p->iend - p->icursor)<3) return 0;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (p->icursor[1]!='<') return 0;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   char *s = p->icursor + 2;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   int count = p->iend - p->icursor - 3;
7a39dde24b 2009-09-26    robert:   while (count--){
cacb8db398 2009-09-26    robert:    if (s[0]=='>' && s[1]=='>'){
cacb8db398 2009-09-26    robert:       blob_appendf(p->iblob, "<span class='creole-nomacro'>%s</span>", htmlize(p->icursor, s - p->icursor + 2));
7a39dde24b 2009-09-26    robert:       p->icursor = s + 2;
7a39dde24b 2009-09-26    robert:       return 1;
7a39dde24b 2009-09-26    robert:     }
7a39dde24b 2009-09-26    robert:     s++;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert:   return 0;
26af399a5c 2009-05-09    robert: 
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: 
7a39dde24b 2009-09-26    robert:   int tsize = bar-s;
7a39dde24b 2009-09-26    robert:   int dsize = e - bar-1;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (tsize < 1) return;
7a39dde24b 2009-09-26    robert:   if (dsize < 1) dsize = 0;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   char zTarget[tsize + 1];
7a39dde24b 2009-09-26    robert:   memcpy(zTarget, s, tsize);
7a39dde24b 2009-09-26    robert:   zTarget[tsize] = '\0';
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   char zClose[20];
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   Blob *pOut = p->r->pOut;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   p->r->pOut = p->iblob;
7a39dde24b 2009-09-26    robert:   wf_openHyperlink(p->r, zTarget, zClose, sizeof(zClose));
7a39dde24b 2009-09-26    robert:   p->r->pOut = pOut;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (dsize)
7a39dde24b 2009-09-26    robert:     cr_parseInline(p, bar+1, e) ;
7a39dde24b 2009-09-26    robert:   else
7a39dde24b 2009-09-26    robert:     blob_append(p->iblob, htmlize(s, tsize), -1);
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   if (p->inLink) return 0;
7a39dde24b 2009-09-26    robert:   if ((p->iend - p->icursor)<3) return 0;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (p->icursor[1]!='[') return 0;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   char *s = p->icursor + 2;
7a39dde24b 2009-09-26    robert:   char *bar = NULL;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   int count = p->iend - p->icursor -3;
7a39dde24b 2009-09-26    robert:   while (count--){
7a39dde24b 2009-09-26    robert:     if (s[0]==']' && s[1]==']'){
7a39dde24b 2009-09-26    robert:       if (!bar) bar = s;
7a39dde24b 2009-09-26    robert:       p->inLink = 1;
7a39dde24b 2009-09-26    robert:       cr_renderLink(p, p->icursor+2, bar, s);
7a39dde24b 2009-09-26    robert:       p->inLink = 0;
7a39dde24b 2009-09-26    robert:       p->icursor = s + 2;
7a39dde24b 2009-09-26    robert:       return 1;
7a39dde24b 2009-09-26    robert:     }
7a39dde24b 2009-09-26    robert:     if (!bar && s[0]=='|') bar=s;
7a39dde24b 2009-09-26    robert:     s++;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   int save_iesc = p->iesc;
7a39dde24b 2009-09-26    robert:   char *save_iend = p->iend;
7a39dde24b 2009-09-26    robert:   Node *save_istack = p->istack;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   p->iesc = 0;
7a39dde24b 2009-09-26    robert:   p->iend = e;
7a39dde24b 2009-09-26    robert:   p->istack = NULL;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   p->icursor = s;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   char *eof = NULL;
7a39dde24b 2009-09-26    robert:   while (!eof &&  p->icursor < p->iend ){
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     switch (*p->icursor) {//{{{
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       case '~':
7a39dde24b 2009-09-26    robert:         if (p->iesc) {
7a39dde24b 2009-09-26    robert:           blob_append(p->iblob, "~", 1);
7a39dde24b 2009-09-26    robert:           p->iesc = 0;
7a39dde24b 2009-09-26    robert:         }
7a39dde24b 2009-09-26    robert:         p->iesc = !p->iesc;
7a39dde24b 2009-09-26    robert:         p->icursor+=1;
7a39dde24b 2009-09-26    robert:         break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       case '*':
7a39dde24b 2009-09-26    robert:         cr_iMarkup(p, KIND_BOLD);
7a39dde24b 2009-09-26    robert:         break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       case '/':
7a39dde24b 2009-09-26    robert:         cr_iMarkup(p, KIND_ITALIC);
7a39dde24b 2009-09-26    robert:         break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       case '^':
7a39dde24b 2009-09-26    robert:         cr_iMarkup(p, KIND_SUPERSCRIPT);
7a39dde24b 2009-09-26    robert:         break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       case ',':
7a39dde24b 2009-09-26    robert:         cr_iMarkup(p, KIND_SUBSCRIPT);
7a39dde24b 2009-09-26    robert:         break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       case '#':
7a39dde24b 2009-09-26    robert:         cr_iMarkup(p, KIND_MONOSPACED);
7a39dde24b 2009-09-26    robert:         break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       case '\\':
7a39dde24b 2009-09-26    robert:         cr_iMarkup(p, KIND_BREAK);
7a39dde24b 2009-09-26    robert:         break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       case '{':
7a39dde24b 2009-09-26    robert:         if (cr_isEsc(p)) break;
7a39dde24b 2009-09-26    robert:         if (cr_iNoWiki(p)) break;
7a39dde24b 2009-09-26    robert:         if (cr_iImage(p)) break;
7a39dde24b 2009-09-26    robert:         blob_append(p->iblob, p->icursor, 1);
7a39dde24b 2009-09-26    robert:         p->icursor += 1;
7a39dde24b 2009-09-26    robert:         break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       case '[':
7a39dde24b 2009-09-26    robert:         if (cr_isEsc(p)) break;
7a39dde24b 2009-09-26    robert:         if (cr_iLink(p)) break;
7a39dde24b 2009-09-26    robert:         blob_append(p->iblob, p->icursor, 1);
7a39dde24b 2009-09-26    robert:         p->icursor += 1;
7a39dde24b 2009-09-26    robert:         break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       case '<':
7a39dde24b 2009-09-26    robert:         if (cr_isEsc(p)) break;
7a39dde24b 2009-09-26    robert:         if (cr_iMacro(p)) break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:         blob_append(p->iblob, "&lt;", 4);
7a39dde24b 2009-09-26    robert:         p->icursor += 1;
7a39dde24b 2009-09-26    robert:         break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       case '>':
7a39dde24b 2009-09-26    robert:         if (p->iesc) {
7a39dde24b 2009-09-26    robert:           blob_append(p->iblob, "~", 1);
7a39dde24b 2009-09-26    robert:           p->iesc = 0;
7a39dde24b 2009-09-26    robert:         }
7a39dde24b 2009-09-26    robert:         blob_append(p->iblob, "&gt;", 4);
7a39dde24b 2009-09-26    robert:         p->icursor += 1;
7a39dde24b 2009-09-26    robert:         break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       case '&':
7a39dde24b 2009-09-26    robert:         if (p->iesc) {
7a39dde24b 2009-09-26    robert:           blob_append(p->iblob, "~", 1);
7a39dde24b 2009-09-26    robert:           p->iesc = 0;
7a39dde24b 2009-09-26    robert:         }
7a39dde24b 2009-09-26    robert:         blob_append(p->iblob, "&amp;", 5);
7a39dde24b 2009-09-26    robert:         p->icursor += 1;
7a39dde24b 2009-09-26    robert:         break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       case '|':
7a39dde24b 2009-09-26    robert:         if (p->inTable){
7a39dde24b 2009-09-26    robert:           if (p->iesc) {
7a39dde24b 2009-09-26    robert:             blob_append(p->iblob, p->icursor, 1);
7a39dde24b 2009-09-26    robert:             p->iesc = 0;
7a39dde24b 2009-09-26    robert:             p->icursor += 1;
7a39dde24b 2009-09-26    robert:             break;
7a39dde24b 2009-09-26    robert:           }
7a39dde24b 2009-09-26    robert:           eof = p->icursor + 1;
7a39dde24b 2009-09-26    robert:           break;
7a39dde24b 2009-09-26    robert:         }
7a39dde24b 2009-09-26    robert:         // fall through to default
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       default:
7a39dde24b 2009-09-26    robert:         if (p->iesc) {
7a39dde24b 2009-09-26    robert:           blob_append(p->iblob, "~", 1);
7a39dde24b 2009-09-26    robert:           p->iesc = 0;
7a39dde24b 2009-09-26    robert:         }
7a39dde24b 2009-09-26    robert:         blob_append(p->iblob, p->icursor, 1);
7a39dde24b 2009-09-26    robert:         p->icursor +=1;
7a39dde24b 2009-09-26    robert:     }//}}}
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   while (p->istack){
7a39dde24b 2009-09-26    robert:     cr_iClose(p, p->istack->kind);
7a39dde24b 2009-09-26    robert:     p->istack = p->istack->next;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   p->iesc = save_iesc;
7a39dde24b 2009-09-26    robert:   p->iend = save_iend;
7a39dde24b 2009-09-26    robert:   p->istack = save_istack;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   return eof;
26af399a5c 2009-05-09    robert: 
26af399a5c 2009-05-09    robert: }
26af399a5c 2009-05-09    robert: //}}}
26af399a5c 2009-05-09    robert: //}}}
26af399a5c 2009-05-09    robert: 
26af399a5c 2009-05-09    robert: //{{{ BLOCK PARSER
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: 
7a39dde24b 2009-09-26    robert:   blob_append(p->iblob, "<li>", 4);
7a39dde24b 2009-09-26    robert:   cr_parseInline(p, n->start, n->end);
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (n->children){
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     int ord = (n->children->kind & KIND_ORDERED_LIST);
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     if (ord)   blob_append(p->iblob, "<ol>", 4);
7a39dde24b 2009-09-26    robert:     else       blob_append(p->iblob, "<ul>", 4);
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     n = n->children;
7a39dde24b 2009-09-26    robert:     while (n){
7a39dde24b 2009-09-26    robert:       cr_renderListItem(p, n);
7a39dde24b 2009-09-26    robert:       n = n->next;
7a39dde24b 2009-09-26    robert:     }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     if (ord)   blob_append(p->iblob, "</ol>", 5);
7a39dde24b 2009-09-26    robert:     else       blob_append(p->iblob, "</ul>", 5);
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert:   blob_append(p->iblob, "</li>", 5);
26af399a5c 2009-05-09    robert: }
26af399a5c 2009-05-09    robert: //}}}
26af399a5c 2009-05-09    robert: static void cr_renderList(Parser *p){//{{{
26af399a5c 2009-05-09    robert: 
7a39dde24b 2009-09-26    robert:   Node *n = p->list;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   while (n->parent !=n)  n = n->parent;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   int ord = (n->kind & KIND_ORDERED_LIST);
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (ord)   blob_append(p->iblob, "\n\n<ol>", -1);
7a39dde24b 2009-09-26    robert:   else       blob_append(p->iblob, "\n\n<ul>", -1);
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   while (n) {
7a39dde24b 2009-09-26    robert:     cr_renderListItem(p, n);
7a39dde24b 2009-09-26    robert:     n = n->next;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (ord)   blob_append(p->iblob, "</ol>", 5);
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   char *s = row->start;
7a39dde24b 2009-09-26    robert:   int th;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   blob_append(p->iblob, "\n<tr>", -1);
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   while (s && s < row->end){
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     if ((th = *s == '=')) {
7a39dde24b 2009-09-26    robert:       s++;
7a39dde24b 2009-09-26    robert:       blob_append(p->iblob, "<th>", -1);
7a39dde24b 2009-09-26    robert:     }
7a39dde24b 2009-09-26    robert:     else {
7a39dde24b 2009-09-26    robert:       blob_append(p->iblob, "<td>", -1);
7a39dde24b 2009-09-26    robert:     }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     s = cr_parseInline(p, s, row->end);
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     if (th)
7a39dde24b 2009-09-26    robert:       blob_append(p->iblob, "</th>\n", -1);
7a39dde24b 2009-09-26    robert:     else
7a39dde24b 2009-09-26    robert:       blob_append(p->iblob, "</td>\n", -1);
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     if (!s) break;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert:   blob_append(p->iblob, "</tr>", 5);
26af399a5c 2009-05-09    robert: }
26af399a5c 2009-05-09    robert: //}}}
b877d2cfcd 2009-05-08    robert: static void cr_renderTable(Parser *p, Node *n){//{{{
b877d2cfcd 2009-05-08    robert: 
7a39dde24b 2009-09-26    robert:   Node *row = n->children;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   blob_append(p->iblob, "<table class='creoletable'>", -1);
7a39dde24b 2009-09-26    robert:   p->inTable = 1;
7a39dde24b 2009-09-26    robert:   while (row){
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     cr_renderTableRow(p, row);
7a39dde24b 2009-09-26    robert:     row = row->next;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert:   blob_append(p->iblob, "</table>", -1);
7a39dde24b 2009-09-26    robert:   p->inTable = 0;
26af399a5c 2009-05-09    robert: 
26af399a5c 2009-05-09    robert: }
26af399a5c 2009-05-09    robert: //}}}
b877d2cfcd 2009-05-08    robert: 
b877d2cfcd 2009-05-08    robert: static void cr_render(Parser *p, Node *node){//{{{
b877d2cfcd 2009-05-08    robert: 
7a39dde24b 2009-09-26    robert:   if (node->kind & KIND_PARAGRAPH){
7a39dde24b 2009-09-26    robert:     blob_append(p->iblob,   "\n<p>", -1);
7a39dde24b 2009-09-26    robert:     cr_parseInline(p, node->start, node->end );
7a39dde24b 2009-09-26    robert:     blob_append(p->iblob, "</p>\n", -1  );
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (node->kind & KIND_HEADING){
7a39dde24b 2009-09-26    robert:     blob_appendf(p->iblob,
7a39dde24b 2009-09-26    robert:         "\n<h%d %s>",
7a39dde24b 2009-09-26    robert:         node->level,
7a39dde24b 2009-09-26    robert:         (node->flags & FLAG_CENTER) ? " style='text-align:center;'" : ""
7a39dde24b 2009-09-26    robert:     );
7a39dde24b 2009-09-26    robert:     cr_parseInline(p, node->start, node->end);
7a39dde24b 2009-09-26    robert:     blob_appendf(p->iblob, "</h%d>\n", node->level  );
7a39dde24b 2009-09-26    robert:     return;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (node->kind & KIND_HORIZONTAL_RULE){
7a39dde24b 2009-09-26    robert:     blob_append(p->iblob, "<hr />", -1);
7a39dde24b 2009-09-26    robert:     return;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (node->kind & KIND_LIST){
7a39dde24b 2009-09-26    robert:     cr_renderList(p);
7a39dde24b 2009-09-26    robert:     p->list = NULL;
7a39dde24b 2009-09-26    robert:     return;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (node->kind & KIND_TABLE){
7a39dde24b 2009-09-26    robert:     cr_renderTable(p, node);
7a39dde24b 2009-09-26    robert:     return;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (node->kind & KIND_NO_WIKI_BLOCK){
7a39dde24b 2009-09-26    robert:     blob_appendf(p->iblob,
cacb8db398 2009-09-26    robert:       "\n<pre class='creole-block-nowiki'>%s</pre>\n",
7a39dde24b 2009-09-26    robert:         htmlize( node->start, node->end - node->start)
7a39dde24b 2009-09-26    robert:     );
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   char *end;
7a39dde24b 2009-09-26    robert:   while (s[0]){
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     end = s;
7a39dde24b 2009-09-26    robert:     if (s[0] == c && s[0] == c && s[0] == c) {
7a39dde24b 2009-09-26    robert:       s = cr_nextLine(p, s + 3);
7a39dde24b 2009-09-26    robert:       if (p->lineWasBlank) {
7a39dde24b 2009-09-26    robert:           p->cursor = s;
7a39dde24b 2009-09-26    robert:           return end;
7a39dde24b 2009-09-26    robert:       }
7a39dde24b 2009-09-26    robert:     }
7a39dde24b 2009-09-26    robert:     else {
7a39dde24b 2009-09-26    robert:       s = cr_nextLine(p, s);
7a39dde24b 2009-09-26    robert:     }
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert:   return 0;
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: 
7a39dde24b 2009-09-26    robert:   n->parent = n;
7a39dde24b 2009-09-26    robert:   n->next = n->children = NULL;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (!p->list) {
7a39dde24b 2009-09-26    robert:     if (n->level != 1) return 0;
7a39dde24b 2009-09-26    robert:     p->list = n;
7a39dde24b 2009-09-26    robert:     return 1;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   Node *list = p->list;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   while (n->level < list->level){
7a39dde24b 2009-09-26    robert:     list = list->parent;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (n->level == list->level){
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     if (n->kind != list->kind){
7a39dde24b 2009-09-26    robert:       if (n->level>1) return 0;
7a39dde24b 2009-09-26    robert:       cr_renderList(p);
7a39dde24b 2009-09-26    robert:       p->list = n;
7a39dde24b 2009-09-26    robert:       return 1;
7a39dde24b 2009-09-26    robert:     }
7a39dde24b 2009-09-26    robert:     n->parent = list->parent;
7a39dde24b 2009-09-26    robert:     p->list = list->next = n;
7a39dde24b 2009-09-26    robert:     return 1;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if ( (n->level - list->level) > 1 ) return 0;
7a39dde24b 2009-09-26    robert:   n->parent = p->list;
7a39dde24b 2009-09-26    robert:   p->list->children = n;
7a39dde24b 2009-09-26    robert:   p->list = n;
7a39dde24b 2009-09-26    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: static int isEndWikiMarker(Parser *p){//{{{
b877d2cfcd 2009-05-08    robert: 
7a39dde24b 2009-09-26    robert:   char *s = p->cursor;
7a39dde24b 2009-09-26    robert:   if (memcmp(s, "<<fossil>>", 10)) return 0;
7a39dde24b 2009-09-26    robert:   p->this->start = s;
7a39dde24b 2009-09-26    robert:   p->this->kind = KIND_END_WIKI_MARKER;
7a39dde24b 2009-09-26    robert:   p->cursor += 10;
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   char *s = p->cursor;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (s[0] != '{') return 0; s++;
7a39dde24b 2009-09-26    robert:   if (s[0] != '{') return 0; s++;
7a39dde24b 2009-09-26    robert:   if (s[0] != '{') return 0; s++;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   s = cr_nextLine(p, s);
7a39dde24b 2009-09-26    robert:   if (!p->lineWasBlank) return 0;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   p->this->start = s;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   s = cr_findEndOfBlock(p, s, '}');
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (!s) return 0;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   // p->cursor was set by findEndOfBlock
7a39dde24b 2009-09-26    robert:   p->this->kind = KIND_NO_WIKI_BLOCK;
7a39dde24b 2009-09-26    robert:   p->this->end = s;
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   char *s = cr_nextLine(p, p->cursor);
7a39dde24b 2009-09-26    robert:   if (!p->lineWasBlank) return 0;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   p->cursor = s;
7a39dde24b 2009-09-26    robert:   p->this->kind = KIND_PARA_BREAK;
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   char *s = cr_skipBlanks(p, p->cursor);
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   int flags = 0;
7a39dde24b 2009-09-26    robert:   int level = cr_countChars(p, s, '=');
7a39dde24b 2009-09-26    robert:   if (!level) return 0;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   s += level;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (s[0] == '<' && s[1] == '>') {
7a39dde24b 2009-09-26    robert:     flags |= FLAG_CENTER;
7a39dde24b 2009-09-26    robert:     s += 2;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert:   s = cr_skipBlanks(p, s);
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   p->this->start = s;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   s = cr_nextLine(p, s);
7a39dde24b 2009-09-26    robert:   char *z = s;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (s[-1] == '\n') s--;
7a39dde24b 2009-09-26    robert:   while(s[-1] == ' ' || s[-1]=='\t') s--;
7a39dde24b 2009-09-26    robert:   while(s[-1] == '=' ) s--;
7a39dde24b 2009-09-26    robert:   if (p->this->start < s){
7a39dde24b 2009-09-26    robert:     p->cursor = z;
7a39dde24b 2009-09-26    robert:     p->this->kind = KIND_HEADING;
7a39dde24b 2009-09-26    robert:     p->this->end = s;
7a39dde24b 2009-09-26    robert:     p->this->level = level;
7a39dde24b 2009-09-26    robert:     p->this->flags |= flags;
7a39dde24b 2009-09-26    robert:     return 1;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   char *s = cr_skipBlanks(p, p->cursor);
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   int level = cr_countChars(p, s, '-');
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if  (level < 4) return 0;
7a39dde24b 2009-09-26    robert:   s = cr_nextLine(p, s + level);
7a39dde24b 2009-09-26    robert:   if (!p->lineWasBlank) return 0;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   p->cursor = s;
7a39dde24b 2009-09-26    robert:   p->this->kind = KIND_HORIZONTAL_RULE;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   char *s = cr_skipBlanks(p, p->cursor);
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   int level = cr_countChars(p, s, '#');
7a39dde24b 2009-09-26    robert:   if (!level) level = cr_countChars(p, s, '*');
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if ( !level) return 0;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   p->this->kind = (s[0] == '#') ? KIND_ORDERED_LIST : KIND_UNORDERED_LIST;
7a39dde24b 2009-09-26    robert:   p->this->level = level;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   s = cr_skipBlanks(p, s + level);
7a39dde24b 2009-09-26    robert:   p->this->start = s;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   s = cr_nextLine(p, s);
7a39dde24b 2009-09-26    robert:   if (p->lineWasBlank) return 0;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   if (cr_addListItem(p, p->this)){
7a39dde24b 2009-09-26    robert:     p->cursor = p->this->end = s;
7a39dde24b 2009-09-26    robert:     return 1;
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    robert:   p->this->kind = 0;
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   p->this->start = p->cursor;
7a39dde24b 2009-09-26    robert:   char *s = cr_skipBlanks(p, p->cursor);
7a39dde24b 2009-09-26    robert:   if (s[0] != '|') return 0;
b877d2cfcd 2009-05-08    robert:   s +=1;
7a39dde24b 2009-09-26    robert:   p->this->kind = KIND_TABLE;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   //p->cursor =   p->this->end = cr_nextLine(p, s);
7a39dde24b 2009-09-26    robert:   Node *row;
7a39dde24b 2009-09-26    robert:   Node *tail = NULL;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   while (1) {
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     row = pool_new(p);
7a39dde24b 2009-09-26    robert:     row->kind = KIND_TABLE_ROW;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     if (tail)   tail = tail->next = row;
7a39dde24b 2009-09-26    robert:     else p->this->children = tail = row;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     row->start = s;
7a39dde24b 2009-09-26    robert:     p->cursor = s =   row->end = p->this->end = cr_nextLine(p, s);
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     if (row->end[-1] == '\n') row->end -= 1;
7a39dde24b 2009-09-26    robert:     while(row->end[-1] == ' ' ) row->end -= 1;
7a39dde24b 2009-09-26    robert:     if (row->end[-1] == '|') row->end -= 1;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     if (!*s) break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     // blanks *not* normalized
7a39dde24b 2009-09-26    robert:     s = cr_skipBlanks(p, p->cursor);
7a39dde24b 2009-09-26    robert:     if (s[0] != '|') break;
7a39dde24b 2009-09-26    robert:     s++;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   }
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   char *s = p->cursor;
7a39dde24b 2009-09-26    robert:   p->this->start = s;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   s = cr_nextLine(p, s);
7a39dde24b 2009-09-26    robert:   p->cursor = p->this->end = s;
7a39dde24b 2009-09-26    robert:   p->this->kind = KIND_PARAGRAPH;
7a39dde24b 2009-09-26    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: 
7a39dde24b 2009-09-26    robert:   p->previous = pool_new(p);
7a39dde24b 2009-09-26    robert:   p->previous->kind = KIND_PARA_BREAK;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   p->this = pool_new(p);
7a39dde24b 2009-09-26    robert:   p->this->kind = KIND_PARA_BREAK;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   p->inLink = 0;
7a39dde24b 2009-09-26    robert:   p->inTable = 0;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   p->cursor = z;
7a39dde24b 2009-09-26    robert:   p->list = NULL;
7a39dde24b 2009-09-26    robert:   p->istack = NULL;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   while (p->cursor[0]) {
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     while (1){
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       // must be first
7a39dde24b 2009-09-26    robert:       if (isNoWikiBlock(p)) break;
7a39dde24b 2009-09-26    robert:       if (isParaBreak(p))   break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       // order not important
7a39dde24b 2009-09-26    robert:       if (isHeading(p)) break;
7a39dde24b 2009-09-26    robert:       if (isHorizontalRule(p)) break;
7a39dde24b 2009-09-26    robert:       if (isListItem(p)) break;
7a39dde24b 2009-09-26    robert:       if (isTable(p)) break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       // here for efficiency?
7a39dde24b 2009-09-26    robert:       if (isEndWikiMarker(p)) break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       // must be last
7a39dde24b 2009-09-26    robert:       if (isParagraph(p)); break;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:       // doh!
7a39dde24b 2009-09-26    robert:       assert(0);
7a39dde24b 2009-09-26    robert:     }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     int kind = p->this->kind;
7a39dde24b 2009-09-26    robert:     int prev = p->previous->kind;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     if (kind & KIND_END_WIKI_MARKER)  return;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     if (kind == KIND_PARAGRAPH && prev & KIND_LIST_OR_PARAGRAPH) {
7a39dde24b 2009-09-26    robert:         p->previous->end = p->this->end;
7a39dde24b 2009-09-26    robert:         p->this = pool_new(p);
7a39dde24b 2009-09-26    robert:         continue;
7a39dde24b 2009-09-26    robert:     }
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     if ( !(kind & KIND_LIST && prev & KIND_LIST) )
7a39dde24b 2009-09-26    robert:       cr_render(p, p->previous);
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:     p->previous = p->this;
7a39dde24b 2009-09-26    robert:     p->this = pool_new(p);
b877d2cfcd 2009-05-08    robert: 
7a39dde24b 2009-09-26    robert:   }
b877d2cfcd 2009-05-08    robert: }
26af399a5c 2009-05-09    robert: //}}}
26af399a5c 2009-05-09    robert: 
b877d2cfcd 2009-05-08    robert: //}}}
b877d2cfcd 2009-05-08    robert: 
7a39dde24b 2009-09-26    robert: char *wiki_render_creole(Renderer *r, char *z){
b877d2cfcd 2009-05-08    robert: 
b877d2cfcd 2009-05-08    robert:   Parser parser;
7a39dde24b 2009-09-26    robert:   Parser *p = &parser;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   p->r = r;
7a39dde24b 2009-09-26    robert:   p->iblob = r->pOut;
7a39dde24b 2009-09-26    robert: 
7a39dde24b 2009-09-26    robert:   p->nFree = 0;
7a39dde24b 2009-09-26    robert:   p->pool = NULL;
b877d2cfcd 2009-05-08    robert: 
7a39dde24b 2009-09-26    robert:   cr_parse(p, z);
b877d2cfcd 2009-05-08    robert: 
7a39dde24b 2009-09-26    robert:   cr_render(p, p->previous);
b877d2cfcd 2009-05-08    robert: 
7a39dde24b 2009-09-26    robert:   pool_free(p);
b877d2cfcd 2009-05-08    robert: 
7a39dde24b 2009-09-26    robert:   return p->cursor;
b877d2cfcd 2009-05-08    robert: 
b877d2cfcd 2009-05-08    robert: }
7a39dde24b 2009-09-26    robert: