* finish selectboxes in Mailedit dialogs
authorWilfried Göesgens <willi@citadel.org>
Sun, 23 Nov 2008 18:22:20 +0000 (18:22 +0000)
committerWilfried Göesgens <willi@citadel.org>
Sun, 23 Nov 2008 18:22:20 +0000 (18:22 +0000)
* new templating mechanism: if prepended by : ; _ B the tokens can be loaded via preferences / gettext / bstr
* start implementing preferences screen with templates
* fix some tiny bugs

webcit/context_loop.c
webcit/preferences.c
webcit/static/t/beginbox.html
webcit/static/t/beginbox.m.html
webcit/static/t/box_preferences.html [new file with mode: 0644]
webcit/static/t/preferences.html [new file with mode: 0644]
webcit/static/t/pushemail.html
webcit/static/t/section_msg_sender_from_select.html
webcit/static/t/section_msg_sender_name_select.html
webcit/subst.c
webcit/webcit.h

index 9bbb477c40418ed28ee477c42ed2cece7bea182d..ece52c75466b14d01d14bb1742d46351db9a9d8b 100644 (file)
@@ -356,7 +356,7 @@ void context_loop(int *sock)
                    (isspace(*ChrPtr(Line)))) {
                        pch = pchs = ChrPtr(Line);
                        pche = pchs + StrLength(Line);
-                       while (isspace(pch) && (pch < pche))
+                       while (isspace(*pch) && (pch < pche))
                                pch ++;
                        StrBufCutLeft(Line, pch - pchs);
                        StrBufAppendBuf(LastLine, Line, 0);
@@ -444,7 +444,7 @@ void context_loop(int *sock)
        StrBufCutLeft(ReqLine, StrLength(ReqType) + 1);
        StrBufCutRight(ReqLine, StrLength(HTTPVersion) + 1);
 
-       if ((StrLength(ReqLine) >= 8) &&
+       if ((follow_xff == 1) && (StrLength(ReqLine) >= 8) &&
            (ptr = strstr(ChrPtr(ReqLine), "/webcit/"), /*< Handle "/webcit/" */
             (ptr != NULL))) {
                StrBufCutLeft(ReqLine, 7);
index e4689e8ad5381397c132b822f734b2d1ed8adc4f..c839d57380d80ce5a79e56506a0c07f791cba0c3 100644 (file)
@@ -654,6 +654,9 @@ void set_preferences(void)
        set_pref_long("dayend", lbstr("dayend"), 0);
        set_preference("default_header_charset", NewStrBufPlain(bstr("default_header_charset"), -1), 0);
        set_preference("emptyfloors", NewStrBufPlain(bstr("emptyfloors"), -1), 0);
+       set_preference("defaultfrom", NewStrBufDup(sbstr("defaultfrom")), 0);
+       set_preference("defaultname", NewStrBufDup(sbstr("defaultname")), 0);
+
 
        buf = NewStrBufPlain(bstr("signature"), -1);
        encBuf = NewStrBuf();
@@ -751,11 +754,6 @@ void DeleteGVEAHash(HashList **KillMe)
 {
        DeleteHash(KillMe);
 }
-void tmplput_EMAIL_ADDR(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       StrBuf *EmailAddr = (StrBuf*) Context;
-       StrBufAppendBuf(Target, EmailAddr, 0);
-}
 
 HashList *GetGVSNHash(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
 {
@@ -792,11 +790,7 @@ void DeleteGVSNHash(HashList **KillMe)
 {
        DeleteHash(KillMe);
 }
-void tmplput_EMAIL_NAME(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       StrBuf *EmailAddr = (StrBuf*) Context;
-       StrBufAppendBuf(Target, EmailAddr, 0);
-}
+
 
 void 
 InitModule_PREFERENCES
@@ -815,6 +809,11 @@ InitModule_PREFERENCES
        RegisterPreference("signature",_("Use this signature:"),PRF_QP_STRING);
        RegisterPreference("default_header_charset", _("Default character set for email headers:") ,PRF_STRING);
        RegisterPreference("emptyfloors", _("Show empty floors"), PRF_YESNO);
+       RegisterPreference("defaultfrom", _("Prefered Email Address"), PRF_STRING);
+       RegisterPreference("defaultname", _("Prefered Email Sendername"), PRF_STRING);
+
+
+
        
        RegisterNamespace("PREF:VALUE", 1, 2, tmplput_CFG_Value, CTX_NONE);
        RegisterNamespace("PREF:DESCR", 1, 1, tmplput_CFG_Descr, CTX_NONE);
@@ -822,12 +821,10 @@ InitModule_PREFERENCES
 
        RegisterConditional(HKEY("COND:PREF"), 4, ConditionalPreference, CTX_NONE);
        
-       RegisterNamespace("PREF:EMAIL:ADDR", 0, 1, tmplput_EMAIL_ADDR, CTX_GVEA);
        RegisterIterator("PREF:VALID:EMAIL:ADDR", 0, NULL, 
-                        GetGVEAHash, NULL, DeleteGVEAHash, CTX_GVEA, CTX_NONE);
-       RegisterNamespace("PREF:EMAIL:NAME", 0, 1, tmplput_EMAIL_NAME, CTX_GVSN);
+                        GetGVEAHash, NULL, DeleteGVEAHash, CTX_STRBUF, CTX_NONE);
        RegisterIterator("PREF:VALID:EMAIL:NAME", 0, NULL, 
-                        GetGVSNHash, NULL, DeleteGVSNHash, CTX_GVSN, CTX_NONE);
+                        GetGVSNHash, NULL, DeleteGVSNHash, CTX_STRBUF, CTX_NONE);
 
 }
 /*@}*/
index 593fefef9eaba94892b74beff1228946e0a924bc..32ecfedac963358f6e1104dfa9d21604385a6321 100644 (file)
@@ -1,5 +1,5 @@
 <!-- start beginbox.html-->
 <div class="box">
-<div class="boxlabel"><?BOXTITLE></div>
+<div class="boxlabel"><?BOXTITLE><?CONTEXTSTR("X)></div>
 <div class="boxcontent">
 <!-- end beginbox.html-->
index 593fefef9eaba94892b74beff1228946e0a924bc..2d9cc609da0f0cc00cb291eeaaa55cd555b05e8e 100644 (file)
@@ -1,5 +1,5 @@
 <!-- start beginbox.html-->
 <div class="box">
-<div class="boxlabel"><?BOXTITLE></div>
+<div class="boxlabel"><?CONTEXTSTR("X")></div>
 <div class="boxcontent">
 <!-- end beginbox.html-->
diff --git a/webcit/static/t/box_preferences.html b/webcit/static/t/box_preferences.html
new file mode 100644 (file)
index 0000000..faa26c9
--- /dev/null
@@ -0,0 +1,143 @@
+<?%("COND:PREF", 1, :"", "", "selected", "")>
+
+<form name="prefform" action="set_preferences" method="post">
+<input type="hidden" name="nonce" value="<?NONCE>">
+<table class="altern">
+<?:("roomlistview")>
+
+<tr class="even"><td><?PREF:DESCR("roomlistview")> </td>
+<td>
+  <input type="radio" name="roomlistview" VALUE="folders" <?%("COND:PREF", 1, :"roomlistview", "folders", "selected", "")> ><?_("Tree (folders) view")></input>
+  &nbsp;&nbsp;&nbsp;
+  <input type="radio" name="roomlistview" VALUE="rooms" <?%("COND:PREF", 1, :"roomlistview", "rooms", "selected", "")>><?_("Table (rooms) view")></input>
+</td>
+</tr>
+
+<tr class="odd">
+  <td><?PREF:DESCR("calhourformat")</td>
+  <td>
+    <input type="radio" name="calhourformat" VALUE="12" <?%("COND:PREF", 1, :"calhourformat", "12", "selected", "")>><?_("12 hour (am/pm)")></input>
+    &nbsp;&nbsp;&nbsp;
+    <input type="radio" name="calhourformat" VALUE="24" <?%("COND:PREF", 1, :"calhourformat", "24", "selected", "")> ><?_("24 hour")></input>
+  </td>
+</tr>
+
+
+<tr class="even"><td><?PREF:DESCR("daystart")></td><td>
+<select name="daystart" size="1">
+<option <?%("COND:PREF", 1, :"daystart", "0", "selected", "")> value="0">0:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "1", "selected", "")> value="1">1:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "2", "selected", "")> value="2">2:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "3", "selected", "")> value="3">3:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "4", "selected", "")> value="4">4:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "5", "selected", "")> value="5">5:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "6", "selected", "")> value="6">6:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "7", "selected", "")> value="7">7:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "8", "selected", "")> value="8">8:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "9", "selected", "")> value="9">9:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "10", "selected", "")> value="10">10:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "11", "selected", "")> value="11">11:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "12", "selected", "")> value="12">12:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "13", "selected", "")> value="13">13:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "14", "selected", "")> value="14">14:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "15", "selected", "")> value="15">15:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "16", "selected", "")> value="16">16:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "17", "selected", "")> value="17">17:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "18", "selected", "")> value="18">18:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "19", "selected", "")> value="19">19:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "20", "selected", "")> value="20">20:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "21", "selected", "")> value="21">21:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "22", "selected", "")> value="22">22:00</option>
+<option <?%("COND:PREF", 1, :"daystart", "23", "selected", "")> value="23">23:00</option>
+</select>
+</td></tr>
+
+<tr class="odd">
+  <td><?PREF:DESCR("dayend")></td>
+  <td><select name="dayend" size="1">
+<option <?%("COND:PREF", 1, :"dayend", "0", "selected", "")> value="0">0:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "1", "selected", "")> value="1">1:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "2", "selected", "")> value="2">2:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "3", "selected", "")> value="3">3:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "4", "selected", "")> value="4">4:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "5", "selected", "")> value="5">5:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "6", "selected", "")> value="6">6:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "7", "selected", "")> value="7">7:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "8", "selected", "")> value="8">8:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "9", "selected", "")> value="9">9:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "10", "selected", "")> value="10">10:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "11", "selected", "")> value="11">11:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "12", "selected", "")> value="12">12:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "13", "selected", "")> value="13">13:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "14", "selected", "")> value="14">14:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "15", "selected", "")> value="15">15:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "16", "selected", "")> value="16">16:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "17", "selected", "")> value="17">17:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "18", "selected", "")> value="18">18:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "19", "selected", "")> value="19">19:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "20", "selected", "")> value="20">20:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "21", "selected", "")> value="21">21:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "22", "selected", "")> value="22">22:00</option>
+<option <?%("COND:PREF", 1, :"dayend", "23", "selected", "")> value="23">23:00</option>
+</select>
+</td></tr>
+
+<tr class="even">
+  <td>
+    <?PREF:DESCR("weekstart")>
+  </td>
+  <td>
+    <select name="weekstart" size="1">
+      <option <?%("COND:PREF", 1, :"weekstart", "0", "selected", "") value="0"><?_("Sunday")></option>
+      <option <?%("COND:PREF", 1, :"weekstart", "1", "selected", "") value="1"><?_("Monday")></option>
+    </select>
+  </td>
+</tr>
+
+<tr class="odd">
+   <td><?PREF:DESCR("use_sig")></td>
+   <td>
+       <script type="text/javascript">
+       function show_or_hide_sigbox() {
+               if ( $F('yes_sig') ) {
+                       $('signature_box').style.display = 'inline';
+               }
+               else {
+                       $('signature_box').style.display = 'none';
+               }
+       }
+       </script>
+
+signature
+
+       
+       <input type="radio" id="no_sig" name="use_sig" VALUE="no" checked onChange="show_or_hide_sigbox();" ><?_("No signature")></input>
+       &nbsp,&nbsp;&nbsp;
+       <input type="radio" id="yes_sig" name="use_sig" VALUE="yes" onChange="show_or_hide_sigbox();" >
+               <div id="signature_box"><br>
+                 <textarea name="signature" cols="40" rows="5"><?PREF:VALUE("signature")></textarea>
+               </div></input>
+  </td>
+</tr>
+<script type="text/javascript">show_or_hide_sigbox();</script>
+
+<tr class="even">
+  <td><?PREF:DESCR("default_header_charset")></td>
+  <td><input type="text" NAME="default_header_charset" MAXLENGTH="32" VALUE="<?PREF:VALUE("default_header_charset")>">
+</td>
+
+</tr>
+  <tr class="odd">
+    <td><?PREF:DESCR("emptyfloors")></td>
+    <td>
+      <input type="radio" name="emptyfloors" VALUE="yes" <?%("COND:PREF", 1, :"emptyfloors", "yes", "selected", "")> ><?_("Yes")></input>
+      &nbsp;&nbsp;&nbsp;
+      <input type="radio" name="emptyfloors" VALUE="no"  <?%("COND:PREF", 1, :"emptyfloors", "no",  "selected", "")> ><?_("No")></input>
+</td>
+</tr>
+</table>
+
+<div class="buttons"> 
+  <input type="submit" name="change_button" value="<?_("Change")>">&nbsp;
+  <input type="submit" name="cancel_button" value="<?_("Cancel")>">
+</div>
diff --git a/webcit/static/t/preferences.html b/webcit/static/t/preferences.html
new file mode 100644 (file)
index 0000000..3b30345
--- /dev/null
@@ -0,0 +1,9 @@
+<?=("head")>
+<?=("important_msg")>
+<?ICONBAR>
+<div id="banner">
+</div>
+<div id="content" class="service">
+<?DOBOXED("box_preferences", _"Preferences and settings")>
+</div>
+<?=("trailing")>
index bf9213b8ce329fbcdb02e0cb4105cf15ea145fa6..15711e910fe191ed856a92fc163d8514d1445d44 100644 (file)
@@ -5,7 +5,7 @@
     <div id="content" class="config_service">
     <!-- NOT beginbox -->
     <div class="box">
-    <div class="boxlabel"><?BOXTITLE></div>
+    <div class="boxlabel"><?BOXTITLE><?CONTEXTSTR("X")></div>
     <div class="boxcontent">
        <!-- still not begin box -->
     <!-- Begin Push email configure -->
index d683d6fa98e04a3c4b2242f7e4193b405dcd78db..6fe807466be3ede5effd3bb600e599030dc94cc9 100644 (file)
@@ -1 +1 @@
-<option value="willi@peza.home.net">&lt;willi@peza.home.net&gt;</option>
+<option value="<?CONTEXTSTR("X")>" <?%("COND:CONTEXTSTR", 1, :"defaultname", "selected", "")>>&lt;<?CONTEXTSTR("H")>&gt;</option>
index 41373c54b1459f1ed62f42d6bb661ad00ce7938d..a0b760f4cf00993c5a4003fa721dddc60c9e379c 100644 (file)
@@ -1 +1 @@
-<option  value="<?PREF:EMAIL:NAME("X")>"><?PREF:EMAIL:NAME("U")></option>
+<option  value="<?CONTEXTSTR("X")>"><?CONTEXTSTR("U") <?%("COND:CONTEXTSTR", 1, :"defaultfrom", "selected", "")></option>
index c77851bf8236c6e26c9830e452b3d9075b024224..4d102045bd0d9ab7a3481fed3989d3de3cc8d9bd 100644 (file)
@@ -506,6 +506,54 @@ void StrBufAppendTemplate(StrBuf *Target,
 }
 
 
+void GetTemplateTokenString(WCTemplateToken *Tokens,
+                           int N, 
+                           const char **Value, 
+                           long *len)
+{
+       StrBuf *Buf;
+
+       if (Tokens->HaveParameters < N) {
+               *Value = "";
+               *len = 0;
+               return;
+       }
+
+       switch (Tokens->Params[N]->Type) {
+
+       case TYPE_STR:
+               *Value = Tokens->Params[N]->Start;
+               *len = Tokens->Params[N]->len;
+               break;
+       case TYPE_BSTR:
+               Buf = (StrBuf*) SBstr(Tokens->Params[N]->Start, 
+                                     Tokens->Params[N]->len);
+               *Value = ChrPtr(Buf);
+               *len = StrLength(Buf);
+               break;
+       case TYPE_PREFSTR:
+               get_PREFERENCE(
+                       Tokens->Params[N]->Start, 
+                       Tokens->Params[N]->len, 
+                       &Buf);
+               *Value = ChrPtr(Buf);
+               *len = StrLength(Buf);
+               break;
+       case TYPE_LONG:
+       case TYPE_PREFINT:
+               break; ///todo: string to text?
+       case TYPE_GETTEXT:
+               *Value = _(Tokens->Params[N]->Start);
+               *len = strlen(*Value);
+               break;
+       default:
+               break;
+//todo log error
+       }
+}
+
+
+
 /**
  * \brief Print the value of a variable
  * \param keyname get a key to print
@@ -658,11 +706,33 @@ TemplateParam *GetNextParameter(StrBuf *Buf, const char **pCh, const char *pe, W
        TemplateParam *Parm = (TemplateParam *) malloc(sizeof(TemplateParam));
        char quote = '\0';
        
+
+       Parm->Type = TYPE_STR;
+
        /* Skip leading whitespaces */
        while ((*pch == ' ' )||
               (*pch == '\t')||
               (*pch == '\r')||
               (*pch == '\n')) pch ++;
+
+       if (*pch == ':') {
+               Parm->Type = TYPE_PREFSTR;
+               pch ++;
+       }
+       else if (*pch == ';') {
+               Parm->Type = TYPE_PREFINT;
+               pch ++;
+       }
+       else if (*pch == '_') {
+               Parm->Type = TYPE_GETTEXT;
+               pch ++;
+       }
+       else if (*pch == 'B') {
+               Parm->Type = TYPE_BSTR;
+               pch ++;
+       }
+
+
        if (*pch == '"')
                quote = '"';
        else if (*pch == '\'')
@@ -670,7 +740,6 @@ TemplateParam *GetNextParameter(StrBuf *Buf, const char **pCh, const char *pe, W
        if (quote != '\0') {
                pch ++;
                pchs = pch;
-               Parm->Type = TYPE_STR;
                while (pch <= pe &&
                       ((*pch != quote) ||
                        ( (pch > pchs) && (*(pch - 1) == '\\'))
@@ -1572,19 +1641,46 @@ void RegisterConditional(const char *Name, long len,
        Put(Conditionals, Name, len, Cond, NULL);
 }
 
+
+void tmplput_ContextString(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+       StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, (StrBuf*)Context, 0);
+}
+int ConditionalContextStr(WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+       StrBuf *EmailAddr = (StrBuf*) Context;
+       const char *CompareToken;
+       long len;
+
+       GetTemplateTokenString(Tokens, 3, &CompareToken, &len);
+       return strcmp(ChrPtr(EmailAddr), CompareToken) == 0;
+}
+
+
 void tmpl_do_boxed(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
 {
+       StrBuf *Headline;
        if (nArgs == 2) {
-               StrBuf *Headline = NewStrBuf();
-               DoTemplate(Tokens->Params[1]->Start, 
-                          Tokens->Params[1]->len,
-                          Headline, 
-                          Context, 
-                          ContextType);
-               SVPutBuf("BOXTITLE", Headline, 0);
+               if (Tokens->Params[1]->Type == TYPE_STR) {
+                       Headline = NewStrBuf();
+                       DoTemplate(Tokens->Params[1]->Start, 
+                                  Tokens->Params[1]->len,
+                                  Headline, 
+                                  Context, 
+                                  ContextType);
+               }
+               else {
+                       const char *Ch;
+                       long *len;
+                       GetTemplateTokenString(Tokens, 
+                                              1,
+                                              &Ch,
+                                              &len);
+                       Headline = NewStrBufPlain(Ch, len);
+               }
        }
        
-       DoTemplate(HKEY("beginbox"), Target, Context, ContextType);
+       DoTemplate(HKEY("beginbox"), Target, Headline, CTX_STRBUF);
        DoTemplate(Tokens->Params[0]->Start, 
                   Tokens->Params[0]->len,
                   Target, 
@@ -1593,6 +1689,7 @@ void tmpl_do_boxed(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Con
        DoTemplate(HKEY("endbox"), Target, Context, ContextType);
 }
 
+
 void tmpl_do_tabbed(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
 {
        StrBuf **TabNames;
@@ -1633,10 +1730,13 @@ void
 InitModule_SUBST
 (void)
 {
+       RegisterNamespace("CONTEXTSTR", 0, 1, tmplput_ContextString, CTX_STRBUF);
        RegisterNamespace("ITERATE", 2, 100, tmpl_iterate_subtmpl, CTX_NONE);
        RegisterNamespace("DOBOXED", 1, 2, tmpl_do_boxed, CTX_NONE);
        RegisterNamespace("DOTABBED", 2, 100, tmpl_do_tabbed, CTX_NONE);
        RegisterConditional(HKEY("COND:SUBST"), 3, ConditionalVar, CTX_NONE);
+       RegisterConditional(HKEY("COND:CONTEXT"), 3, ConditionalContextStr, CTX_NONE);
+
 }
 
 /*@}*/
index 4aa951252ea98f3a7b0f5f4876a553d8ea24cd84..7dd5922d55a0183a397d8fb9a3ed165edcc3265a 100644 (file)
@@ -260,7 +260,13 @@ struct roomlisting {
 
 #define TYPE_STR   1
 #define TYPE_LONG  2
+#define TYPE_PREFSTR 3
+#define TYPE_PREFINT 4
+#define TYPE_GETTEXT 5
+#define TYPE_BSTR 6
 #define MAXPARAM  20
+
+
 typedef struct _TemplateParam {
        const char *Start;
        int Type;
@@ -314,8 +320,7 @@ typedef struct _wcsubst {
 #define CTX_MAILSUM 9
 #define CTX_MIME_ATACH 10
 #define CTX_ATT 11
-#define CTX_GVEA 12
-#define CTX_GVSN 13
+#define CTX_STRBUF 12
 
 void RegisterNS(const char *NSName, long len, 
                int nMinArgs, 
@@ -350,6 +355,12 @@ void RegisterITERATOR(const char *Name, long len, /* Our identifier */
                      int XPectContextType);         /* which context do we expct to be called in? */
 #define RegisterIterator(a, b, c, d, e, f, g, h) RegisterITERATOR(a, sizeof(a)-1, b, c, d, e, f, g, h)
 
+void GetTemplateTokenString(WCTemplateToken *Tokens,
+                           int N, 
+                           const char **Value, 
+                           long *len);
+
+
 void SVPut(char *keyname, size_t keylen, int keytype, char *Data);
 #define svput(a, b, c) SVPut(a, sizeof(a) - 1, b, c)
 void SVPutLong(char *keyname, size_t keylen, long Data);