Check-in [2859293737]
Not logged in
Overview

SHA1 Hash:285929373757b9813748fd31744b4379dc163dfd
Date: 2007-11-22 22:55:05
User: drh
Comment:Add the %w and %W formatting options for internal printf usage. Use these formatting characters to render wiki. Fix additional problems of unterminated wiki on webpage rendering by using %w. (There are probably more problems yet to be discovered and fixed.)
Timelines: ancestors | descendants | both | trunk
Other Links: files | ZIP archive | manifest

Tags And Properties
Changes
[hide diffs]

Modified src/blob.c from [1da99958db] to [e355ed75f1].

@@ -540,31 +540,20 @@
   for(i=0; i<nToken && blob_token(pIn, &aToken[i]); i++){}
   return i;
 }
 
 /*
-** This function implements the callback from vxprintf.
-**
-** This routine add nNewChar characters of text in zNewText to
-** the Blob structure pointed to by "arg".
-*/
-static void bout(void *arg, const char *zNewText, int nNewChar){
-  Blob *pBlob = (Blob*)arg;
-  blob_append(pBlob, zNewText, nNewChar);
-}
-
-/*
 ** Do printf-style string rendering and append the results to a blob.
 */
 void blob_appendf(Blob *pBlob, const char *zFormat, ...){
   va_list ap;
   va_start(ap, zFormat);
-  vxprintf(bout, pBlob, zFormat, ap);
+  vxprintf(pBlob, zFormat, ap);
   va_end(ap);
 }
 void blob_vappendf(Blob *pBlob, const char *zFormat, va_list ap){
-  vxprintf(bout, pBlob, zFormat, ap);
+  vxprintf(pBlob, zFormat, ap);
 }
 
 /*
 ** Initalize a blob to the data on an input channel.  Return
 ** the number of bytes read into the blob.  Any prior content

Modified src/cgi.c from [470b9d6c4c] to [144475b0ed].

@@ -921,36 +921,26 @@
   }
   cgi_printf("%*s</select>\n", in, "");
 }
 
 /*
-** This function implements the callback from vxprintf.
-**
-** This routine sends nNewChar characters of text in zNewText to
-** CGI reply content buffer.
-*/
-static void sout(void *NotUsed, const char *zNewText, int nNewChar){
-  cgi_append_content(zNewText, nNewChar);
-}
-
-/*
 ** This routine works like "printf" except that it has the
 ** extra formatting capabilities such as %h and %t.
 */
 void cgi_printf(const char *zFormat, ...){
   va_list ap;
   va_start(ap,zFormat);
-  vxprintf(sout,0,zFormat,ap);
+  vxprintf(&cgiContent,zFormat,ap);
   va_end(ap);
 }
 
 /*
 ** This routine works like "vprintf" except that it has the
 ** extra formatting capabilities such as %h and %t.
 */
 void cgi_vprintf(const char *zFormat, va_list ap){
-  vxprintf(sout,0,zFormat,ap);
+  vxprintf(&cgiContent,zFormat,ap);
 }
 
 
 /*
 ** Send a reply indicating that the HTTP request was malformed
@@ -974,11 +964,11 @@
   cgi_printf(
     "<html><body><h1>Internal Server Error</h1>\n"
     "<plaintext>"
   );
   va_start(ap, zFormat);
-  vxprintf(sout,0,zFormat,ap);
+  vxprintf(&cgiContent,zFormat,ap);
   va_end(ap);
   cgi_reply();
   exit(1);
 }
 

Modified src/info.c from [17c99730c3] to [5b0da28053].

@@ -139,11 +139,11 @@
       }
       @ <ul>
     }
     @ <li>
     hyperlink_to_uuid(zUuid);
-    @ %s(zCom) (by %s(zUser) on %s(zDate))
+    @ %w(zCom) (by %s(zUser) on %s(zDate))
     if( depth ){
       n = showDescendents(cid, depth-1, 0);
     }else{
       n = db_int(0, "SELECT 1 FROM plink WHERE pid=%d", cid);
     }
@@ -190,11 +190,11 @@
       }
       @ <ul>
     }
     @ <li>
     hyperlink_to_uuid(zUuid);
-    @ %s(zCom) (by %s(zUser) on %s(zDate))
+    @ %w(zCom) (by %s(zUser) on %s(zDate))
     if( depth ){
       showAncestors(cid, depth-1, 0);
     }
   }
   db_finalize(&q);
@@ -229,11 +229,11 @@
       @ <div class="section-title">Leaves</div>
       @ <ul>
     }
     @ <li>
     hyperlink_to_uuid(zUuid);
-    @ %s(zCom) (by %s(zUser) on %s(zDate))
+    @ %w(zCom) (by %s(zUser) on %s(zDate))
   }
   db_finalize(&q);
   if( cnt ){
     @ </ul>
   }
@@ -316,11 +316,10 @@
      " WHERE blob.rid=%d"
      "   AND event.objid=%d",
      rid, rid
   );
   if( db_step(&q)==SQLITE_ROW ){
-    Blob comment;
     const char *zUuid = db_column_text(&q, 0);
     char *zTitle = mprintf("Version: [%.10s]", zUuid);
     style_header(zTitle);
     free(zTitle);
     /*@ <h2>Version %s(zUuid)</h2>*/
@@ -329,14 +328,12 @@
     @ <tr><th>Version:</th><td>%s(zUuid)</td></tr>
     @ <tr><th>Date:</th><td>%s(db_column_text(&q, 1))</td></tr>
     if( g.okSetup ){
       @ <tr><th>Record ID:</th><td>%d(rid)</td></tr>
     }
-    @ <tr><th>Original&nbsp;User:</th><td>%s(db_column_text(&q, 2))</td></tr>
-    @ <tr><th>Original&nbsp;Comment:</th><td>
-    db_ephemeral_blob(&q, 3, &comment);
-    wiki_convert(&comment, 0, 0);
+    @ <tr><th>Original&nbsp;User:</th><td>%h(db_column_text(&q, 2))</td></tr>
+    @ <tr><th>Original&nbsp;Comment:</th><td>%w(db_column_text(&q,3))</td></tr>
     @ </td></tr>
     @ <tr><th>Commands:</th>
     @   <td>
     @     <a href="%s(g.zBaseURL)/vdiff/%d(rid)">diff</a>
     @     | <a href="%s(g.zBaseURL)/zip/%s(zUuid).zip">ZIP archive</a>
@@ -602,21 +599,17 @@
   );
   while( db_step(&q)==SQLITE_ROW ){
     const char *zName = db_column_text(&q, 0);
     const char *zDate = db_column_text(&q, 1);
     const char *zFuuid = db_column_text(&q, 2);
+    const char *zCom = db_column_text(&q, 3);
     const char *zUser = db_column_text(&q, 4);
     const char *zVers = db_column_text(&q, 5);
-    Blob comment;
     @ File <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a>
     @ uuid %s(zFuuid) part of check-in
     hyperlink_to_uuid(zVers);
-    blob_zero(&comment);
-    db_column_blob(&q, 3, &comment);
-    blob_appendf(&comment, " by %h(zUser) on %s(zDate)");
-    wiki_convert(&comment, 0, 0);
-    blob_reset(&comment);
+    @ %w(zCom) by %h(zUser) on %s(zDate)
     cnt++;
   }
   db_finalize(&q);
   db_prepare(&q,
     "SELECT substr(tagname, 6, 10000), datetime(event.mtime),"
@@ -651,18 +644,14 @@
     );
     while( db_step(&q)==SQLITE_ROW ){
       const char *zDate = db_column_text(&q, 0);
       const char *zUuid = db_column_text(&q, 3);
       const char *zUser = db_column_text(&q, 1);
-      Blob comment;
+      const char *zCom = db_column_text(&q, 2);
       @ Manifest of version
       hyperlink_to_uuid(zUuid);
-      blob_zero(&comment);
-      db_column_blob(&q, 2, &comment);
-      blob_appendf(&comment, " by %h(zUser) on %s(zDate)");
-      wiki_convert(&comment, 0, 0);
-      blob_reset(&comment);
+      @ %w(zCom) by %h(zUser) on %s(zDate)
       cnt++;
     }
     db_finalize(&q);
   }
   if( cnt==0 ){

Modified src/printf.c from [63619c9ec6] to [af38cba6b0].

@@ -50,10 +50,12 @@
 #define etHTMLIZE    16 /* Make text safe for HTML */
 #define etHTTPIZE    17 /* Make text safe for HTTP.  "/" encoded as %2f */
 #define etURLIZE     18 /* Make text safe for HTTP.  "/" not encoded */
 #define etFOSSILIZE  19 /* The fossil header encoding format. */
 #define etPATH       20 /* Path type */
+#define etWIKISTR    21 /* Wiki text rendered from a char* */
+#define etWIKIBLOB   22 /* Wiki text rendered from a Blob* */
 
 
 /*
 ** An "etByte" is an 8-bit unsigned value.
 */
@@ -93,10 +95,12 @@
   {  'z',  0, 6, etDYNSTRING,  0,  0 },
   {  'q',  0, 4, etSQLESCAPE,  0,  0 },
   {  'Q',  0, 4, etSQLESCAPE2, 0,  0 },
   {  'b',  0, 2, etBLOB,       0,  0 },
   {  'B',  0, 2, etBLOBSQL,    0,  0 },
+  {  'w',  0, 2, etWIKISTR,    0,  0 },
+  {  'W',  0, 2, etWIKIBLOB,   0,  0 },
   {  'h',  0, 4, etHTMLIZE,    0,  0 },
   {  't',  0, 4, etHTTPIZE,    0,  0 },  /* "/" -> "%2F" */
   {  'T',  0, 4, etURLIZE,     0,  0 },  /* "/" unchanged */
   {  'F',  0, 4, etFOSSILIZE,  0,  0 },
   {  'c',  0, 0, etCHARX,      0,  0 },
@@ -171,12 +175,11 @@
 ** Note that the order in which automatic variables are declared below
 ** seems to make a big difference in determining how fast this beast
 ** will run.
 */
 int vxprintf(
-  void (*func)(void*,const char*,int),     /* Consumer of text */
-  void *arg,                         /* First argument to the consumer */
+  Blob *pBlob,                       /* Append output to this blob */
   const char *fmt,                   /* Format string */
   va_list ap                         /* arguments */
 ){
   int c;                     /* Next character in the format string */
   char *bufpt;               /* Pointer to the conversion buffer */
@@ -210,26 +213,25 @@
   etByte flag_dp;            /* True if decimal point should be shown */
   etByte flag_rtz;           /* True if trailing zeros should be removed */
   etByte flag_exp;           /* True to force display of the exponent */
   int nsd;                   /* Number of significant digits returned */
 
-  func(arg,"",0);
   count = length = 0;
   bufpt = 0;
   for(; (c=(*fmt))!=0; ++fmt){
     if( c!='%' ){
       int amt;
       bufpt = (char *)fmt;
       amt = 1;
       while( (c=(*++fmt))!='%' && c!=0 ) amt++;
-      (*func)(arg,bufpt,amt);
+      blob_append(pBlob,bufpt,amt);
       count += amt;
       if( c==0 ) break;
     }
     if( (c=(*++fmt))==0 ){
       errorflag = 1;
-      (*func)(arg,"%",1);
+      blob_append(pBlob,"%",1);
       count++;
       break;
     }
     /* Find out what flags are present */
     flag_leftjustify = flag_plussign = flag_blanksign =
@@ -659,16 +661,31 @@
         zExtra = bufpt = fossilize(zMem, -1);
         length = strlen(bufpt);
         if( precision>=0 && precision<length ) length = precision;
         break;
       }
+      case etWIKISTR: {
+        char *zWiki = va_arg(ap, char*);
+        Blob wiki;
+        blob_init(&wiki, zWiki, -1);
+        wiki_convert(&wiki, pBlob, WIKI_INLINE);
+        blob_reset(&wiki);
+        length = width = 0;
+        break;
+      }
+      case etWIKIBLOB: {
+        Blob *pWiki = va_arg(ap, Blob*);
+        wiki_convert(pWiki, pBlob, WIKI_INLINE);
+        length = width = 0;
+        break;
+      }
       case etERROR:
         buf[0] = '%';
         buf[1] = c;
         errorflag = 0;
         idx = 1+(c!=0);
-        (*func)(arg,"%",idx);
+        blob_append(pBlob,"%",idx);
         count += idx;
         if( c==0 ) fmt--;
         break;
     }/* End switch over the format type */
     /*
@@ -680,30 +697,30 @@
       register int nspace;
       nspace = width-length;
       if( nspace>0 ){
         count += nspace;
         while( nspace>=etSPACESIZE ){
-          (*func)(arg,spaces,etSPACESIZE);
+          blob_append(pBlob,spaces,etSPACESIZE);
           nspace -= etSPACESIZE;
         }
-        if( nspace>0 ) (*func)(arg,spaces,nspace);
+        if( nspace>0 ) blob_append(pBlob,spaces,nspace);
       }
     }
     if( length>0 ){
-      (*func)(arg,bufpt,length);
+      blob_append(pBlob,bufpt,length);
       count += length;
     }
     if( flag_leftjustify ){
       register int nspace;
       nspace = width-length;
       if( nspace>0 ){
         count += nspace;
         while( nspace>=etSPACESIZE ){
-          (*func)(arg,spaces,etSPACESIZE);
+          blob_append(pBlob,spaces,etSPACESIZE);
           nspace -= etSPACESIZE;
         }
-        if( nspace>0 ) (*func)(arg,spaces,nspace);
+        if( nspace>0 ) blob_append(pBlob,spaces,nspace);
       }
     }
     if( zExtra ){
       free(zExtra);
     }