OSDN Git Service

* Added test code of the <ol> tag for SoftBank HTML converter.
[modchxj/mod_chxj.git] / src / chxj_jhtml.c
index 19266ed..649f7bb 100644 (file)
@@ -21,6 +21,7 @@
 #include "chxj_qr_code.h"
 #include "chxj_encoding.h"
 #include "chxj_url_encode.h"
+#include "chxj_str_util.h"
 
 
 #define GET_JHTML(X) ((jhtml_t *)(X))
@@ -28,7 +29,7 @@
 #undef W_V
 #define W_L(X)          do { jhtml->out = BUFFERED_WRITE_LITERAL(jhtml->out, &doc->buf, (X)); } while(0)
 #define W_V(X)          do { jhtml->out = (X) ? BUFFERED_WRITE_VALUE(jhtml->out, &doc->buf, (X))  \
-                                               : BUFFERED_WRITE_LITERAL(jhtml->out, &doc->buf, ""); } while(0)
+                                              : BUFFERED_WRITE_LITERAL(jhtml->out, &doc->buf, ""); } while(0)
 
 static char *s_jhtml_start_html_tag     (void *pdoc, Node *node);
 static char *s_jhtml_end_html_tag       (void *pdoc, Node *node);
@@ -92,12 +93,26 @@ static char *s_jhtml_start_dt_tag       (void *pdoc, Node *node);
 static char *s_jhtml_end_dt_tag         (void *pdoc, Node *node);
 static char *s_jhtml_start_dd_tag       (void *pdoc, Node *node);
 static char *s_jhtml_end_dd_tag         (void *pdoc, Node *node);
+static char *s_jhtml_start_h1_tag       (void *pdoc, Node *node);
+static char *s_jhtml_end_h1_tag         (void *pdoc, Node *node);
+static char *s_jhtml_start_h2_tag       (void *pdoc, Node *node);
+static char *s_jhtml_end_h2_tag         (void *pdoc, Node *node);
+static char *s_jhtml_start_h3_tag       (void *pdoc, Node *node);
+static char *s_jhtml_end_h3_tag         (void *pdoc, Node *node);
+static char *s_jhtml_start_h4_tag       (void *pdoc, Node *node);
+static char *s_jhtml_end_h4_tag         (void *pdoc, Node *node);
+static char *s_jhtml_start_h5_tag       (void *pdoc, Node *node);
+static char *s_jhtml_end_h5_tag         (void *pdoc, Node *node);
+static char *s_jhtml_start_h6_tag       (void *pdoc, Node *node);
+static char *s_jhtml_end_h6_tag         (void *pdoc, Node *node);
+static char *s_jhtml_start_menu_tag     (void *pdoc, Node *node);
+static char *s_jhtml_end_menu_tag       (void *pdoc, Node *node);
 
 static void  s_init_jhtml(jhtml_t *jhtml, Doc *doc, request_rec *r, device_table *spec);
 
 static int   s_jhtml_search_emoji(jhtml_t *jhtml, char *txt, char **rslt);
 
-static char *chxj_istyle_to_mode(request_rec *r, const char *s);
+static char *chxj_istyle_to_mode(apr_pool_t *p, const char *s);
 
 
 
@@ -144,33 +159,33 @@ tag_handler jhtml_handler[] = {
   },
   /* tagH1 */
   {
-    NULL,
-    NULL,
+    s_jhtml_start_h1_tag,
+    s_jhtml_end_h1_tag,
   },
   /* tagH2 */
   {
-    NULL,
-    NULL,
+    s_jhtml_start_h2_tag,
+    s_jhtml_end_h2_tag,
   },
   /* tagH3 */
   {
-    NULL,
-    NULL,
+    s_jhtml_start_h3_tag,
+    s_jhtml_end_h3_tag,
   },
   /* tagH4 */
   {
-    NULL,
-    NULL,
+    s_jhtml_start_h4_tag,
+    s_jhtml_end_h4_tag,
   },
   /* tagH5 */
   {
-    NULL,
-    NULL,
+    s_jhtml_start_h5_tag,
+    s_jhtml_end_h5_tag,
   },
   /* tagH6 */
   {
-    NULL,
-    NULL,
+    s_jhtml_start_h6_tag,
+    s_jhtml_end_h6_tag,
   },
   /* tagHEAD */
   {
@@ -349,8 +364,8 @@ tag_handler jhtml_handler[] = {
   },
   /* tagMENU */
   {
-    NULL,
-    NULL,
+    s_jhtml_start_menu_tag,
+    s_jhtml_end_menu_tag,
   },
   /* tagPLAINTEXT */
   {
@@ -1445,64 +1460,74 @@ s_jhtml_start_input_tag(void *pdoc, Node *node)
   size       = qs_get_size_attr(doc, node, r);
 
   if (type) {
-    W_L(" type=\"");
-    W_V(type);
-    W_L("\" ");
+    if (type && (STRCASEEQ('t','T',"text",    type) ||
+                 STRCASEEQ('p','P',"password",type) ||
+                 STRCASEEQ('c','C',"checkbox",type) ||
+                 STRCASEEQ('r','R',"radio",   type) ||
+                 STRCASEEQ('h','H',"hidden",  type) ||
+                 STRCASEEQ('s','S',"submit",  type) ||
+                 STRCASEEQ('r','R',"reset",   type))) {
+      W_L(" type=\"");
+      W_V(type);
+      W_L("\"");
+    }
   }
-  if (size) {
+  if (size && *size) {
     W_L(" size=\"");
     W_V(size);
-    W_L("\" ");
+    W_L("\"");
   }
-  if (name) {
+  if (name && *name) {
     W_L(" name=\"");
     W_V(name);
-    W_L("\" ");
+    W_L("\"");
   }
-  if (value) {
+  if (value && *value) {
     W_L(" value=\"");
     W_V(value);
-    W_L("\" ");
+    W_L("\"");
   }
-  if (accesskey) {
+  if (accesskey && *accesskey) {
     W_L(" accesskey=\"");
     W_V(accesskey);
-    W_L("\" ");
+    W_L("\"");
   }
-  if (istyle) {
+  if (istyle && (*istyle == '1' || *istyle == '2' || *istyle == '3' || *istyle == '4')) {
     /*------------------------------------------------------------------------*/
     /* CHTML 2.0                                                              */
     /*------------------------------------------------------------------------*/
-    if (STRCASEEQ('p','P',"password", type) && ! jhtml->entryp->pc_flag ) {
+    if (type && STRCASEEQ('p','P',"password", type) && ! jhtml->entryp->pc_flag ) {
       W_L(" mode=\"");
       W_L("numeric");
-      W_L("\" ");
+      W_L("\"");
     }
     else {
-      char *vv = chxj_istyle_to_mode(r,istyle);
+      char *vv = chxj_istyle_to_mode(doc->buf.pool,istyle);
       W_L(" mode=\"");
       W_V(vv);
-      W_L("\" ");
+      W_L("\"");
     }
   }
-  else if (istyle == NULL && type != NULL && STRCASEEQ('p','P',"password",type)) {
+  else if (type && STRCASEEQ('p','P',"password",type)) {
     W_L(" mode=\"");
     W_L("numeric");
-    W_L("\" ");
+    W_L("\"");
   }
   /*--------------------------------------------------------------------------*/
   /* The figure is default for the password.                                  */
   /*--------------------------------------------------------------------------*/
-  if (max_length) {
-    W_L(" maxlength=\"");
-    W_V(max_length);
-    W_L("\"");
+  if (max_length && *max_length) {
+    if (chxj_chk_numeric(max_length) == 0) {
+      W_L(" maxlength=\"");
+      W_V(max_length);
+      W_L("\"");
+    }
   }
 
   if (checked) {
-    W_L(" checked ");
+    W_L(" checked");
   }
-  W_L(" >");
+  W_L(">");
   return jhtml->out;
 }
 
@@ -1574,17 +1599,38 @@ s_jhtml_end_center_tag(void *pdoc, Node *UNUSED(child))
  * @return The conversion result is returned.
  */
 static char *
-s_jhtml_start_li_tag(void *pdoc, Node *UNUSED(node)) 
+s_jhtml_start_li_tag(void *pdoc, Node *node)
 {
   jhtml_t       *jhtml;
   Doc           *doc;
   request_rec   *r;
+  Attr          *attr;
 
   jhtml = GET_JHTML(pdoc);
   doc   = jhtml->doc;
   r     = doc->r;
 
-  W_L("<li>");
+  W_L("<li");
+  /*--------------------------------------------------------------------------*/
+  /* Get Attributes                                                           */
+  /*--------------------------------------------------------------------------*/
+  for (attr = qs_get_attr(doc,node);
+       attr;
+       attr = qs_get_next_attr(doc,attr)) {
+    char *name = qs_get_attr_name(doc,attr);
+    char *value = qs_get_attr_value(doc,attr);
+    if (STRCASEEQ('t','T',"type",name) && value && (*value == '1' || *value == 'a' || *value == 'A')) {
+      W_L(" type=\"");
+      W_V(value);
+      W_L("\"");
+    }
+    else if (STRCASEEQ('v','V',"value", name) && value && *value) {
+      W_L(" value=\"");
+      W_V(value);
+      W_L("\"");
+    }
+  }
+  W_L(">");
   return jhtml->out;
 }
 
@@ -1622,17 +1668,38 @@ s_jhtml_end_li_tag(void *pdoc, Node *UNUSED(child))
  * @return The conversion result is returned.
  */
 static char *
-s_jhtml_start_ol_tag(void *pdoc, Node *UNUSED(node)) 
+s_jhtml_start_ol_tag(void *pdoc, Node *node)
 {
   jhtml_t     *jhtml;
   Doc         *doc;
   request_rec *r;
+  Attr        *attr;
 
   jhtml = GET_JHTML(pdoc);
   doc   = jhtml->doc;
   r     = doc->r;
 
-  W_L("<ol>");
+  W_L("<ol");
+  /*--------------------------------------------------------------------------*/
+  /* Get Attributes                                                           */
+  /*--------------------------------------------------------------------------*/
+  for (attr = qs_get_attr(doc,node);
+       attr;
+       attr = qs_get_next_attr(doc,attr)) {
+    char *name = qs_get_attr_name(doc,attr);
+    char *value = qs_get_attr_value(doc,attr);
+    if (STRCASEEQ('t','T',"type",name) && value && (*value == '1' || *value == 'a' || *value == 'A')) {
+      W_L(" type=\"");
+      W_V(value);
+      W_L("\"");
+    }
+    else if (STRCASEEQ('s','S',"start",name) && value && *value) {
+      W_L(" start=\"");
+      W_V(value);
+      W_L("\"");
+    }
+  }
+  W_L(">");
   return jhtml->out;
 }
 
@@ -1808,11 +1875,13 @@ s_jhtml_start_hr_tag(void *pdoc, Node *node)
       /*----------------------------------------------------------------------*/
       /* CHTML 1.0                                                            */
       /*----------------------------------------------------------------------*/
-      W_L(" align=\"");
-      W_V(value);
-      W_L("\"");
+      if (value && (STRCASEEQ('l','L',"left",value) || STRCASEEQ('r','R',"right",value) || STRCASEEQ('c','C',"center",value))) {
+        W_L(" align=\"");
+        W_V(value);
+        W_L("\"");
+      }
     }
-    else if (STRCASEEQ('s','S',"size",name)) {
+    else if (STRCASEEQ('s','S',"size",name) && value && *value) {
       /*----------------------------------------------------------------------*/
       /* CHTML 1.0                                                            */
       /*----------------------------------------------------------------------*/
@@ -1820,7 +1889,7 @@ s_jhtml_start_hr_tag(void *pdoc, Node *node)
       W_V(value);
       W_L("\"");
     }
-    else if (STRCASEEQ('w','W',"width",name)) {
+    else if (STRCASEEQ('w','W',"width",name) && value && *value) {
       /*----------------------------------------------------------------------*/
       /* CHTML 1.0                                                            */
       /*----------------------------------------------------------------------*/
@@ -1834,11 +1903,13 @@ s_jhtml_start_hr_tag(void *pdoc, Node *node)
       /*----------------------------------------------------------------------*/
       W_L(" noshade");
     }
-    else if (STRCASEEQ('c','C',"color",name)) {
+    else if (STRCASEEQ('c','C',"color",name) && value && *value) {
       /*----------------------------------------------------------------------*/
       /* CHTML 4.0                                                            */
       /*----------------------------------------------------------------------*/
-      /* ignore */
+      W_L(" color=\"");
+      W_V(value);
+      W_L("\"");
     }
   }
   W_L(">");
@@ -1927,11 +1998,17 @@ s_jhtml_start_img_tag(void *pdoc, Node *node)
       /*----------------------------------------------------------------------*/
       /* CHTML 1.0                                                            */
       /*----------------------------------------------------------------------*/
-      W_L(" align=\"");
-      W_V(value);
-      W_L("\"");
+      if (value && (STRCASEEQ('t','T',"top",   value) ||
+                    STRCASEEQ('m','M',"middle",value) ||
+                    STRCASEEQ('b','B',"bottom",value) ||
+                    STRCASEEQ('l','L',"left",  value) ||
+                    STRCASEEQ('r','R',"right", value))) {
+        W_L(" align=\"");
+        W_V(value);
+        W_L("\"");
+      }
     }
-    else if (STRCASEEQ('w','W',"width",name)) {
+    else if (STRCASEEQ('w','W',"width",name) && value && *value) {
       /*----------------------------------------------------------------------*/
       /* CHTML 1.0                                                            */
       /*----------------------------------------------------------------------*/
@@ -1939,7 +2016,7 @@ s_jhtml_start_img_tag(void *pdoc, Node *node)
       W_V(value);
       W_L("\"");
     }
-    else if (STRCASEEQ('h','H',"height",name)) {
+    else if (STRCASEEQ('h','H',"height",name) && value && *value) {
       /*----------------------------------------------------------------------*/
       /* CHTML 1.0                                                            */
       /*----------------------------------------------------------------------*/
@@ -1951,19 +2028,15 @@ s_jhtml_start_img_tag(void *pdoc, Node *node)
       /*----------------------------------------------------------------------*/
       /* CHTML 1.0                                                            */
       /*----------------------------------------------------------------------*/
-      W_L(" hspace=\"");
-      W_V(value);
-      W_L("\"");
+      /* ignore */
     }
     else if (STRCASEEQ('v','V',"vspace",name)) {
       /*----------------------------------------------------------------------*/
       /* CHTML 1.0                                                            */
       /*----------------------------------------------------------------------*/
-      W_L(" vspace=\"");
-      W_V(value);
-      W_L("\"");
+      /* ignore */
     }
-    else if (STRCASEEQ('a','A',"alt",name)) {
+    else if (STRCASEEQ('a','A',"alt",name) && value && *value) {
       /*----------------------------------------------------------------------*/
       /* CHTML 1.0                                                            */
       /*----------------------------------------------------------------------*/
@@ -1971,12 +2044,6 @@ s_jhtml_start_img_tag(void *pdoc, Node *node)
       W_V(value);
       W_L("\"");
     }
-    else if (STRCASEEQ('a','A',"align",name)) {
-      /*----------------------------------------------------------------------*/
-      /* CHTML 4.0                                                            */
-      /*----------------------------------------------------------------------*/
-      /* ignore */
-    }
   }
   W_L(">");
   return jhtml->out;
@@ -2219,26 +2286,26 @@ s_jhtml_end_div_tag(void *pdoc, Node *UNUSED(child))
 
 
 static char *
-chxj_istyle_to_mode(request_rec *r, const char *s)
+chxj_istyle_to_mode(apr_pool_t *p, const char *s)
 {
   char *tmp;
 
   if (s) {
     switch (s[0]) {
-    case '1': return apr_psprintf(r->pool, "hiragana");
-    case '2': return apr_psprintf(r->pool, "hankakukana");
-    case '3': return apr_psprintf(r->pool, "alphabet");
-    case '4': return apr_psprintf(r->pool, "numeric");
+    case '1': return apr_psprintf(p, "hiragana");
+    case '2': return apr_psprintf(p, "hankakukana");
+    case '3': return apr_psprintf(p, "alphabet");
+    case '4': return apr_psprintf(p, "numeric");
     default: 
-      tmp = apr_palloc(r->pool, 1);
+      tmp = apr_palloc(p, 1);
       tmp[0] = '\0';
-      return apr_pstrdup(r->pool, tmp);
+      return apr_pstrdup(p, tmp);
     }
   }
 
-  tmp = apr_palloc(r->pool, 1);
+  tmp = apr_palloc(p, 1);
   tmp[0] = '\0';
-  return apr_pstrdup(r->pool,tmp);
+  return apr_pstrdup(p,tmp);
 }
 
 
@@ -2626,6 +2693,474 @@ s_jhtml_end_dd_tag(void *pdoc, Node *UNUSED(child))
   jhtml_t *jhtml = GET_JHTML(pdoc);
   return jhtml->out;
 }
+
+
+/**
+ * It is a handler who processes the H1 tag.
+ *
+ * @param pdoc  [i/o] The pointer to the JHTML structure at the output
+ *                     destination is specified.
+ * @param node   [i]   The H1 tag node is specified.
+ * @return The conversion result is returned.
+ */
+static char *
+s_jhtml_start_h1_tag(void *pdoc, Node *node)
+{
+  jhtml_t       *jhtml;
+  Doc           *doc;
+  request_rec   *r;
+  Attr          *attr;
+  char          *align = NULL;
+
+  jhtml   = GET_JHTML(pdoc);
+  doc     = jhtml->doc;
+  r       = doc->r;
+
+  for (attr = qs_get_attr(doc,node);
+       attr;
+       attr = qs_get_next_attr(doc,attr)) {
+    char* name;
+    char* value;
+    name  = qs_get_attr_name(doc,attr);
+    value = qs_get_attr_value(doc,attr);
+    if (STRCASEEQ('a','A',"align", name)) {
+      if (value && (STRCASEEQ('l','L',"left",value) || STRCASEEQ('r','R',"right",value) || STRCASEEQ('c','C',"center",value))) {
+        jhtml->h1_align_flag++;
+        align = apr_pstrdup(doc->buf.pool, value);
+        break;
+      }
+    }
+  }
+  if (align) {
+    W_L("<div align=\"");
+    W_V(align);
+    W_L("\">");
+  }
+  return jhtml->out;
+}
+
+
+/**
+ * It is a handler who processes the H1 tag.
+ *
+ * @param pdoc  [i/o] The pointer to the JHTML structure at the output
+ *                     destination is specified.
+ * @param node   [i]   The H1 tag node is specified.
+ * @return The conversion result is returned.
+ */
+static char *
+s_jhtml_end_h1_tag(void *pdoc, Node *UNUSED(child)) 
+{
+  jhtml_t*    jhtml;
+  Doc*          doc;
+  request_rec*  r;
+
+  jhtml = GET_JHTML(pdoc);
+  doc     = jhtml->doc;
+  r       = doc->r;
+  
+  if (jhtml->h1_align_flag) {
+    jhtml->h1_align_flag--;
+    W_L("</div>");
+  }
+  return jhtml->out;
+}
+
+
+/**
+ * It is a handler who processes the H2 tag.
+ *
+ * @param pdoc  [i/o] The pointer to the JHTML structure at the output
+ *                     destination is specified.
+ * @param node   [i]   The H1 tag node is specified.
+ * @return The conversion result is returned.
+ */
+static char *
+s_jhtml_start_h2_tag(void *pdoc, Node *node)
+{
+  jhtml_t       *jhtml;
+  Doc           *doc;
+  request_rec   *r;
+  Attr          *attr;
+  char          *align = NULL;
+
+  jhtml   = GET_JHTML(pdoc);
+  doc     = jhtml->doc;
+  r       = doc->r;
+
+  for (attr = qs_get_attr(doc,node);
+       attr;
+       attr = qs_get_next_attr(doc,attr)) {
+    char* name;
+    char* value;
+    name  = qs_get_attr_name(doc,attr);
+    value = qs_get_attr_value(doc,attr);
+    if (STRCASEEQ('a','A',"align", name)) {
+      if (value && (STRCASEEQ('l','L',"left",value) || STRCASEEQ('r','R',"right",value) || STRCASEEQ('c','C',"center",value))) {
+        jhtml->h2_align_flag++;
+        align = apr_pstrdup(doc->buf.pool, value);
+        break;
+      }
+    }
+  }
+  if (align) {
+    W_L("<div align=\"");
+    W_V(align);
+    W_L("\">");
+  }
+  return jhtml->out;
+}
+
+
+/**
+ * It is a handler who processes the H2 tag.
+ *
+ * @param pdoc  [i/o] The pointer to the JHTML structure at the output
+ *                     destination is specified.
+ * @param node   [i]   The H1 tag node is specified.
+ * @return The conversion result is returned.
+ */
+static char *
+s_jhtml_end_h2_tag(void *pdoc, Node *UNUSED(child)) 
+{
+  jhtml_t*    jhtml;
+  Doc*          doc;
+  request_rec*  r;
+
+  jhtml = GET_JHTML(pdoc);
+  doc     = jhtml->doc;
+  r       = doc->r;
+  
+  if (jhtml->h2_align_flag) {
+    jhtml->h2_align_flag--;
+    W_L("</div>");
+  }
+  return jhtml->out;
+}
+
+
+/**
+ * It is a handler who processes the H3 tag.
+ *
+ * @param pdoc  [i/o] The pointer to the JHTML structure at the output
+ *                     destination is specified.
+ * @param node   [i]   The H1 tag node is specified.
+ * @return The conversion result is returned.
+ */
+static char *
+s_jhtml_start_h3_tag(void *pdoc, Node *node)
+{
+  jhtml_t       *jhtml;
+  Doc           *doc;
+  request_rec   *r;
+  Attr          *attr;
+  char          *align = NULL;
+
+  jhtml   = GET_JHTML(pdoc);
+  doc     = jhtml->doc;
+  r       = doc->r;
+
+  for (attr = qs_get_attr(doc,node);
+       attr;
+       attr = qs_get_next_attr(doc,attr)) {
+    char* name;
+    char* value;
+    name  = qs_get_attr_name(doc,attr);
+    value = qs_get_attr_value(doc,attr);
+    if (STRCASEEQ('a','A',"align", name)) {
+      if (value && (STRCASEEQ('l','L',"left",value) || STRCASEEQ('r','R',"right",value) || STRCASEEQ('c','C',"center",value))) {
+        jhtml->h3_align_flag++;
+        align = apr_pstrdup(doc->buf.pool, value);
+        break;
+      }
+    }
+  }
+  if (align) {
+    W_L("<div align=\"");
+    W_V(align);
+    W_L("\">");
+  }
+  return jhtml->out;
+}
+
+
+/**
+ * It is a handler who processes the H3 tag.
+ *
+ * @param pdoc  [i/o] The pointer to the JHTML structure at the output
+ *                     destination is specified.
+ * @param node   [i]   The H1 tag node is specified.
+ * @return The conversion result is returned.
+ */
+static char *
+s_jhtml_end_h3_tag(void *pdoc, Node *UNUSED(child)) 
+{
+  jhtml_t*    jhtml;
+  Doc*          doc;
+  request_rec*  r;
+
+  jhtml = GET_JHTML(pdoc);
+  doc     = jhtml->doc;
+  r       = doc->r;
+  
+  if (jhtml->h3_align_flag) {
+    jhtml->h3_align_flag--;
+    W_L("</div>");
+  }
+  return jhtml->out;
+}
+
+
+/**
+ * It is a handler who processes the H4 tag.
+ *
+ * @param pdoc  [i/o] The pointer to the JHTML structure at the output
+ *                     destination is specified.
+ * @param node   [i]   The H1 tag node is specified.
+ * @return The conversion result is returned.
+ */
+static char *
+s_jhtml_start_h4_tag(void *pdoc, Node *node)
+{
+  jhtml_t       *jhtml;
+  Doc           *doc;
+  request_rec   *r;
+  Attr          *attr;
+  char          *align = NULL;
+
+  jhtml   = GET_JHTML(pdoc);
+  doc     = jhtml->doc;
+  r       = doc->r;
+
+  for (attr = qs_get_attr(doc,node);
+       attr;
+       attr = qs_get_next_attr(doc,attr)) {
+    char* name;
+    char* value;
+    name  = qs_get_attr_name(doc,attr);
+    value = qs_get_attr_value(doc,attr);
+    if (STRCASEEQ('a','A',"align", name)) {
+      if (value && (STRCASEEQ('l','L',"left",value) || STRCASEEQ('r','R',"right",value) || STRCASEEQ('c','C',"center",value))) {
+        jhtml->h4_align_flag++;
+        align = apr_pstrdup(doc->buf.pool, value);
+        break;
+      }
+    }
+  }
+  if (align) {
+    W_L("<div align=\"");
+    W_V(align);
+    W_L("\">");
+  }
+  return jhtml->out;
+}
+
+
+/**
+ * It is a handler who processes the H4 tag.
+ *
+ * @param pdoc  [i/o] The pointer to the JHTML structure at the output
+ *                     destination is specified.
+ * @param node   [i]   The H1 tag node is specified.
+ * @return The conversion result is returned.
+ */
+static char *
+s_jhtml_end_h4_tag(void *pdoc, Node *UNUSED(child)) 
+{
+  jhtml_t*    jhtml;
+  Doc*          doc;
+  request_rec*  r;
+
+  jhtml = GET_JHTML(pdoc);
+  doc     = jhtml->doc;
+  r       = doc->r;
+  
+  if (jhtml->h4_align_flag) {
+    jhtml->h4_align_flag--;
+    W_L("</div>");
+  }
+  return jhtml->out;
+}
+
+
+/**
+ * It is a handler who processes the H5 tag.
+ *
+ * @param pdoc  [i/o] The pointer to the JHTML structure at the output
+ *                     destination is specified.
+ * @param node   [i]   The H1 tag node is specified.
+ * @return The conversion result is returned.
+ */
+static char *
+s_jhtml_start_h5_tag(void *pdoc, Node *node)
+{
+  jhtml_t       *jhtml;
+  Doc           *doc;
+  request_rec   *r;
+  Attr          *attr;
+  char          *align = NULL;
+
+  jhtml   = GET_JHTML(pdoc);
+  doc     = jhtml->doc;
+  r       = doc->r;
+
+  for (attr = qs_get_attr(doc,node);
+       attr;
+       attr = qs_get_next_attr(doc,attr)) {
+    char* name;
+    char* value;
+    name  = qs_get_attr_name(doc,attr);
+    value = qs_get_attr_value(doc,attr);
+    if (STRCASEEQ('a','A',"align", name)) {
+      if (value && (STRCASEEQ('l','L',"left",value) || STRCASEEQ('r','R',"right",value) || STRCASEEQ('c','C',"center",value))) {
+        jhtml->h5_align_flag++;
+        align = apr_pstrdup(doc->buf.pool, value);
+        break;
+      }
+    }
+  }
+  if (align) {
+    W_L("<div align=\"");
+    W_V(align);
+    W_L("\">");
+  }
+  return jhtml->out;
+}
+
+
+/**
+ * It is a handler who processes the H5 tag.
+ *
+ * @param pdoc  [i/o] The pointer to the JHTML structure at the output
+ *                     destination is specified.
+ * @param node   [i]   The H1 tag node is specified.
+ * @return The conversion result is returned.
+ */
+static char *
+s_jhtml_end_h5_tag(void *pdoc, Node *UNUSED(child)) 
+{
+  jhtml_t*    jhtml;
+  Doc*          doc;
+  request_rec*  r;
+
+  jhtml = GET_JHTML(pdoc);
+  doc     = jhtml->doc;
+  r       = doc->r;
+  
+  if (jhtml->h5_align_flag) {
+    jhtml->h5_align_flag--;
+    W_L("</div>");
+  }
+  return jhtml->out;
+}
+
+
+/**
+ * It is a handler who processes the H6 tag.
+ *
+ * @param pdoc  [i/o] The pointer to the JHTML structure at the output
+ *                     destination is specified.
+ * @param node   [i]   The H1 tag node is specified.
+ * @return The conversion result is returned.
+ */
+static char *
+s_jhtml_start_h6_tag(void *pdoc, Node *node)
+{
+  jhtml_t       *jhtml;
+  Doc           *doc;
+  request_rec   *r;
+  Attr          *attr;
+  char          *align = NULL;
+
+  jhtml   = GET_JHTML(pdoc);
+  doc     = jhtml->doc;
+  r       = doc->r;
+
+  for (attr = qs_get_attr(doc,node);
+       attr;
+       attr = qs_get_next_attr(doc,attr)) {
+    char* name;
+    char* value;
+    name  = qs_get_attr_name(doc,attr);
+    value = qs_get_attr_value(doc,attr);
+    if (STRCASEEQ('a','A',"align", name)) {
+      if (value && (STRCASEEQ('l','L',"left",value) || STRCASEEQ('r','R',"right",value) || STRCASEEQ('c','C',"center",value))) {
+        jhtml->h6_align_flag++;
+        align = apr_pstrdup(doc->buf.pool, value);
+        break;
+      }
+    }
+  }
+  if (align) {
+    W_L("<div align=\"");
+    W_V(align);
+    W_L("\">");
+  }
+  return jhtml->out;
+}
+
+
+/**
+ * It is a handler who processes the H6 tag.
+ *
+ * @param pdoc  [i/o] The pointer to the JHTML structure at the output
+ *                     destination is specified.
+ * @param node   [i]   The H1 tag node is specified.
+ * @return The conversion result is returned.
+ */
+static char *
+s_jhtml_end_h6_tag(void *pdoc, Node *UNUSED(child)) 
+{
+  jhtml_t*    jhtml;
+  Doc*          doc;
+  request_rec*  r;
+
+  jhtml = GET_JHTML(pdoc);
+  doc     = jhtml->doc;
+  r       = doc->r;
+  
+  if (jhtml->h6_align_flag) {
+    jhtml->h6_align_flag--;
+    W_L("</div>");
+  }
+  return jhtml->out;
+}
+
+
+/**
+ * It is a handler who processes the MENU tag.
+ *
+ * @param pdoc  [i/o] The pointer to the JHTML structure at the output
+ *                     destination is specified.
+ * @param node   [i]   The MENU tag node is specified.
+ * @return The conversion result is returned.
+ */
+static char *
+s_jhtml_start_menu_tag(void *pdoc, Node *UNUSED(child))
+{
+  jhtml_t *jhtml = GET_JHTML(pdoc);
+  Doc     *doc = jhtml->doc;
+  W_L("<menu>");
+  return jhtml->out;
+}
+
+
+/**
+ * It is a handler who processes the MENU tag.
+ *
+ * @param pdoc  [i/o] The pointer to the JHTML structure at the output
+ *                     destination is specified.
+ * @param node   [i]   The MENU tag node is specified.
+ * @return The conversion result is returned.
+ */
+static char *
+s_jhtml_end_menu_tag(void *pdoc, Node *UNUSED(child))
+{
+  jhtml_t *jhtml = GET_JHTML(pdoc);
+  Doc     *doc = jhtml->doc;
+  W_L("</menu>");
+  return jhtml->out;
+}
 /*
  * vim:ts=2 et
  */