OSDN Git Service

Merge branch 'branch_0.12.0'
[modchxj/mod_chxj.git] / src / chxj_chtml40.c
1 /*
2  * Copyright (C) 2005-2009 Atsushi Konno All rights reserved.
3  * Copyright (C) 2005 QSDN,Inc. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #include <apr_time.h>
18 #include "chxj_chtml40.h"
19 #include "chxj_hdml.h"
20 #include "chxj_str_util.h"
21 #include "chxj_dump.h"
22 #include "chxj_img_conv.h"
23 #include "chxj_qr_code.h"
24 #include "chxj_encoding.h"
25 #include "chxj_header_inf.h"
26
27 #define GET_CHTML40(X) ((chtml40_t *)(X))
28 #undef W_L
29 #undef W_V
30 #define W_L(X)          do { chtml40->out = BUFFERED_WRITE_LITERAL(chtml40->out, &doc->buf, (X)); } while(0)
31 #define W_V(X)          do { chtml40->out = (X) ? BUFFERED_WRITE_VALUE(chtml40->out, &doc->buf, (X))  \
32                                                 : BUFFERED_WRITE_LITERAL(chtml40->out, &doc->buf, ""); } while(0)
33 #undef W_NLCODE
34 #define W_NLCODE()     do { char *nlcode = TO_NLCODE(chtml40->conf); W_V(nlcode); } while (0)
35
36 #define CHTML40_GET_CSS_COLOR_AND_LIST_STYLE_TYPE() \
37   if (IS_CSS_ON(chtml40->entryp)) { \
38     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style); \
39     if (style) { \
40       css_property_t *color_prop           = chxj_css_get_property_value(doc, style, "color"); \
41       css_property_t *list_style_type_prop = chxj_css_get_property_value(doc, style, "list-style-type"); \
42       css_property_t *cur; \
43       for (cur = color_prop->next; cur != color_prop; cur = cur->next) { \
44         if (cur->value && *cur->value) { \
45           attr_color = apr_pstrdup(doc->pool, cur->value); \
46         } \
47       } \
48       for (cur = list_style_type_prop->next; cur != list_style_type_prop; cur = cur->next) { \
49         if (cur->value && *cur->value) { \
50           attr_type = apr_pstrdup(doc->pool, cur->value); \
51         } \
52       } \
53     } \
54   }
55
56 static char *s_chtml40_start_html_tag     (void *pdoc, Node *node);
57 static char *s_chtml40_end_html_tag       (void *pdoc, Node *node);
58 static char *s_chtml40_start_meta_tag     (void *pdoc, Node *node);
59 static char *s_chtml40_end_meta_tag       (void *pdoc, Node *node);
60 static char *s_chtml40_start_textarea_tag (void *pdoc, Node *node);
61 static char *s_chtml40_end_textarea_tag   (void *pdoc, Node *node);
62 static char *s_chtml40_start_p_tag        (void *pdoc, Node *node);
63 static char *s_chtml40_end_p_tag          (void *pdoc, Node *node);
64 static char *s_chtml40_start_pre_tag      (void *pdoc, Node *node);
65 static char *s_chtml40_end_pre_tag        (void *pdoc, Node *node);
66 static char *s_chtml40_start_h1_tag       (void *pdoc, Node *node);
67 static char *s_chtml40_end_h1_tag         (void *pdoc, Node *node);
68 static char *s_chtml40_start_h2_tag       (void *pdoc, Node *node);
69 static char *s_chtml40_end_h2_tag         (void *pdoc, Node *node);
70 static char *s_chtml40_start_h3_tag       (void *pdoc, Node *node);
71 static char *s_chtml40_end_h3_tag         (void *pdoc, Node *node);
72 static char *s_chtml40_start_h4_tag       (void *pdoc, Node *node);
73 static char *s_chtml40_end_h4_tag         (void *pdoc, Node *node);
74 static char *s_chtml40_start_h5_tag       (void *pdoc, Node *node);
75 static char *s_chtml40_end_h5_tag         (void *pdoc, Node *node);
76 static char *s_chtml40_start_h6_tag       (void *pdoc, Node *node);
77 static char *s_chtml40_end_h6_tag         (void *pdoc, Node *node);
78 static char *s_chtml40_start_ul_tag       (void *pdoc, Node *node);
79 static char *s_chtml40_end_ul_tag         (void *pdoc, Node *node);
80 static char *s_chtml40_start_ol_tag       (void *pdoc, Node *node);
81 static char *s_chtml40_end_ol_tag         (void *pdoc, Node *node);
82 static char *s_chtml40_start_li_tag       (void *pdoc, Node *node);
83 static char *s_chtml40_end_li_tag         (void *pdoc, Node *node);
84 static char *s_chtml40_start_head_tag     (void *pdoc, Node *node);
85 static char *s_chtml40_end_head_tag       (void *pdoc, Node *node);
86 static char *s_chtml40_start_title_tag    (void *pdoc, Node *node);
87 static char *s_chtml40_end_title_tag      (void *pdoc, Node *node);
88 static char *s_chtml40_start_base_tag     (void *pdoc, Node *node);
89 static char *s_chtml40_end_base_tag       (void *pdoc, Node *node);
90 static char *s_chtml40_start_body_tag     (void *pdoc, Node *node);
91 static char *s_chtml40_end_body_tag       (void *pdoc, Node *node);
92 static char *s_chtml40_start_a_tag        (void *pdoc, Node *node);
93 static char *s_chtml40_end_a_tag          (void *pdoc, Node *node);
94 static char *s_chtml40_start_br_tag       (void *pdoc, Node *node);
95 static char *s_chtml40_end_br_tag         (void *pdoc, Node *node);
96 static char *s_chtml40_start_tr_tag       (void *pdoc, Node *node);
97 static char *s_chtml40_end_tr_tag         (void *pdoc, Node *node);
98 static char *s_chtml40_start_font_tag     (void *pdoc, Node *node);
99 static char *s_chtml40_end_font_tag       (void *pdoc, Node *node);
100 static char *s_chtml40_start_form_tag     (void *pdoc, Node *node);
101 static char *s_chtml40_end_form_tag       (void *pdoc, Node *node);
102 static char *s_chtml40_start_input_tag    (void *pdoc, Node *node);
103 static char *s_chtml40_end_input_tag      (void *pdoc, Node *node);
104 static char *s_chtml40_start_center_tag   (void *pdoc, Node *node);
105 static char *s_chtml40_end_center_tag     (void *pdoc, Node *node);
106 static char *s_chtml40_start_hr_tag       (void *pdoc, Node *node);
107 static char *s_chtml40_end_hr_tag         (void *pdoc, Node *node);
108 static char *s_chtml40_start_img_tag      (void *pdoc, Node *node);
109 static char *s_chtml40_end_img_tag        (void *pdoc, Node *node);
110 static char *s_chtml40_start_select_tag   (void *pdoc, Node *node);
111 static char *s_chtml40_end_select_tag     (void *pdoc, Node *node);
112 static char *s_chtml40_start_option_tag   (void *pdoc, Node *node);
113 static char *s_chtml40_end_option_tag     (void *pdoc, Node *node);
114 static char *s_chtml40_start_div_tag      (void *pdoc, Node *node);
115 static char *s_chtml40_end_div_tag        (void *pdoc, Node *node);
116 static char *s_chtml40_chxjif_tag         (void *pdoc, Node *node); 
117 static char *s_chtml40_text_tag           (void *pdoc, Node *node);
118 static char *s_chtml40_start_blockquote_tag (void *pdoc, Node *node);
119 static char *s_chtml40_end_blockquote_tag  (void *pdoc, Node *node);
120 static char *s_chtml40_start_dir_tag      (void *pdoc, Node *node);
121 static char *s_chtml40_end_dir_tag        (void *pdoc, Node *node);
122 static char *s_chtml40_start_dl_tag       (void *pdoc, Node *node);
123 static char *s_chtml40_end_dl_tag         (void *pdoc, Node *node);
124 static char *s_chtml40_start_dt_tag       (void *pdoc, Node *node);
125 static char *s_chtml40_end_dt_tag         (void *pdoc, Node *node);
126 static char *s_chtml40_start_dd_tag       (void *pdoc, Node *node);
127 static char *s_chtml40_end_dd_tag         (void *pdoc, Node *node);
128 static char *s_chtml40_start_marquee_tag  (void *pdoc, Node *node);
129 static char *s_chtml40_end_marquee_tag    (void *pdoc, Node *node);
130 static char *s_chtml40_start_blink_tag    (void *pdoc, Node *node);
131 static char *s_chtml40_end_blink_tag      (void *pdoc, Node *node);
132 static char *s_chtml40_start_menu_tag     (void *pdoc, Node *node);
133 static char *s_chtml40_end_menu_tag       (void *pdoc, Node *node);
134 static char *s_chtml40_start_plaintext_tag       (void *pdoc, Node *node);
135 static char *s_chtml40_start_plaintext_tag_inner (void *pdoc, Node *node);
136 static char *s_chtml40_end_plaintext_tag         (void *pdoc, Node *node);
137 static char *s_chtml40_newline_mark       (void *pdoc, Node *node);
138 static char *s_chtml40_link_tag           (void *pdoc, Node *node);
139 static char *s_chtml40_start_span_tag     (void *pdoc, Node *node);
140 static char *s_chtml40_end_span_tag       (void *pdoc, Node *node);
141 static char *s_chtml40_style_tag     (void *pdoc, Node *node);
142
143 static void  s_init_chtml40(chtml40_t *chtml, Doc *doc, request_rec *r, device_table *spec);
144
145 static int   s_chtml40_search_emoji(chtml40_t *chtml, char *txt, char **rslt);
146 static css_prop_list_t *s_chtml40_push_and_get_now_style(void *pdoc, Node *node, const char *style_attr_value);
147 static css_prop_list_t *s_chtml40_nopush_and_get_now_style(void *pdoc, Node *node, const char *style_attr_value);
148
149
150 tag_handler chtml40_handler[] = {
151   /* tagHTML */
152   {
153     s_chtml40_start_html_tag,
154     s_chtml40_end_html_tag,
155   },
156   /* tagMETA */
157   {
158     s_chtml40_start_meta_tag,
159     s_chtml40_end_meta_tag,
160   },
161   /* tagTEXTAREA */
162   {
163     s_chtml40_start_textarea_tag,
164     s_chtml40_end_textarea_tag,
165   },
166   /* tagP */
167   {
168     s_chtml40_start_p_tag,
169     s_chtml40_end_p_tag,
170   },
171   /* tagPRE */
172   {
173     s_chtml40_start_pre_tag,
174     s_chtml40_end_pre_tag,
175   },
176   /* tagUL */
177   {
178     s_chtml40_start_ul_tag,
179     s_chtml40_end_ul_tag,
180   },
181   /* tagLI */
182   {
183     s_chtml40_start_li_tag,
184     s_chtml40_end_li_tag,
185   },
186   /* tagOL */
187   {
188     s_chtml40_start_ol_tag,
189     s_chtml40_end_ol_tag,
190   },
191   /* tagH1 */
192   {
193     s_chtml40_start_h1_tag,
194     s_chtml40_end_h1_tag,
195   },
196   /* tagH2 */
197   {
198     s_chtml40_start_h2_tag,
199     s_chtml40_end_h2_tag,
200   },
201   /* tagH3 */
202   {
203     s_chtml40_start_h3_tag,
204     s_chtml40_end_h3_tag,
205   },
206   /* tagH4 */
207   {
208     s_chtml40_start_h4_tag,
209     s_chtml40_end_h4_tag,
210   },
211   /* tagH5 */
212   {
213     s_chtml40_start_h5_tag,
214     s_chtml40_end_h5_tag,
215   },
216   /* tagH6 */
217   {
218     s_chtml40_start_h6_tag,
219     s_chtml40_end_h6_tag,
220   },
221   /* tagHEAD */
222   {
223     s_chtml40_start_head_tag,
224     s_chtml40_end_head_tag,
225   },
226   /* tagTITLE */
227   {
228     s_chtml40_start_title_tag,
229     s_chtml40_end_title_tag,
230   },
231   /* tagBASE */
232   {
233     s_chtml40_start_base_tag,
234     s_chtml40_end_base_tag,
235   },
236   /* tagBODY */
237   {
238     s_chtml40_start_body_tag,
239     s_chtml40_end_body_tag,
240   },
241   /* tagA */
242   {
243     s_chtml40_start_a_tag,
244     s_chtml40_end_a_tag,
245   },
246   /* tagBR */
247   {
248     s_chtml40_start_br_tag,
249     s_chtml40_end_br_tag,
250   },
251   /* tagTABLE */
252   {
253     NULL,
254     NULL,
255   },
256   /* tagTR */
257   {
258     s_chtml40_start_tr_tag,
259     s_chtml40_end_tr_tag,
260   },
261   /* tagTD */
262   {
263     NULL,
264     NULL,
265   },
266   /* tagTBODY */
267   {
268     NULL,
269     NULL,
270   },
271   /* tagFONT */
272   {
273     s_chtml40_start_font_tag,
274     s_chtml40_end_font_tag,
275   },
276   /* tagFORM */
277   {
278     s_chtml40_start_form_tag,
279     s_chtml40_end_form_tag,
280   },
281   /* tagINPUT */
282   {
283     s_chtml40_start_input_tag,
284     s_chtml40_end_input_tag,
285   },
286   /* tagCENTER */
287   {
288     s_chtml40_start_center_tag,
289     s_chtml40_end_center_tag,
290   },
291   /* tagHR */
292   {
293     s_chtml40_start_hr_tag,
294     s_chtml40_end_hr_tag,
295   },
296   /* tagIMG */
297   {
298     s_chtml40_start_img_tag,
299     s_chtml40_end_img_tag,
300   },
301   /* tagSELECT */
302   {
303     s_chtml40_start_select_tag,
304     s_chtml40_end_select_tag,
305   },
306   /* tagOPTION */
307   {
308     s_chtml40_start_option_tag,
309     s_chtml40_end_option_tag,
310   },
311   /* tagDIV */
312   {
313     s_chtml40_start_div_tag,
314     s_chtml40_end_div_tag,
315   },
316   /* tagCHXJIF */
317   {
318     s_chtml40_chxjif_tag,
319     NULL,
320   },
321   /* tagNOBR */
322   {
323     NULL,
324     NULL,
325   },
326   /* tagSMALL */
327   {
328     NULL,
329     NULL,
330   },
331   /* tagSTYLE */
332   {
333     s_chtml40_style_tag,
334     NULL,
335   },
336   /* tagSPAN */
337   {
338     s_chtml40_start_span_tag,
339     s_chtml40_end_span_tag,
340   },
341   /* tagTEXT */
342   {
343     s_chtml40_text_tag,
344     NULL,
345   },
346   /* tagTH */
347   {
348     NULL,
349     NULL,
350   },
351   /* tagB */
352   {
353     NULL,
354     NULL,
355   },
356   /* tagFIELDSET */
357   {
358     NULL,
359     NULL,
360   },
361   /* tagDT */
362   {
363     s_chtml40_start_dt_tag,
364     s_chtml40_end_dt_tag,
365   },
366   /* tagLEGEND */
367   {
368     NULL,
369     NULL,
370   },
371   /* tagLABEL */
372   {
373     NULL,
374     NULL,
375   },
376   /* tagBLOCKQUOTE */
377   {
378     s_chtml40_start_blockquote_tag,
379     s_chtml40_end_blockquote_tag,
380   },
381   /* tagDIR */
382   {
383     s_chtml40_start_dir_tag,
384     s_chtml40_end_dir_tag,
385   },
386   /* tagDL */
387   {
388     s_chtml40_start_dl_tag,
389     s_chtml40_end_dl_tag,
390   },
391   /* tagDD */
392   {
393     s_chtml40_start_dd_tag,
394     s_chtml40_end_dd_tag,
395   },
396   /* tagMENU */
397   {
398     s_chtml40_start_menu_tag,
399     s_chtml40_end_menu_tag,
400   },
401   /* tagPLAINTEXT */
402   {
403     s_chtml40_start_plaintext_tag,
404     s_chtml40_end_plaintext_tag,
405   },
406   /* tagBLINK */
407   {
408     s_chtml40_start_blink_tag,
409     s_chtml40_end_blink_tag,
410   },
411   /* tagMARQUEE */
412   {
413     s_chtml40_start_marquee_tag,
414     s_chtml40_end_marquee_tag,
415   },
416   /* tagLINK */
417   {
418     s_chtml40_link_tag,
419     NULL,
420   },
421   /* tagNLMARK */
422   {
423     s_chtml40_newline_mark,
424     NULL,
425   },
426 };
427
428
429 /**
430  * converts from CHTML5.0 to CHTML3.0.
431  *
432  * @param r     [i]   Requet_rec is appointed.
433  * @param spec  [i]   The result of the device specification processing which 
434  *                    was done in advance is appointed.
435  * @param src   [i]   The character string before the converting is appointed.
436  * @return The character string after the converting is returned.
437  */
438 char*
439 chxj_convert_chtml40(
440   request_rec         *r,
441   device_table        *spec,
442   const char          *src,
443   apr_size_t          srclen,
444   apr_size_t          *dstlen,
445   chxjconvrule_entry  *entryp,
446   cookie_t            *cookie
447 )
448 {
449   char      *dst = NULL;
450   char      *ss;
451   chtml40_t chtml40;
452   Doc       doc;
453
454   DBG(r, "start chxj_convert_chtml40()");
455
456   /*--------------------------------------------------------------------------*/
457   /* If qrcode xml                                                            */
458   /*--------------------------------------------------------------------------*/
459   *dstlen = srclen;
460   dst = chxj_qr_code_blob_handler(r, src, (size_t*)dstlen);
461   if (dst) {
462     DBG(r,"i found qrcode xml");
463     DBG(r, "end chxj_convert_chtml40()");
464     return dst;
465   }
466   DBG(r,"not found qrcode xml");
467
468   /*--------------------------------------------------------------------------*/
469   /* The CHTML structure is initialized.                                      */
470   /*--------------------------------------------------------------------------*/
471   s_init_chtml40(&chtml40, &doc, r, spec);
472
473   chtml40.entryp = entryp;
474   chtml40.cookie = cookie;
475
476   chxj_set_content_type(r, chxj_header_inf_set_content_type(r, "text/html; charset=Windows-31J"));
477
478   /*--------------------------------------------------------------------------*/
479   /* The character string of the input is analyzed.                           */
480   /*--------------------------------------------------------------------------*/
481   qs_init_malloc(&doc);
482   qs_init_root_node(&doc);
483
484   ss = apr_pcalloc(r->pool, srclen + 1);
485   memset(ss, 0, srclen + 1);
486   memcpy(ss, src, srclen);
487
488 #ifdef DUMP_LOG
489   chxj_dump_out("[src] CHTML -> CHTML4.0", ss, srclen);
490 #endif
491   if (IS_CSS_ON(chtml40.entryp)) {
492     /* current property list */
493     chtml40.css_prop_stack = chxj_new_prop_list_stack(&doc);
494   }
495
496   chxj_buffered_write_init(r->pool, &doc.buf);
497
498   qs_parse_string(&doc,ss, strlen(ss));
499
500   /*--------------------------------------------------------------------------*/
501   /* It converts it from CHTML to CHTML.                                      */
502   /*--------------------------------------------------------------------------*/
503   chxj_node_convert(spec,r,(void*)&chtml40, &doc, qs_get_root(&doc), 0);
504   chtml40.out = chxj_buffered_write_flush(chtml40.out, &doc.buf);
505   dst = apr_pstrdup(r->pool, chtml40.out);
506   chxj_buffered_write_terminate(&doc.buf);
507
508   qs_all_free(&doc,QX_LOGMARK);
509
510   if (dst == NULL) {
511     dst = apr_pstrdup(r->pool,ss);
512   }
513   if (strlen(dst) == 0) {
514     dst = apr_psprintf(r->pool, "\n");
515   }
516
517   *dstlen = strlen(dst);
518
519 #ifdef DUMP_LOG
520   chxj_dump_out("[src] CHTML -> CHTML4.0", dst, *dstlen);
521 #endif
522
523   DBG(r, "end chxj_convert_chtml40()");
524   return dst;
525 }
526
527
528 /**
529  * The CHTML structure is initialized.
530  *
531  * @param chtml40 [i/o] The pointer to the HDML structure that wants to be
532  *                   initialized is specified.
533  * @param doc   [i]   The Doc structure that should be set to the initialized
534  *                   HDML structure is specified.
535  * @param r     [i]   To use POOL, the pointer to request_rec is specified.
536  * @param spec  [i]   The pointer to the device_table
537  */
538 static void
539 s_init_chtml40(chtml40_t *chtml40, Doc *doc, request_rec *r, device_table *spec)
540 {
541   memset(doc,     0, sizeof(Doc));
542   memset(chtml40, 0, sizeof(chtml40_t));
543
544   doc->r        = r;
545   chtml40->doc  = doc;
546   chtml40->spec = spec;
547   chtml40->out  = qs_alloc_zero_byte_string(r->pool);
548   chtml40->conf = chxj_get_module_config(r->per_dir_config, &chxj_module);
549   chtml40->doc->parse_mode = PARSE_MODE_CHTML;
550 }
551
552
553 /**
554  * Corresponding EMOJI to a current character-code is retrieved. 
555  * The substitution character string is stored in the rslt pointer if agreeing.
556  *
557  * @param chtml40   [i]   The pointer to the CHTML structure is specified. 
558  * @param txt     [i]   The character string to want to examine whether it is 
559  *                      EMOJI is specified. 
560  * @param rslt    [o]   The pointer to the pointer that stores the result is 
561  *                      specified. 
562  * @return When corresponding EMOJI exists, it returns it excluding 0. 
563  */
564 static int
565 s_chtml40_search_emoji(chtml40_t *chtml40, char *txt, char **rslt)
566 {
567   emoji_t       *ee;
568   request_rec   *r;
569   device_table  *spec;
570   int           len;
571
572   spec = chtml40->spec;
573
574   len = strlen(txt);
575   r   = chtml40->doc->r;
576
577   if (!spec) {
578     DBG(r,"spec is NULL");
579   }
580
581   for (ee = chtml40->conf->emoji;
582        ee;
583        ee = ee->next) {
584     if (ee->imode == NULL) {
585       DBG(r, "emoji->imode is NULL");
586       continue;
587     }
588
589     if (ee->imode->string != NULL
590     &&  strlen(ee->imode->string) > 0
591     &&  strncasecmp(ee->imode->string, txt, strlen(ee->imode->string)) == 0) {
592
593       if (spec == NULL || spec->emoji_type == NULL) {
594         *rslt = apr_palloc(r->pool, 3);
595         (*rslt)[0] = ee->imode->hex1byte & 0xff;
596         (*rslt)[1] = ee->imode->hex2byte & 0xff;
597         (*rslt)[2] = 0;
598         return strlen(ee->imode->string);
599       }
600
601       return 0;
602     }
603   }
604
605   return 0;
606 }
607
608
609 char *
610 chxj_chtml40_emoji_only_converter(request_rec *r, device_table *spec, const char *src, apr_size_t len)
611 {
612   apr_size_t ii;
613   Doc __doc;
614   Doc *doc;
615   chtml40_t __chtml40;
616   chtml40_t *chtml40;
617   char one_byte[2];
618   char two_byte[3];
619   apr_pool_t *pool;
620
621   chtml40 = &__chtml40;
622   doc     = &__doc;
623
624   DBG(r, "REQ[%X] start chxj_chtml40_emoji_eonly_converter()", (apr_size_t)(unsigned int)r);
625   memset(doc,     0, sizeof(Doc));
626   memset(chtml40, 0, sizeof(chtml40_t));
627
628   doc->r        = r;
629   chtml40->doc  = doc;
630   chtml40->spec = spec;
631   chtml40->out  = qs_alloc_zero_byte_string(r->pool);
632   chtml40->conf = chxj_get_module_config(r->per_dir_config, &chxj_module);
633   chtml40->doc->parse_mode = PARSE_MODE_CHTML;
634
635   apr_pool_create(&pool, r->pool);
636
637   chxj_buffered_write_init(pool, &doc->buf);
638
639   for (ii=0; ii<len; ii++) {
640     char *out;
641     int   rtn;
642
643     rtn = s_chtml40_search_emoji(chtml40, (char *)&src[ii], &out);
644     if (rtn) {
645       W_V(out);
646       ii+=(rtn - 1);
647       continue;
648     }
649
650     if (is_sjis_kanji(src[ii])) {
651       two_byte[0] = src[ii+0];
652       two_byte[1] = src[ii+1];
653       two_byte[2] = 0;
654       W_V(two_byte);
655       ii++;
656     }
657     else {
658       one_byte[0] = src[ii+0];
659       one_byte[1] = 0;
660       W_V(one_byte);
661     }
662   }
663   chtml40->out = chxj_buffered_write_flush(chtml40->out, &doc->buf);
664
665   DBG(r, "REQ[%X] end chxj_chtml40_emoji_eonly_converter()", (apr_size_t)(unsigned int)r);
666   return chtml40->out;
667 }
668
669
670 /**
671  * It is a handler who processes the HTML tag.
672  *
673  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
674  *                     destination is specified.
675  * @param node   [i]   The HTML tag node is specified.
676  * @return The conversion result is returned.
677  */
678 static char *
679 s_chtml40_start_html_tag(void *pdoc, Node *UNUSED(node)) 
680 {
681   chtml40_t *chtml40 = GET_CHTML40(pdoc);
682   Doc       *doc     = chtml40->doc;
683
684   /*--------------------------------------------------------------------------*/
685   /* start HTML tag                                                           */
686   /*--------------------------------------------------------------------------*/
687   W_L("<html>");
688
689   return chtml40->out;
690 }
691
692
693 /**
694  * It is a handler who processes the HTML tag.
695  *
696  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
697  *                     destination is specified.
698  * @param node   [i]   The HTML tag node is specified.
699  * @return The conversion result is returned.
700  */
701 static char *
702 s_chtml40_end_html_tag(void *pdoc, Node *UNUSED(child)) 
703 {
704   chtml40_t   *chtml40 = GET_CHTML40(pdoc);
705   Doc         *doc     = chtml40->doc;
706
707   W_L("</html>");
708   return chtml40->out;
709 }
710
711
712 /**
713  * It is a handler who processes the META tag.
714  *
715  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
716  *                     destination is specified.
717  * @param node   [i]   The META tag node is specified.
718  * @return The conversion result is returned.
719  */
720 static char *
721 s_chtml40_start_meta_tag(void *pdoc, Node *node) 
722 {
723   chtml40_t     *chtml40;
724   Doc           *doc;
725   request_rec   *r;
726   Attr          *attr;
727   int           content_type_flag;
728   int           refresh_flag;
729
730   chtml40 = GET_CHTML40(pdoc);
731   doc     = chtml40->doc;
732   r       = doc->r;
733
734   content_type_flag = 0;
735   refresh_flag      = 0;
736
737   W_L("<meta");
738   /*--------------------------------------------------------------------------*/
739   /* Get Attributes                                                           */
740   /*--------------------------------------------------------------------------*/
741   for (attr = qs_get_attr(doc,node);
742        attr;
743        attr = qs_get_next_attr(doc,attr)) {
744     char *name   = qs_get_attr_name(doc,attr);
745     char *value  = qs_get_attr_value(doc,attr);
746     switch(*name) {
747     case 'h':
748     case 'H':
749       if (strcasecmp(name, "http-equiv") == 0 && value && *value) {
750         /*----------------------------------------------------------------------*/
751         /* CHTML 2.0                                                            */
752         /*----------------------------------------------------------------------*/
753         W_L(" http-equiv=\"");
754         W_V(value);
755         W_L("\"");
756         if (STRCASEEQ('c','C',"content-type", value))
757           content_type_flag = 1;
758   
759         if (STRCASEEQ('r','R',"refresh", value))
760           refresh_flag = 1;
761       }
762       break;
763
764     case 'c':
765     case 'C':
766       if (strcasecmp(name, "content") == 0 && value && *value) {
767         if (content_type_flag) {
768           W_L(" ");
769           W_V(name);
770           W_L("=\"");
771           W_V(chxj_header_inf_set_content_type(r, "text/html; charset=SHIFT_JIS"));
772           W_L("\"");
773         }
774         else
775         if (refresh_flag) {
776           char *buf;
777           char *sec;
778           char *url;
779           buf = apr_pstrdup(r->pool, value);
780           url = strchr(buf, ';');
781           if (url) {
782             sec = apr_pstrdup(r->pool, buf);
783             sec[url-buf] = 0;
784             url++;
785             url = chxj_encoding_parameter(r, url, 0);
786             url = chxj_add_cookie_parameter(r, url, chtml40->cookie);
787             W_L(" ");
788             W_V(name);
789             W_L("=\"");
790             W_V(sec);
791             W_L(";");
792             W_V(url);
793             W_L("\"");
794           }
795         }
796         else {
797           W_L(" ");
798           W_V(name);
799           W_L("=\"");
800           W_V(value);
801           W_L("\"");
802         }
803       }
804       break;
805
806     default:
807       break;
808     }
809   }
810   W_L(">");
811   return chtml40->out;
812 }
813
814
815 /**
816  * It is a handler who processes the META tag.
817  *
818  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
819  *                     destination is specified.
820  * @param node   [i]   The META tag node is specified.
821  * @return The conversion result is returned.
822  */
823 static char*
824 s_chtml40_end_meta_tag(void* pdoc, Node* UNUSED(child)) 
825 {
826   chtml40_t *chtml40 = GET_CHTML40(pdoc);
827
828   return chtml40->out;
829 }
830
831
832 /**
833  * It is a handler who processes the HEAD tag.
834  *
835  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
836  *                     destination is specified.
837  * @param node   [i]   The HEAD tag node is specified.
838  * @return The conversion result is returned.
839  */
840 static char*
841 s_chtml40_start_head_tag(void* pdoc, Node* UNUSED(node)) 
842 {
843   chtml40_t   *chtml40 = GET_CHTML40(pdoc);
844   Doc         *doc     = chtml40->doc;
845
846   W_L("<head>");
847
848   return chtml40->out;
849 }
850
851
852 /**
853  * It is a handler who processes the HEAD tag.
854  *
855  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
856  *                     destination is specified.
857  * @param node   [i]   The HEAD tag node is specified.
858  * @return The conversion result is returned.
859  */
860 static char *
861 s_chtml40_end_head_tag(void *pdoc, Node *UNUSED(node)) 
862 {
863   chtml40_t *chtml40 = GET_CHTML40(pdoc);
864   Doc       *doc     = chtml40->doc;
865
866   W_L("</head>");
867
868   return chtml40->out;
869 }
870
871
872 /**
873  * It is a handler who processes the TITLE tag.
874  *
875  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
876  *                     destination is specified.
877  * @param node   [i]   The TITLE tag node is specified.
878  * @return The conversion result is returned.
879  */
880 static char *
881 s_chtml40_start_title_tag(void *pdoc, Node *UNUSED(node)) 
882 {
883   chtml40_t     *chtml40 = GET_CHTML40(pdoc);
884   Doc           *doc     = chtml40->doc;
885
886   W_L("<title>");
887
888   return chtml40->out;
889 }
890
891
892 /**
893  * It is a handler who processes the TITLE tag.
894  *
895  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
896  *                     destination is specified.
897  * @param node   [i]   The TITLE tag node is specified.
898  * @return The conversion result is returned.
899  */
900 static char *
901 s_chtml40_end_title_tag(void *pdoc, Node *UNUSED(child)) 
902 {
903   chtml40_t    *chtml40 = GET_CHTML40(pdoc);
904   Doc          *doc     = chtml40->doc;
905
906   W_L("</title>");
907
908   return chtml40->out;
909 }
910
911
912 /**
913  * It is a handler who processes the BASE tag.
914  *
915  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
916  *                     destination is specified.
917  * @param node   [i]   The BASE tag node is specified.
918  * @return The conversion result is returned.
919  */
920 static char *
921 s_chtml40_start_base_tag(void *pdoc, Node *node) 
922 {
923   Attr        *attr;
924   chtml40_t   *chtml40;
925   Doc         *doc;
926   request_rec *r;
927
928   chtml40 = GET_CHTML40(pdoc);
929   doc     = chtml40->doc;
930   r       = doc->r;
931
932   W_L("<base");
933   /*--------------------------------------------------------------------------*/
934   /* Get Attributes                                                           */
935   /*--------------------------------------------------------------------------*/
936   for (attr = qs_get_attr(doc,node);
937        attr;
938        attr = qs_get_next_attr(doc,attr)) {
939     char *name = qs_get_attr_name(doc,attr);
940     char *value = qs_get_attr_value(doc,attr);
941     if (STRCASEEQ('h','H',"href", name)) {
942       W_L(" href=\"");
943       W_V(value);
944       W_L("\"");
945     }
946   }
947   W_L(">");
948
949   return chtml40->out;
950 }
951
952
953 /**
954  * It is a handler who processes the BASE tag.
955  *
956  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
957  *                     destination is specified.
958  * @param node   [i]   The BASE tag node is specified.
959  * @return The conversion result is returned.
960  */
961 static char *
962 s_chtml40_end_base_tag(void *pdoc, Node *UNUSED(child)) 
963 {
964   chtml40_t *chtml40 = GET_CHTML40(pdoc);
965
966   return chtml40->out;
967 }
968
969
970 /**
971  * It is a handler who processes the BODY tag.
972  *
973  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
974  *                     destination is specified.
975  * @param node   [i]   The BODY tag node is specified.
976  * @return The conversion result is returned.
977  */
978 static char *
979 s_chtml40_start_body_tag(void *pdoc, Node *node) 
980 {
981   chtml40_t   *chtml40;
982   Doc         *doc;
983   request_rec *r;
984   Attr        *attr;
985   char        *attr_bgcolor = NULL;
986   char        *attr_text    = NULL;
987   char        *attr_link    = NULL;
988   char        *attr_style   = NULL;
989   char        *attr_alink   = NULL;
990   char        *attr_vlink   = NULL;
991
992
993   chtml40 = GET_CHTML40(pdoc);
994   doc     = chtml40->doc;
995   r       = doc->r;
996
997   /*--------------------------------------------------------------------------*/
998   /* Get Attributes                                                           */
999   /*--------------------------------------------------------------------------*/
1000   for (attr = qs_get_attr(doc,node);
1001        attr;
1002        attr = qs_get_next_attr(doc,attr)) {
1003     char *name   = qs_get_attr_name(doc,attr);
1004     char *value  = qs_get_attr_value(doc,attr);
1005     if (STRCASEEQ('b','B', "bgcolor", name) && value && *value) {
1006       /*----------------------------------------------------------------------*/
1007       /* CHTML 2.0                                                            */
1008       /*----------------------------------------------------------------------*/
1009       attr_bgcolor = value;
1010     }
1011     else if (STRCASEEQ('t','T', "text", name) && value && *value) {
1012       /*----------------------------------------------------------------------*/
1013       /* CHTML 2.0                                                            */
1014       /*----------------------------------------------------------------------*/
1015       attr_text = value;
1016     }
1017     else if (STRCASEEQ('l','L',"link", name) && value && *value) {
1018       /*----------------------------------------------------------------------*/
1019       /* CHTML 2.0                                                            */
1020       /*----------------------------------------------------------------------*/
1021       attr_link = value;
1022     }
1023     else if (STRCASEEQ('a','A',"alink", name) && value && *value) {
1024       /*----------------------------------------------------------------------*/
1025       /* CHTML 4.0                                                            */
1026       /*----------------------------------------------------------------------*/
1027       attr_alink = value;
1028     }
1029     else if (STRCASEEQ('v','V',"vlink", name) && value && *value) {
1030       /*----------------------------------------------------------------------*/
1031       /* CHTML 4.0                                                            */
1032       /*----------------------------------------------------------------------*/
1033       attr_vlink = value;
1034     }
1035     else if (STRCASEEQ('s','S',"style", name) && value && *value) {
1036       attr_style = value;
1037     }
1038   }
1039
1040   if (IS_CSS_ON(chtml40->entryp)) {
1041     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
1042     if (style) {
1043       css_property_t *color_prop      = chxj_css_get_property_value(doc, style, "color");
1044       css_property_t *bgcolor_prop    = chxj_css_get_property_value(doc, style, "background-color");
1045       css_property_t *cur;
1046       for (cur = color_prop->next; cur != color_prop; cur = cur->next) {
1047         if (cur->value && *cur->value) {
1048           attr_text = apr_pstrdup(doc->pool, cur->value);
1049         }
1050       }
1051       for (cur = bgcolor_prop->next; cur != bgcolor_prop; cur = cur->next) {
1052         if (cur->value && *cur->value) {
1053           attr_bgcolor = apr_pstrdup(doc->pool, cur->value);
1054         }
1055       }
1056     }
1057     if (chtml40->style) {
1058       css_stylesheet_t *pseudos = chxj_find_pseudo_selectors(doc, chtml40->style);
1059       css_selector_t *cur_sel;
1060       for (cur_sel = pseudos->selector_head.next; cur_sel != &pseudos->selector_head; cur_sel = cur_sel->next) {
1061         if (cur_sel->name && strcasecmp(cur_sel->name, "a:link") == 0) {
1062           css_property_t *cur;
1063           for (cur = cur_sel->property_head.next; cur != &cur_sel->property_head; cur = cur->next) {
1064             if (cur->name && strcasecmp(cur->name, "color") == 0) {
1065               attr_link = apr_pstrdup(doc->pool, cur->value);
1066             }
1067           }
1068         }
1069         else if (cur_sel->name && strcasecmp(cur_sel->name, "a:visited") == 0) {
1070           css_property_t *cur;
1071           for (cur = cur_sel->property_head.next; cur != &cur_sel->property_head; cur = cur->next) {
1072             if (cur->name && strcasecmp(cur->name, "color") == 0) {
1073               attr_vlink = apr_pstrdup(doc->pool, cur->value);
1074             }
1075           }
1076         }
1077         else if (cur_sel->name && strcasecmp(cur_sel->name, "a:focus") == 0) {
1078           css_property_t *cur;
1079           for (cur = cur_sel->property_head.next; cur != &cur_sel->property_head; cur = cur->next) {
1080             if (cur->name && strcasecmp(cur->name, "color") == 0) {
1081               attr_alink = apr_pstrdup(doc->pool, cur->value);
1082             }
1083           }
1084         }
1085       }
1086     }
1087   }
1088
1089   W_L("<body");
1090   if (attr_bgcolor) {
1091     attr_bgcolor = chxj_css_rgb_func_to_value(doc->pool, attr_bgcolor);
1092     W_L(" bgcolor=\"");
1093     W_V(attr_bgcolor);
1094     W_L("\"");
1095   }
1096   if (attr_text) {
1097     attr_text = chxj_css_rgb_func_to_value(doc->pool, attr_text);
1098     W_L(" text=\"");
1099     W_V(attr_text);
1100     W_L("\"");
1101   }
1102   if (attr_link) {
1103     attr_link = chxj_css_rgb_func_to_value(doc->pool, attr_link);
1104     W_L(" link=\"");
1105     W_V(attr_link);
1106     W_L("\"");
1107   }
1108   if (attr_alink) {
1109     attr_alink = chxj_css_rgb_func_to_value(doc->pool, attr_alink);
1110     W_L(" alink=\"");
1111     W_V(attr_alink);
1112     W_L("\"");
1113   }
1114   if (attr_vlink) {
1115     attr_vlink = chxj_css_rgb_func_to_value(doc->pool, attr_vlink);
1116     W_L(" vlink=\"");
1117     W_V(attr_vlink);
1118     W_L("\"");
1119   }
1120   W_L(">");
1121
1122   return chtml40->out;
1123 }
1124
1125
1126 /**
1127  * It is a handler who processes the BODY tag.
1128  *
1129  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
1130  *                     destination is specified.
1131  * @param node   [i]   The BODY tag node is specified.
1132  * @return The conversion result is returned.
1133  */
1134 static char *
1135 s_chtml40_end_body_tag(void *pdoc, Node *UNUSED(child)) 
1136 {
1137   chtml40_t   *chtml40;
1138   Doc         *doc;
1139
1140   chtml40 = GET_CHTML40(pdoc);
1141   doc     = chtml40->doc;
1142
1143   W_L("</body>");
1144   if (IS_CSS_ON(chtml40->entryp)) {
1145     chxj_css_pop_prop_list(chtml40->css_prop_stack);
1146   }
1147
1148   return chtml40->out;
1149 }
1150
1151
1152 /**
1153  * It is a handler who processes the A tag.
1154  *
1155  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
1156  *                     destination is specified.
1157  * @param node   [i]   The A tag node is specified.
1158  * @return The conversion result is returned.
1159  */
1160 static char *
1161 s_chtml40_start_a_tag(void *pdoc, Node *node) 
1162 {
1163   chtml40_t   *chtml40;
1164   Doc         *doc;
1165   request_rec *r;
1166   Attr        *attr;
1167   char        *attr_style = NULL;
1168
1169   chtml40 = GET_CHTML40(pdoc);
1170   doc     = chtml40->doc;
1171   r       = doc->r;
1172
1173   W_L("<a");
1174   /*--------------------------------------------------------------------------*/
1175   /* Get Attributes                                                           */
1176   /*--------------------------------------------------------------------------*/
1177   for (attr = qs_get_attr(doc,node);
1178        attr; 
1179        attr = qs_get_next_attr(doc,attr)) {
1180     char *name  = qs_get_attr_name(doc,attr);
1181     char *value = qs_get_attr_value(doc,attr);
1182     if (STRCASEEQ('n','N',"name", name)) {
1183       /*----------------------------------------------------------------------*/
1184       /* CHTML1.0                                                             */
1185       /*----------------------------------------------------------------------*/
1186       W_L(" name=\"");
1187       W_V(value);
1188       W_L("\"");
1189     }
1190     else if (STRCASEEQ('h','H',"href", name)) {
1191       /*----------------------------------------------------------------------*/
1192       /* CHTML1.0                                                             */
1193       /*----------------------------------------------------------------------*/
1194       value = chxj_encoding_parameter(r, value, 0);
1195       if (! chxj_starts_with(value, "mailto:") && ! chxj_starts_with(value, "tel:")) {
1196         value = chxj_add_cookie_parameter(r, value, chtml40->cookie);
1197       }
1198       W_L(" href=\"");
1199       W_V(value);
1200       W_L("\"");
1201     }
1202     else if (STRCASEEQ('a','A',"accesskey", name)) {
1203       /*----------------------------------------------------------------------*/
1204       /* CHTML1.0                                                             */
1205       /*----------------------------------------------------------------------*/
1206       W_L(" accesskey=\"");
1207       W_V(value);
1208       W_L("\"");
1209     }
1210     else if (STRCASEEQ('c','C',"cti", name)) {
1211       /*----------------------------------------------------------------------*/
1212       /* CHTML 2.0                                                            */
1213       /*----------------------------------------------------------------------*/
1214       W_L(" cti=\"");
1215       W_V(value);
1216       W_L("\"");
1217     }
1218     else if (STRCASEEQ('i','I',"ijam", name)) {
1219       /*----------------------------------------------------------------------*/
1220       /* CHTML 3.0                                                            */
1221       /*----------------------------------------------------------------------*/
1222       /* ignore */
1223     }
1224     else if (STRCASEEQ('u','U',"utn", name)) {
1225       /*----------------------------------------------------------------------*/
1226       /* CHTML 3.0                                                            */
1227       /* It is special only for CHTML.                                        */
1228       /*----------------------------------------------------------------------*/
1229       W_L(" utn ");
1230     }
1231     else if (STRCASEEQ('t','T',"telbook", name)) {
1232       /*----------------------------------------------------------------------*/
1233       /* CHTML 3.0                                                            */
1234       /*----------------------------------------------------------------------*/
1235       /* not support */
1236     }
1237     else if (STRCASEEQ('k','K',"kana", name)) {
1238       /*----------------------------------------------------------------------*/
1239       /* CHTML 3.0                                                            */
1240       /*----------------------------------------------------------------------*/
1241       /* not support */
1242     }
1243     else if (STRCASEEQ('e','E',"email", name)) {
1244       /*----------------------------------------------------------------------*/
1245       /* CHTML 3.0                                                            */
1246       /*----------------------------------------------------------------------*/
1247       /* not support */
1248     }
1249     else if (STRCASEEQ('i','I',"ista", name)) {
1250       /*----------------------------------------------------------------------*/
1251       /* CHTML 4.0                                                            */
1252       /*----------------------------------------------------------------------*/
1253       /* ignore */
1254     }
1255     else if (STRCASEEQ('i','I',"ilet", name)) {
1256       /*----------------------------------------------------------------------*/
1257       /* CHTML 5.0                                                            */
1258       /*----------------------------------------------------------------------*/
1259       /* ignore */
1260     }
1261     else if (STRCASEEQ('i','I',"iswf", name)) {
1262       /*----------------------------------------------------------------------*/
1263       /* CHTML 5.0                                                            */
1264       /*----------------------------------------------------------------------*/
1265       /* ignore */
1266     }
1267     else if (STRCASEEQ('i','I',"irst", name)) {
1268       /*----------------------------------------------------------------------*/
1269       /* CHTML 5.0                                                            */
1270       /*----------------------------------------------------------------------*/
1271       /* ignore */
1272     }
1273     else if (STRCASEEQ('s','S',"style", name) && value && *value) {
1274       attr_style = value;
1275     }
1276   }
1277   W_L(">");
1278
1279   if (IS_CSS_ON(chtml40->entryp)) {
1280     s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
1281   }
1282
1283   return chtml40->out;
1284 }
1285
1286
1287 /**
1288  * It is a handler who processes the A tag.
1289  *
1290  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
1291  *                     destination is specified.
1292  * @param node   [i]   The A tag node is specified.
1293  * @return The conversion result is returned.
1294  */
1295 static char *
1296 s_chtml40_end_a_tag(void *pdoc, Node *UNUSED(child)) 
1297 {
1298   chtml40_t   *chtml40;
1299   Doc         *doc;
1300
1301   chtml40 = GET_CHTML40(pdoc);
1302   doc     = chtml40->doc;
1303
1304   W_L("</a>");
1305
1306   if (IS_CSS_ON(chtml40->entryp)) {
1307     chxj_css_pop_prop_list(chtml40->css_prop_stack);
1308   }
1309
1310   return chtml40->out;
1311 }
1312
1313
1314 /**
1315  * It is a handler who processes the BR tag.
1316  *
1317  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
1318  *                     destination is specified.
1319  * @param node   [i]   The BR tag node is specified.
1320  * @return The conversion result is returned.
1321  */
1322 static char *
1323 s_chtml40_start_br_tag(void *pdoc, Node *node)
1324 {
1325   chtml40_t   *chtml40;
1326   Doc         *doc;
1327   request_rec *r;
1328   Attr        *attr;
1329
1330   chtml40 = GET_CHTML40(pdoc);
1331   doc     = chtml40->doc;
1332   r       = doc->r;
1333   W_L("<br");
1334   /*--------------------------------------------------------------------------*/
1335   /* Get Attributes                                                           */
1336   /*--------------------------------------------------------------------------*/
1337   for (attr = qs_get_attr(doc,node);
1338        attr;
1339        attr = qs_get_next_attr(doc,attr)) {
1340     char *name  = qs_get_attr_name(doc,attr);
1341     char *value = qs_get_attr_value(doc,attr);
1342     if (STRCASEEQ('c','C',"clear",name)) {
1343       if (value && (STRCASEEQ('l','L',"left",value) || STRCASEEQ('r','R',"right",value) || STRCASEEQ('a','A',"all",value))) {
1344         W_L(" clear=\"");
1345         W_V(value);
1346         W_L("\"");
1347       }
1348     }
1349   }
1350   W_L(">");
1351
1352   return chtml40->out;
1353 }
1354
1355
1356 /**
1357  * It is a handler who processes the BR tag.
1358  *
1359  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
1360  *                     destination is specified.
1361  * @param node   [i]   The BR tag node is specified.
1362  * @return The conversion result is returned.
1363  */
1364 static char *
1365 s_chtml40_end_br_tag(void *pdoc, Node *UNUSED(child)) 
1366 {
1367   chtml40_t *chtml40 = GET_CHTML40(pdoc);
1368
1369   return chtml40->out;
1370 }
1371
1372
1373 /**
1374  * It is a handler who processes the TR tag.
1375  *
1376  * @param chtml40  [i/o] The pointer to the CHTML structure at the output
1377  *                     destination is specified.
1378  * @param node   [i]   The TR tag node is specified.
1379  * @return The conversion result is returned.
1380  */
1381 static char *
1382 s_chtml40_start_tr_tag(void *pdoc, Node *UNUSED(node)) 
1383 {
1384   chtml40_t *chtml40 = GET_CHTML40(pdoc);
1385
1386   return chtml40->out;
1387 }
1388
1389
1390 /**
1391  * It is a handler who processes the TR tag.
1392  *
1393  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
1394  *                     destination is specified.
1395  * @param node   [i]   The TR tag node is specified.
1396  * @return The conversion result is returned.
1397  */
1398 static char *
1399 s_chtml40_end_tr_tag(void *pdoc, Node *UNUSED(child)) 
1400 {
1401   chtml40_t   *chtml40;
1402   Doc         *doc;
1403   request_rec *r;
1404
1405   chtml40 = GET_CHTML40(pdoc);
1406   doc     = chtml40->doc;
1407   r       = doc->r;
1408
1409   W_L("<br>");
1410
1411   return chtml40->out;
1412 }
1413
1414
1415 /**
1416  * It is a handler who processes the FONT tag.
1417  *
1418  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
1419  *                     destination is specified.
1420  * @param node   [i]   The FONT tag node is specified.
1421  * @return The conversion result is returned.
1422  */
1423 static char *
1424 s_chtml40_start_font_tag(void *pdoc, Node *node) 
1425 {
1426   Attr          *attr;
1427   chtml40_t     *chtml40;
1428   Doc           *doc;
1429   request_rec   *r;
1430   char          *attr_color = NULL;
1431   char          *attr_style = NULL;
1432
1433   chtml40 = GET_CHTML40(pdoc);
1434   doc     = chtml40->doc;
1435   r       = doc->r;
1436
1437   /*--------------------------------------------------------------------------*/
1438   /* Get Attributes                                                           */
1439   /*--------------------------------------------------------------------------*/
1440   for (attr = qs_get_attr(doc,node);
1441        attr; 
1442        attr = qs_get_next_attr(doc,attr)) {
1443     char *name  = qs_get_attr_name(doc,attr);
1444     char *value = qs_get_attr_value(doc,attr);
1445     if (STRCASEEQ('c','C',"color", name) && value && *value) {
1446       attr_color = apr_pstrdup(doc->buf.pool, value);
1447       break;
1448     }
1449     else if (STRCASEEQ('s','S',"size", name)) {
1450       /*----------------------------------------------------------------------*/
1451       /* CHTML 5.0                                                            */
1452       /*----------------------------------------------------------------------*/
1453       /* ignore */
1454     }
1455     else if (STRCASEEQ('s','S',"style", name) && value && *value) {
1456       attr_style = value;
1457     }
1458   }
1459   if (IS_CSS_ON(chtml40->entryp)) {
1460     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
1461     if (style) {
1462       css_property_t *color_prop = chxj_css_get_property_value(doc, style, "color");
1463       css_property_t *cur;
1464       for (cur = color_prop->next; cur != color_prop; cur = cur->next) {
1465         if (cur->value && *cur->value) {
1466           attr_color = apr_pstrdup(doc->pool, cur->value);
1467         }
1468       }
1469     }
1470   }
1471   if (attr_color) {
1472     attr_color = chxj_css_rgb_func_to_value(doc->pool, attr_color);
1473     W_L("<font color=\"");
1474     W_V(attr_color);
1475     W_L("\">");
1476     chtml40_flags_t *flg = (chtml40_flags_t *)apr_palloc(doc->pool, sizeof(*flg));
1477     flg->with_font_flag = 1;
1478     node->userData = flg;
1479   }
1480   else {
1481     node->userData = NULL;
1482   }
1483   return chtml40->out;
1484 }
1485
1486
1487 /**
1488  * It is a handler who processes the FONT tag.
1489  *
1490  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
1491  *                     destination is specified.
1492  * @param node   [i]   The FONT tag node is specified.
1493  * @return The conversion result is returned.
1494  */
1495 static char *
1496 s_chtml40_end_font_tag(void *pdoc, Node *node)
1497 {
1498   chtml40_t     *chtml40;
1499   Doc           *doc;
1500   request_rec   *r;
1501
1502   chtml40 = GET_CHTML40(pdoc);
1503   doc     = chtml40->doc;
1504   r       = doc->r;
1505
1506   chtml40_flags_t *flg = (chtml40_flags_t *)node->userData;
1507   if (flg && flg->with_font_flag) {
1508     W_L("</font>");
1509   }
1510   if (IS_CSS_ON(chtml40->entryp)) {
1511     chxj_css_pop_prop_list(chtml40->css_prop_stack);
1512   }
1513
1514   return chtml40->out;
1515 }
1516
1517
1518 /**
1519  * It is a handler who processes the FORM tag.
1520  *
1521  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
1522  *                     destination is specified.
1523  * @param node   [i]   The FORM tag node is specified.
1524  * @return The conversion result is returned.
1525  */
1526 static char *
1527 s_chtml40_start_form_tag(void *pdoc, Node *node) 
1528 {
1529   chtml40_t   *chtml40;
1530   Doc         *doc;
1531   request_rec *r;
1532   Attr        *attr;
1533   char        *attr_action = NULL;
1534   char        *attr_method = NULL;
1535   char        *attr_style  = NULL;
1536   char        *attr_color  = NULL;
1537   char        *attr_align  = NULL;
1538   char        *attr_utn    = NULL;
1539   char        *new_hidden_tag = NULL;
1540
1541   chtml40 = GET_CHTML40(pdoc);
1542   doc     = chtml40->doc;
1543   r       = doc->r;
1544
1545   /*--------------------------------------------------------------------------*/
1546   /* Get Attributes                                                           */
1547   /*--------------------------------------------------------------------------*/
1548   for (attr = qs_get_attr(doc,node);
1549        attr;
1550        attr = qs_get_next_attr(doc,attr)) {
1551     char *name  = qs_get_attr_name(doc,attr);
1552     char *value = qs_get_attr_value(doc,attr);
1553     switch(*name) {
1554     case 'a':
1555     case 'A':
1556       if (strcasecmp(name, "action") == 0) {
1557         /*--------------------------------------------------------------------*/
1558         /* CHTML 1.0                                                          */
1559         /*--------------------------------------------------------------------*/
1560         attr_action = value;
1561       }
1562       break;
1563
1564     case 'm':
1565     case 'M':
1566       if (strcasecmp(name, "method") == 0) {
1567         /*--------------------------------------------------------------------*/
1568         /* CHTML 1.0                                                          */
1569         /*--------------------------------------------------------------------*/
1570         attr_method = value;
1571       }
1572       break;
1573
1574     case 'u':
1575     case 'U':
1576       if (strcasecmp(name, "utn") == 0) {
1577         /*--------------------------------------------------------------------*/
1578         /* CHTML 3.0                                                          */
1579         /*--------------------------------------------------------------------*/
1580         attr_utn = value;
1581       }
1582       break;
1583
1584     case 's':
1585     case 'S':
1586       if (strcasecmp(name, "style") == 0) {
1587         attr_style = value;
1588       }
1589       break;
1590
1591     default:
1592       break;
1593     }
1594   }
1595   if (IS_CSS_ON(chtml40->entryp)) {
1596     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
1597     if (style) {
1598       css_property_t *text_align_prop = chxj_css_get_property_value(doc, style, "text-align");
1599       css_property_t *color_prop      = chxj_css_get_property_value(doc, style, "color");
1600       css_property_t *cur;
1601       for (cur = text_align_prop->next; cur != text_align_prop; cur = cur->next) {
1602         if (STRCASEEQ('l','L',"left", cur->value)) {
1603           attr_align = apr_pstrdup(doc->pool, "left");
1604         }
1605         else if (STRCASEEQ('c','C',"center",cur->value)) {
1606           attr_align = apr_pstrdup(doc->pool, "center");
1607         }
1608         else if (STRCASEEQ('r','R',"right",cur->value)) {
1609           attr_align = apr_pstrdup(doc->pool, "right");
1610         }
1611       }
1612       for (cur = color_prop->next; cur != color_prop; cur = cur->next) {
1613         attr_color = apr_pstrdup(doc->pool, cur->value);
1614       }
1615     }
1616   }
1617
1618   int post_flag = (attr_method && strcasecmp(attr_method, "post") == 0) ? 1 : 0;
1619
1620   W_L("<form");
1621   if (attr_action) {
1622     attr_action = chxj_encoding_parameter(r, attr_action, 0);
1623     attr_action = chxj_add_cookie_parameter(r, attr_action, chtml40->cookie);
1624     char *q;
1625     char *new_query_string = NULL;
1626     q = strchr(attr_action, '?');
1627     if (q) {
1628       new_hidden_tag = chxj_form_action_to_hidden_tag(r, doc->pool, attr_action, 0, post_flag, &new_query_string, CHXJ_TRUE, CHXJ_FALSE, chtml40->entryp);
1629       if (new_hidden_tag || new_query_string) {
1630         *q = 0;
1631       }
1632     }
1633     W_L(" action=\"");
1634     W_V(attr_action);
1635     if (new_query_string) {
1636       W_L("?");
1637       W_V(new_query_string);
1638     }
1639     W_L("\"");
1640   }
1641   if (attr_method) {
1642     W_L(" method=\"");
1643     W_V(attr_method);
1644     W_L("\"");
1645   }
1646   if (attr_utn) {
1647     W_L(" utn");
1648   }
1649   W_L(">");
1650   if (new_hidden_tag) {
1651     W_V(new_hidden_tag);
1652   }
1653
1654   chtml40_flags_t *flg = (chtml40_flags_t *)apr_palloc(doc->pool, sizeof(chtml40_flags_t));
1655   memset(flg, 0, sizeof(*flg));
1656   if (attr_color) {
1657     attr_color = chxj_css_rgb_func_to_value(doc->pool, attr_color);
1658     W_L("<font color=\"");
1659     W_V(attr_color);
1660     W_L("\">");
1661     flg->with_font_flag = 1;
1662   }
1663   if (attr_align) {
1664     W_L("<div align=\"");
1665     W_V(attr_align);
1666     W_L("\">");
1667     flg->with_div_flag = 1;
1668   }
1669   node->userData = flg;
1670
1671   return chtml40->out;
1672 }
1673
1674
1675 /**
1676  * It is a handler who processes the FORM tag.
1677  *
1678  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
1679  *                     destination is specified.
1680  * @param node   [i]   The FORM tag node is specified.
1681  * @return The conversion result is returned.
1682  */
1683 static char *
1684 s_chtml40_end_form_tag(void *pdoc, Node *node)
1685 {
1686   chtml40_t    *chtml40;
1687   Doc          *doc;
1688
1689   chtml40 = GET_CHTML40(pdoc);
1690   doc     = chtml40->doc;
1691
1692   chtml40_flags_t *flg = (chtml40_flags_t *)node->userData;
1693   if (flg && flg->with_div_flag) {
1694     W_L("</div>");
1695   }
1696   if (flg && flg->with_font_flag) {
1697     W_L("</font>");
1698   }
1699   W_L("</form>");
1700   if (IS_CSS_ON(chtml40->entryp)) {
1701     chxj_css_pop_prop_list(chtml40->css_prop_stack);
1702   }
1703
1704   return chtml40->out;
1705 }
1706
1707
1708 /**
1709  * It is a handler who processes the INPUT tag.
1710  *
1711  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
1712  *                     destination is specified.
1713  * @param node   [i]   The INPUT tag node is specified.
1714  * @return The conversion result is returned.
1715  */
1716 static char *
1717 s_chtml40_start_input_tag(void *pdoc, Node *node) 
1718 {
1719   chtml40_t   *chtml40;
1720   Doc         *doc;
1721   request_rec *r;
1722   Attr        *attr;
1723   char        *attr_accesskey  = NULL;
1724   char        *attr_max_length = NULL;
1725   char        *attr_type       = NULL;
1726   char        *attr_name       = NULL;
1727   char        *attr_value      = NULL;
1728   char        *attr_istyle     = NULL;
1729   char        *attr_size       = NULL;
1730   char        *attr_checked    = NULL;
1731   char        *attr_style      = NULL;
1732
1733   chtml40 = GET_CHTML40(pdoc);
1734   doc     = chtml40->doc;
1735   r       = doc->r;
1736
1737   /*--------------------------------------------------------------------------*/
1738   /* Get Attributes                                                           */
1739   /*--------------------------------------------------------------------------*/
1740   for (attr = qs_get_attr(doc,node);
1741        attr;
1742        attr = qs_get_next_attr(doc,attr)) {
1743     char *name  = qs_get_attr_name(doc,attr);
1744     char *value = qs_get_attr_value(doc,attr);
1745     if (STRCASEEQ('t','T',"type",name) && value && *value) {
1746       char *tmp_type = qs_trim_string(doc->buf.pool, value);
1747       if (tmp_type && (STRCASEEQ('t','T',"text",    tmp_type) ||
1748                        STRCASEEQ('p','P',"password",tmp_type) ||
1749                        STRCASEEQ('c','C',"checkbox",tmp_type) ||
1750                        STRCASEEQ('r','R',"radio",   tmp_type) ||
1751                        STRCASEEQ('h','H',"hidden",  tmp_type) ||
1752                        STRCASEEQ('s','S',"submit",  tmp_type) ||
1753                        STRCASEEQ('r','R',"reset",   tmp_type))) {
1754         attr_type = tmp_type;
1755       }
1756     }
1757     else if (STRCASEEQ('n','N',"name",name) && value && *value) {
1758       attr_name = value;
1759     }
1760     else if (STRCASEEQ('v','V',"value",name) && value && *value) {
1761       attr_value = value;
1762     }
1763     else if (STRCASEEQ('i','I',"istyle",name) && value && *value) {
1764       attr_istyle = value;
1765     }
1766     else if (STRCASEEQ('m','M',"maxlength",name) && value && *value) {
1767       attr_max_length = value;
1768     }
1769     else if (STRCASEEQ('c','C',"checked", name)) {
1770       attr_checked = value;
1771     }
1772     else if (STRCASEEQ('a','A',"accesskey", name) && value && *value) {
1773       attr_accesskey = value;
1774     }
1775     else if (STRCASEEQ('s','S',"size", name) && value && *value) {
1776       attr_size = value;
1777     }
1778     else if (STRCASEEQ('s','S',"style", name) && value && *value) {
1779       attr_style = value;
1780     }
1781   }
1782
1783   if (IS_CSS_ON(chtml40->entryp)) {
1784     css_prop_list_t *style = s_chtml40_nopush_and_get_now_style(pdoc, node, attr_style);
1785     if (style) {
1786       css_property_t *wap_input_format = chxj_css_get_property_value(doc, style, "-wap-input-format");
1787       css_property_t *cur;
1788       for (cur = wap_input_format->next; cur != wap_input_format; cur = cur->next) {
1789         if (strcasestr(cur->value, "<ja:n>")) {
1790           attr_istyle = "4";
1791         }
1792         else if (strcasestr(cur->value, "<ja:en>")) {
1793           attr_istyle = "3";
1794         }
1795         else if (strcasestr(cur->value, "<ja:hk>")) {
1796           attr_istyle = "2";
1797         }
1798         else if (strcasestr(cur->value, "<ja:h>")) {
1799           attr_istyle = "1";
1800         }
1801       }
1802     }
1803   }
1804
1805   W_L("<input");
1806   if (attr_type) {
1807     W_L(" type=\"");
1808     W_V(attr_type);
1809     W_L("\"");
1810   }
1811   if (attr_size) {
1812     W_L(" size=\"");
1813     W_V(attr_size);
1814     W_L("\"");
1815   }
1816   if (attr_name) {
1817     W_L(" name=\"");
1818     W_V(attr_name);
1819     W_L("\"");
1820   }
1821   if (attr_value) {
1822     W_L(" value=\"");
1823     W_V(chxj_add_slash_to_doublequote(doc->pool, attr_value));
1824     W_L("\"");
1825   }
1826   if (attr_accesskey) {
1827     W_L(" accesskey=\"");
1828     W_V(attr_accesskey);
1829     W_L("\"");
1830   }
1831   if (attr_istyle) {
1832     if (*attr_istyle == '1' || *attr_istyle == '2' || *attr_istyle == '3' || *attr_istyle == '4') {
1833       W_L(" istyle=\"");
1834       W_V(attr_istyle);
1835       W_L("\"");
1836     }
1837   }
1838   /*--------------------------------------------------------------------------*/
1839   /* The figure is default for the password.                                  */
1840   /*--------------------------------------------------------------------------*/
1841   if (attr_max_length) {
1842     if (chxj_chk_numeric(attr_max_length) != 0) {
1843       attr_max_length = apr_psprintf(doc->buf.pool, "0");
1844     }
1845     if (attr_istyle && *attr_istyle == '1') {
1846       char *vv = apr_psprintf(doc->buf.pool, " maxlength=\"%d\"", chxj_atoi(attr_max_length) * 2);
1847       W_V(vv);
1848     }
1849     else {
1850       char *vv = apr_psprintf(doc->buf.pool, " maxlength=\"%d\"", chxj_atoi(attr_max_length));
1851       W_V(vv);
1852     }
1853   }
1854   if (attr_checked) {
1855     W_L(" checked");
1856   }
1857   W_L(">");
1858
1859   return chtml40->out;
1860 }
1861
1862
1863 /**
1864  * It is a handler who processes the INPUT tag.
1865  *
1866  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
1867  *                     destination is specified.
1868  * @param node   [i]   The INPUT tag node is specified.
1869  * @return The conversion result is returned.
1870  */
1871 static char *
1872 s_chtml40_end_input_tag(void *pdoc, Node *UNUSED(child)) 
1873 {
1874   chtml40_t *chtml40 = GET_CHTML40(pdoc);
1875
1876   return chtml40->out;
1877 }
1878
1879
1880 /**
1881  * It is a handler who processes the CENTER tag.
1882  *
1883  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
1884  *                     destination is specified.
1885  * @param node   [i]   The CENTER tag node is specified.
1886  * @return The conversion result is returned.
1887  */
1888 static char *
1889 s_chtml40_start_center_tag(void *pdoc, Node *node)
1890 {
1891   chtml40_t   *chtml40;
1892   Doc         *doc;
1893   Attr        *attr;
1894   char        *attr_style = NULL;
1895   char        *attr_color = NULL;
1896
1897   chtml40 = GET_CHTML40(pdoc);
1898   doc     = chtml40->doc;
1899
1900   for (attr = qs_get_attr(doc,node);
1901        attr;
1902        attr = qs_get_next_attr(doc,attr)) {
1903     char *name  = qs_get_attr_name(doc,attr);
1904     char *value = qs_get_attr_value(doc,attr);
1905     if (STRCASEEQ('s','S',"style",name) && value && *value) {
1906       attr_style = value;
1907     }
1908   }
1909   if (IS_CSS_ON(chtml40->entryp)) {
1910     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
1911     if (style) {
1912       css_property_t *color_prop      = chxj_css_get_property_value(doc, style, "color");
1913       css_property_t *cur;
1914       for (cur = color_prop->next; cur != color_prop; cur = cur->next) {
1915         if (cur->value && *cur->value) {
1916           attr_color = apr_pstrdup(doc->pool, cur->value);
1917         }
1918       }
1919     }
1920   }
1921
1922   W_L("<center>");
1923   chtml40_flags_t *flg = (chtml40_flags_t *)apr_palloc(doc->pool, sizeof(chtml40_flags_t));
1924   memset(flg, 0, sizeof(*flg));
1925   if (attr_color) {
1926     attr_color = chxj_css_rgb_func_to_value(doc->pool, attr_color);
1927     W_L("<font color=\"");
1928     W_V(attr_color);
1929     W_L("\">");
1930     flg->with_font_flag = 1;
1931   }
1932   node->userData = flg;
1933
1934   return chtml40->out;
1935 }
1936
1937
1938 /**
1939  * It is a handler who processes the CENTER tag.
1940  *
1941  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
1942  *                     destination is specified.
1943  * @param node   [i]   The CENTER tag node is specified.
1944  * @return The conversion result is returned.
1945  */
1946 static char *
1947 s_chtml40_end_center_tag(void *pdoc, Node *node)
1948 {
1949   chtml40_t     *chtml40;
1950   Doc           *doc;
1951
1952   chtml40 = GET_CHTML40(pdoc);
1953   doc     = chtml40->doc;
1954
1955   if (IS_CSS_ON(chtml40->entryp)) {
1956     chxj_css_pop_prop_list(chtml40->css_prop_stack);
1957   }
1958   chtml40_flags_t *flg = (chtml40_flags_t *)node->userData;
1959   if (flg && flg->with_font_flag) {
1960     W_L("</font>");
1961   }
1962   W_L("</center>");
1963
1964   return chtml40->out;
1965 }
1966
1967
1968 /**
1969  * It is a handler who processes the HR tag.
1970  *
1971  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
1972  *                     destination is specified.
1973  * @param node   [i]   The HR tag node is specified.
1974  * @return The conversion result is returned.
1975  */
1976 static char *
1977 s_chtml40_start_hr_tag(void *pdoc, Node *node) 
1978 {
1979   Attr        *attr;
1980   chtml40_t   *chtml40;
1981   Doc         *doc;
1982   request_rec *r;
1983   char        *attr_align   = NULL;
1984   char        *attr_size    = NULL;
1985   char        *attr_width   = NULL;
1986   char        *attr_noshade = NULL;
1987   char        *attr_style   = NULL;
1988   char        *attr_color   = NULL;
1989
1990   chtml40 = GET_CHTML40(pdoc);
1991   doc     = chtml40->doc;
1992   r       = doc->r;
1993
1994   for (attr = qs_get_attr(doc,node);
1995        attr; 
1996        attr = qs_get_next_attr(doc,attr)) {
1997     char *name  = qs_get_attr_name (doc,attr);
1998     char *value = qs_get_attr_value(doc,attr);
1999     switch(*name) {
2000     case 'a':
2001     case 'A':
2002       if (strcasecmp(name, "align") == 0) {
2003         /*--------------------------------------------------------------------*/
2004         /* CHTML 1.0                                                          */
2005         /*--------------------------------------------------------------------*/
2006         if (value && (STRCASEEQ('l','L',"left",value) || STRCASEEQ('r','R',"right",value) || STRCASEEQ('c','C',"center",value))) {
2007           attr_align = value;
2008         }
2009       }
2010       break;
2011
2012     case 's':
2013     case 'S':
2014       if (strcasecmp(name, "size") == 0) {
2015         /*--------------------------------------------------------------------*/
2016         /* CHTML 1.0                                                          */
2017         /*--------------------------------------------------------------------*/
2018         if (value && *value) {
2019           attr_size = value;
2020         }
2021       }
2022       else if (strcasecmp(name, "style") == 0) {
2023         if (value && *value) {
2024           attr_style = value;
2025         }
2026       }
2027       break;
2028
2029     case 'w':
2030     case 'W':
2031       if (strcasecmp(name, "width") == 0) {
2032         /*--------------------------------------------------------------------*/
2033         /* CHTML 1.0                                                          */
2034         /*--------------------------------------------------------------------*/
2035         if (value && *value) {
2036           attr_width = value;
2037         }
2038       }
2039       break;
2040
2041     case 'n':
2042     case 'N':
2043       if (strcasecmp(name, "noshade") == 0) {
2044         /*--------------------------------------------------------------------*/
2045         /* CHTML 1.0                                                          */
2046         /*--------------------------------------------------------------------*/
2047         attr_noshade = apr_pstrdup(doc->pool, "noshade");
2048       }
2049       break;
2050
2051     case 'c':
2052     case 'C':
2053       if (strcasecmp(name, "color") == 0 && value && *value) {
2054         /*--------------------------------------------------------------------*/
2055         /* CHTML 4.0                                                          */
2056         /*--------------------------------------------------------------------*/
2057         attr_color = value;
2058       }
2059       break;
2060
2061     default:
2062       break;
2063     }
2064   }
2065   if (IS_CSS_ON(chtml40->entryp)) {
2066     css_prop_list_t *style = s_chtml40_nopush_and_get_now_style(pdoc, node, attr_style);
2067     if (style) {
2068       css_property_t *border_style_prop = chxj_css_get_property_value(doc, style, "border-style");
2069       css_property_t *height_prop       = chxj_css_get_property_value(doc, style, "height");
2070       css_property_t *width_prop        = chxj_css_get_property_value(doc, style, "width");
2071       css_property_t *cur;
2072       for (cur = border_style_prop->next; cur != border_style_prop; cur = cur->next) {
2073         if (STRCASEEQ('s','S',"solid",cur->value)) {
2074           attr_noshade = "noshade";
2075         }
2076       }
2077       for (cur = height_prop->next; cur != height_prop; cur = cur->next) {
2078         char *tmp = apr_pstrdup(doc->pool, cur->value);
2079         char *tmpp = strstr(tmp, "px");
2080         if (tmpp) { 
2081           *tmpp = 0;
2082           attr_size = apr_pstrdup(doc->pool, tmp);
2083         }
2084       }
2085       for (cur = width_prop->next; cur != width_prop; cur = cur->next) {
2086         char *tmp = apr_pstrdup(doc->pool, cur->value);
2087         char *tmpp = strstr(tmp, "px");
2088         if (tmpp) {
2089           *tmpp = 0;
2090           attr_width = apr_pstrdup(doc->pool, tmp);
2091         }
2092         else {
2093           tmpp = strstr(tmp, "%");
2094           if (tmpp) {
2095             attr_width = apr_pstrdup(doc->pool, tmp);
2096           }
2097         }
2098       }
2099     }
2100   }
2101   W_L("<hr");
2102   if (attr_align) {
2103     W_L(" align=\"");
2104     W_V(attr_align);
2105     W_L("\"");
2106   }
2107   if (attr_size) {
2108     W_L(" size=\"");
2109     W_V(attr_size);
2110     W_L("\"");
2111   }
2112   if (attr_width) {
2113     W_L(" width=\"");
2114     W_V(attr_width);
2115     W_L("\"");
2116   }
2117   if (attr_color) {
2118     W_L(" color=\"");
2119     W_V(attr_color);
2120     W_L("\"");
2121   }
2122   if (attr_noshade) {
2123     W_L(" noshade");
2124   }
2125   W_L(">");
2126   return chtml40->out;
2127 }
2128
2129
2130 /**
2131  * It is a handler who processes the HR tag.
2132  *
2133  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
2134  *                     destination is specified.
2135  * @param node   [i]   The HR tag node is specified.
2136  * @return The conversion result is returned.
2137  */
2138 static char *
2139 s_chtml40_end_hr_tag(void *pdoc, Node *UNUSED(child)) 
2140 {
2141   chtml40_t *chtml40 = GET_CHTML40(pdoc);
2142
2143   return chtml40->out;
2144 }
2145
2146
2147 /**
2148  * It is a handler who processes the IMG tag.
2149  *
2150  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
2151  *                     destination is specified.
2152  * @param node   [i]   The IMG tag node is specified.
2153  * @return The conversion result is returned.
2154  */
2155 static char *
2156 s_chtml40_start_img_tag(void *pdoc, Node *node) 
2157 {
2158   chtml40_t   *chtml40;
2159   Doc         *doc;
2160   request_rec *r;
2161   Attr        *attr;
2162   char        *attr_src    = NULL;
2163   char        *attr_align  = NULL;
2164   char        *attr_style  = NULL;
2165   char        *attr_alt    = NULL;
2166   char        *attr_width  = NULL;
2167   char        *attr_height = NULL;
2168   char        *attr_hspace = NULL;
2169   char        *attr_vspace = NULL;
2170 #ifndef IMG_NOT_CONVERT_FILENAME
2171   device_table *spec;
2172 #endif
2173
2174   chtml40 = GET_CHTML40(pdoc);
2175 #ifndef IMG_NOT_CONVERT_FILENAME
2176   spec    = chtml40->spec;
2177 #endif
2178   doc     = chtml40->doc;
2179   r       = doc->r;
2180
2181   /*--------------------------------------------------------------------------*/
2182   /* Get Attributes                                                           */
2183   /*--------------------------------------------------------------------------*/
2184   for (attr = qs_get_attr(doc,node);
2185        attr;
2186        attr = qs_get_next_attr(doc,attr)) {
2187     char *name  = qs_get_attr_name (doc,attr);
2188     char *value = qs_get_attr_value(doc,attr);
2189     switch(*name) {
2190     case 's':
2191     case 'S':
2192       if (strcasecmp(name, "src") == 0) {
2193         /*--------------------------------------------------------------------*/
2194         /* CHTML 1.0                                                          */
2195         /*--------------------------------------------------------------------*/
2196 #ifdef IMG_NOT_CONVERT_FILENAME
2197       value = chxj_encoding_parameter(r, value, 0);
2198       value = chxj_add_cookie_parameter(r, value, chtml40->cookie);
2199       value = chxj_add_cookie_no_update_parameter(r, value);
2200       attr_src = value;
2201 #else
2202       value = chxj_img_conv(r,spec,value);
2203       value = chxj_encoding_parameter(r, value, 0);
2204       value = chxj_add_cookie_parameter(r, value, chtml40->cookie);
2205       value = chxj_add_cookie_no_update_parameter(r, value);
2206       attr_src = value;
2207 #endif
2208       }
2209       else if (strcasecmp(name,"style") == 0 && value && *value) {
2210         attr_style = value;
2211       }
2212       break;
2213
2214     case 'a':
2215     case 'A':
2216       if (strcasecmp(name, "align" ) == 0) {
2217         /*--------------------------------------------------------------------*/
2218         /* CHTML 1.0                                                          */
2219         /*--------------------------------------------------------------------*/
2220         /*--------------------------------------------------------------------*/
2221         /* CHTML 4.0                                                          */
2222         /*--------------------------------------------------------------------*/
2223         if (value) {
2224           if (STRCASEEQ('t','T',"top",   value) ||
2225               STRCASEEQ('m','M',"middle",value) ||
2226               STRCASEEQ('b','B',"bottom",value) ||
2227               STRCASEEQ('l','L',"left",  value) ||
2228               STRCASEEQ('r','R',"right", value)) {
2229             attr_align = value;
2230           }
2231           else if (STRCASEEQ('c','C',"center",  value)) {
2232             attr_align = apr_pstrdup(doc->pool, "middle");
2233           }
2234         }
2235       }
2236       else if (strcasecmp(name, "alt"   ) == 0 && value && *value) {
2237         /*--------------------------------------------------------------------*/
2238         /* CHTML 1.0                                                          */
2239         /*--------------------------------------------------------------------*/
2240         attr_alt = value;
2241       }
2242       break;
2243
2244     case 'w':
2245     case 'W':
2246       if (strcasecmp(name, "width" ) == 0 && value && *value) {
2247         /*--------------------------------------------------------------------*/
2248         /* CHTML 1.0                                                          */
2249         /*--------------------------------------------------------------------*/
2250         attr_width = value;
2251       }
2252       break;
2253
2254     case 'h':
2255     case 'H':
2256       if (strcasecmp(name, "height") == 0 && value && *value) {
2257         /*--------------------------------------------------------------------*/
2258         /* CHTML 1.0                                                          */
2259         /*--------------------------------------------------------------------*/
2260         attr_height = value;
2261       }
2262       else
2263       if (strcasecmp(name, "hspace") == 0 && value && *value) {
2264         /*--------------------------------------------------------------------*/
2265         /* CHTML 1.0                                                          */
2266         /*--------------------------------------------------------------------*/
2267         attr_hspace = value;
2268       }
2269       break;
2270
2271     case 'v':
2272     case 'V':
2273       if (strcasecmp(name, "vspace") == 0 && value && *value) {
2274         /*--------------------------------------------------------------------*/
2275         /* CHTML 1.0                                                          */
2276         /*--------------------------------------------------------------------*/
2277         attr_vspace = value;
2278       }
2279       break;
2280
2281     default:
2282       break;
2283     }
2284   }
2285
2286   if (IS_CSS_ON(chtml40->entryp)) {
2287     css_prop_list_t *style = s_chtml40_nopush_and_get_now_style(pdoc, node, attr_style);
2288     if (style) {
2289       css_property_t *height_prop = chxj_css_get_property_value(doc, style, "height");
2290       css_property_t *width_prop  = chxj_css_get_property_value(doc, style, "width");
2291       css_property_t *valign_prop = chxj_css_get_property_value(doc, style, "vertical-align");
2292       css_property_t *cur;
2293       for (cur = height_prop->next; cur != height_prop; cur = cur->next) {
2294         attr_height = apr_pstrdup(doc->pool, cur->value);
2295       }
2296       for (cur = width_prop->next; cur != width_prop; cur = cur->next) {
2297         attr_width = apr_pstrdup(doc->pool, cur->value);
2298       }
2299       for (cur = valign_prop->next; cur != valign_prop; cur = cur->next) {
2300         attr_align = apr_pstrdup(doc->pool, cur->value);
2301       }
2302     }
2303   }
2304
2305   W_L("<img");
2306   if (attr_src) {
2307     W_L(" src=\"");
2308     W_V(attr_src);
2309     W_L("\"");
2310   }
2311   if (attr_align) {
2312     W_L(" align=\"");
2313     W_V(attr_align);
2314     W_L("\"");
2315   }
2316   if (attr_alt) {
2317     W_L(" alt=\"");
2318     W_V(attr_alt);
2319     W_L("\"");
2320   }
2321   if (attr_width) {
2322     W_L(" width=\"");
2323     W_V(attr_width);
2324     W_L("\"");
2325   }
2326   if (attr_height) {
2327     W_L(" height=\"");
2328     W_V(attr_height);
2329     W_L("\"");
2330   }
2331   if (attr_hspace) {
2332     W_L(" hspace=\"");
2333     W_V(attr_hspace);
2334     W_L("\"");
2335   }
2336   if (attr_vspace) {
2337     W_L(" vspace=\"");
2338     W_V(attr_vspace);
2339     W_L("\"");
2340   }
2341   W_L(">");
2342   return chtml40->out;
2343 }
2344
2345
2346 /**
2347  * It is a handler who processes the IMG tag.
2348  *
2349  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
2350  *                     destination is specified.
2351  * @param node   [i]   The IMG tag node is specified.
2352  * @return The conversion result is returned.
2353  */
2354 static char *
2355 s_chtml40_end_img_tag(void *pdoc, Node *UNUSED(child)) 
2356 {
2357   chtml40_t *chtml40 = GET_CHTML40(pdoc);
2358
2359   return chtml40->out;
2360 }
2361
2362
2363 /**
2364  * It is a handler who processes the SELECT tag.
2365  *
2366  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
2367  *                     destination is specified.
2368  * @param node   [i]   The SELECT tag node is specified.
2369  * @return The conversion result is returned.
2370  */
2371 static char *
2372 s_chtml40_start_select_tag(void *pdoc, Node *node)
2373 {
2374   chtml40_t   *chtml40  = GET_CHTML40(pdoc);
2375   Doc         *doc      = chtml40->doc;
2376   char        *size     = NULL;
2377   char        *name     = NULL;
2378   char        *multiple = NULL;
2379   Attr        *attr;
2380   char        *attr_style = NULL;
2381
2382   W_L("<select");
2383   for (attr = qs_get_attr(doc,node);
2384        attr;
2385        attr = qs_get_next_attr(doc,attr)) {
2386     char *nm  = qs_get_attr_name(doc,attr);
2387     char *val = qs_get_attr_value(doc,attr);
2388     if (STRCASEEQ('s','S',"size", nm)) {
2389       /*----------------------------------------------------------------------*/
2390       /* CHTML 1.0 version 2.0                                                */
2391       /*----------------------------------------------------------------------*/
2392       size = apr_pstrdup(doc->buf.pool, val);
2393     }
2394     else if (STRCASEEQ('s','S',"style", nm) && val && *val) {
2395       /*----------------------------------------------------------------------*/
2396       /* CHTML 1.0 version 2.0                                                */
2397       /*----------------------------------------------------------------------*/
2398       attr_style = apr_pstrdup(doc->buf.pool, val);
2399     }
2400     else if (STRCASEEQ('n','N',"name", nm)) {
2401       /*----------------------------------------------------------------------*/
2402       /* CHTML 1.0 version 2.0                                                */
2403       /*----------------------------------------------------------------------*/
2404       name = apr_pstrdup(doc->buf.pool, val);
2405     }
2406     else if (STRCASEEQ('m','M',"multiple", nm)) {
2407       /*----------------------------------------------------------------------*/
2408       /* CHTML 1.0 version 2.0                                                */
2409       /*----------------------------------------------------------------------*/
2410       multiple = apr_pstrdup(doc->buf.pool, val);
2411     }
2412   }
2413   if (size && *size) {
2414     W_L(" size=\"");
2415     W_V(size);
2416     W_L("\"");
2417   }
2418   if (name && *name) {
2419     W_L(" name=\"");
2420     W_V(name);
2421     W_L("\"");
2422   }
2423   if (multiple) {
2424     W_L(" multiple");
2425   }
2426   W_L(">");
2427   if (IS_CSS_ON(chtml40->entryp)) {
2428     s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
2429   }
2430   return chtml40->out;
2431 }
2432
2433
2434 /**
2435  * It is a handler who processes the SELECT tag.
2436  *
2437  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
2438  *                     destination is specified.
2439  * @param node   [i]   The SELECT tag node is specified.
2440  * @return The conversion result is returned.
2441  */
2442 static char *
2443 s_chtml40_end_select_tag(void *pdoc, Node *UNUSED(child))
2444 {
2445   chtml40_t    *chtml40 = GET_CHTML40(pdoc);
2446   Doc          *doc   = chtml40->doc;
2447
2448   W_L("</select>");
2449   if (IS_CSS_ON(chtml40->entryp)) {
2450     chxj_css_pop_prop_list(chtml40->css_prop_stack);
2451   }
2452   return chtml40->out;
2453 }
2454
2455
2456 /**
2457  * It is a handler who processes the OPTION tag.
2458  *
2459  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
2460  *                     destination is specified.
2461  * @param node   [i]   The OPTION tag node is specified.
2462  * @return The conversion result is returned.
2463  */
2464 static char *
2465 s_chtml40_start_option_tag(void *pdoc, Node *node)
2466 {
2467   Attr        *attr;
2468   chtml40_t   *chtml40;
2469   Doc         *doc;
2470   request_rec *r;
2471   char        *selected;
2472   char        *value;
2473   char        *attr_style = NULL;
2474
2475   chtml40    = GET_CHTML40(pdoc);
2476   doc        = chtml40->doc;
2477   r          = doc->r;
2478   selected   = NULL;
2479   value      = NULL;
2480
2481   W_L("<option");
2482   for (attr = qs_get_attr(doc,node);
2483        attr;
2484        attr = qs_get_next_attr(doc,attr)) {
2485     char *nm  = qs_get_attr_name(doc,attr);
2486     char *val = qs_get_attr_value(doc,attr);
2487     if (STRCASEEQ('s','S',"selected", nm)) {
2488       /*----------------------------------------------------------------------*/
2489       /* CHTML 1.0 version 2.0                                                */
2490       /*----------------------------------------------------------------------*/
2491       selected = apr_pstrdup(doc->buf.pool, val);
2492     }
2493     else if (STRCASEEQ('s','S',"style", nm) && val && *val) {
2494       /*----------------------------------------------------------------------*/
2495       /* CHTML 1.0 version 2.0                                                */
2496       /*----------------------------------------------------------------------*/
2497       attr_style = apr_pstrdup(doc->buf.pool, val);
2498     }
2499     else if (STRCASEEQ('v','V',"value", nm)) {
2500       /*----------------------------------------------------------------------*/
2501       /* CHTML 1.0 version 2.0                                                */
2502       /*----------------------------------------------------------------------*/
2503       value = apr_pstrdup(doc->buf.pool, val);
2504     }
2505   }
2506   if (value) {
2507     W_L(" value=\"");
2508     W_V(value);
2509     W_L("\"");
2510   }
2511   if (selected) {
2512     W_L(" selected");
2513   }
2514   W_L(">");
2515
2516   if (IS_CSS_ON(chtml40->entryp)) {
2517     s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
2518   }
2519
2520   return chtml40->out;
2521 }
2522
2523
2524 /**
2525  * It is a handler who processes the OPTION tag.
2526  *
2527  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
2528  *                     destination is specified.
2529  * @param node   [i]   The OPTION tag node is specified.
2530  * @return The conversion result is returned.
2531  */
2532 static char *
2533 s_chtml40_end_option_tag(void *pdoc, Node *UNUSED(child))
2534 {
2535   chtml40_t *chtml40 = GET_CHTML40(pdoc);
2536
2537   /* Don't close */
2538   if (IS_CSS_ON(chtml40->entryp)) {
2539     chxj_css_pop_prop_list(chtml40->css_prop_stack);
2540   }
2541
2542   return chtml40->out;
2543 }
2544
2545
2546 /**
2547  * It is a handler who processes the DIV tag.
2548  *
2549  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
2550  *                     destination is specified.
2551  * @param node   [i]   The DIV tag node is specified.
2552  * @return The conversion result is returned.
2553  */
2554 static char *
2555 s_chtml40_start_div_tag(void *pdoc, Node *node)
2556 {
2557   chtml40_t   *chtml40;
2558   Doc         *doc;
2559   request_rec *r;
2560   Attr        *attr;
2561   char        *attr_style             = NULL;
2562   char        *attr_align             = NULL;
2563   char        *attr_display           = NULL;
2564   char        *attr_decoration        = NULL;
2565   char        *attr_wap_marquee_style = NULL;
2566   char        *attr_wap_marquee_dir   = NULL;
2567   char        *attr_wap_marquee_loop  = NULL;
2568   char        *attr_color             = NULL;
2569   char        *attr_bgcolor           = NULL;
2570
2571   chtml40 = GET_CHTML40(pdoc);
2572   doc     = chtml40->doc;
2573   r       = doc->r;
2574
2575   for (attr = qs_get_attr(doc,node);
2576        attr;
2577        attr = qs_get_next_attr(doc,attr)) {
2578     char *nm  = qs_get_attr_name(doc,attr);
2579     char *val = qs_get_attr_value(doc,attr);
2580     if (STRCASEEQ('a','A', "align", nm)) {
2581       /*----------------------------------------------------------------------*/
2582       /* CHTML 1.0 (W3C version 3.2)                                          */
2583       /*----------------------------------------------------------------------*/
2584       if (val && (STRCASEEQ('l','L',"left",val) || STRCASEEQ('r','R',"right",val) || STRCASEEQ('c','C',"center",val))) {
2585         attr_align = apr_pstrdup(doc->buf.pool, val);
2586       }
2587     }
2588     else if (STRCASEEQ('s','S',"style",nm) && val && *val) {
2589       attr_style = apr_pstrdup(doc->buf.pool, val);
2590     }
2591   }
2592
2593   if (IS_CSS_ON(chtml40->entryp)) {
2594     css_prop_list_t *style = s_chtml40_nopush_and_get_now_style(pdoc, node, attr_style);
2595     if (style) {
2596       css_property_t *display_prop           = chxj_css_get_property_value(doc, style, "display");
2597       css_property_t *text_decoration_prop   = chxj_css_get_property_value(doc, style, "text-decoration");
2598       css_property_t *color_prop             = chxj_css_get_property_value(doc, style, "color");
2599       css_property_t *text_align_prop        = chxj_css_get_property_value(doc, style, "text-align");
2600       css_property_t *background_color_prop  = chxj_css_get_property_value(doc, style, "background-color");
2601       css_property_t *background_prop        = chxj_css_get_property_value(doc, style, "background");
2602
2603       css_property_t *cur;
2604       for (cur = display_prop->next; cur != display_prop; cur = cur->next) {
2605         if (strcasecmp("-wap-marquee", cur->value) == 0) {
2606           attr_display = apr_pstrdup(doc->pool, cur->value);
2607         }
2608       }
2609       for (cur = text_decoration_prop->next; cur != text_decoration_prop; cur = cur->next) {
2610         if (STRCASEEQ('b','B',"blink", cur->value)) {
2611           attr_decoration = apr_pstrdup(doc->pool, cur->value);
2612         }
2613       }
2614       for (cur = color_prop->next; cur != color_prop; cur = cur->next) {
2615         attr_color = apr_pstrdup(doc->pool, cur->value);
2616         attr_color = chxj_css_rgb_func_to_value(doc->pool, attr_color);
2617       }
2618       for (cur = background_color_prop->next; cur != background_color_prop; cur = cur->next) {
2619         attr_bgcolor = apr_pstrdup(doc->pool, cur->value);
2620         attr_bgcolor = chxj_css_rgb_func_to_value(doc->pool, attr_bgcolor);
2621       }
2622       for (cur = background_prop->next; cur != background_prop; cur = cur->next) {
2623         char *ss = strchr(cur->value, '#');
2624         if (!ss) {
2625           ss = strstr(cur->value, "rgb");
2626         }
2627         if (ss) {
2628           attr_bgcolor = apr_pstrdup(doc->pool, cur->value);
2629           attr_bgcolor = chxj_css_rgb_func_to_value(doc->pool, attr_bgcolor);
2630         }
2631       }
2632       for (cur = text_align_prop->next; cur != text_align_prop; cur = cur->next) {
2633         attr_align = apr_pstrdup(doc->pool, cur->value);
2634       }
2635       if (attr_display) {
2636         css_property_t *wap_marquee_style_prop = chxj_css_get_property_value(doc, style, "-wap-marquee-style");
2637         css_property_t *wap_marquee_dir_prop   = chxj_css_get_property_value(doc, style, "-wap-marquee-dir");
2638         css_property_t *wap_marquee_loop_prop  = chxj_css_get_property_value(doc, style, "-wap-marquee-loop");
2639         for (cur = wap_marquee_style_prop->next; cur != wap_marquee_style_prop; cur = cur->next) {
2640           if (STRCASEEQ('s','S',"scroll", cur->value) || STRCASEEQ('s','S',"slide",cur->value) || STRCASEEQ('a','A',"alternate",cur->value)) {
2641             attr_wap_marquee_style = apr_pstrdup(doc->pool, cur->value);
2642           }
2643         }
2644         for (cur = wap_marquee_dir_prop->next; cur != wap_marquee_dir_prop; cur = cur->next) {
2645           if (STRCASEEQ('l','L',"ltr",cur->value)) {
2646             attr_wap_marquee_dir = apr_pstrdup(doc->pool, "right");
2647           }
2648           else if (STRCASEEQ('r','R',"rtl",cur->value)) {
2649             attr_wap_marquee_dir = apr_pstrdup(doc->pool, "left");
2650           }
2651         }
2652         for (cur = wap_marquee_loop_prop->next; cur != wap_marquee_loop_prop; cur = cur->next) {
2653           if (STRCASEEQ('i','I',"infinite",cur->value)) {
2654             attr_wap_marquee_loop = apr_pstrdup(doc->pool, "16");
2655           }
2656           else {
2657             attr_wap_marquee_loop = apr_pstrdup(doc->pool, cur->value);
2658           }
2659         }
2660       }
2661     }
2662   }  
2663   chtml40_flags_t *flg = (chtml40_flags_t *)apr_palloc(doc->pool, sizeof(chtml40_flags_t));
2664   memset(flg, 0, sizeof(*flg));
2665   if (attr_align) {
2666     W_L("<div");
2667     W_L(" align=\"");
2668     W_V(attr_align);
2669     W_L("\"");
2670     W_L(">");
2671     flg->with_div_flag = 1;
2672   }
2673   else {
2674     W_L("<div>");
2675     flg->with_div_flag = 1;
2676   }
2677   if (attr_color) {
2678     if (attr_bgcolor && (STRCASEEQ('w','W',"white",attr_color) || STRCASEEQ('#','#',"#ffffff",attr_color))) {
2679       /* nothing */
2680     }
2681     else {
2682       W_L("<font color=\"");
2683       W_V(attr_color);
2684       W_L("\">");
2685       flg->with_font_flag = 1;
2686     }
2687   }
2688   if (attr_decoration) {
2689     W_L("<blink>");
2690     flg->with_blink_flag = 1;
2691   }
2692   if (attr_display) {
2693     W_L("<marquee");
2694     if (attr_wap_marquee_style) {
2695       W_L(" behavior=\"");
2696       W_V(attr_wap_marquee_style);
2697       W_L("\"");
2698     }
2699     if (attr_wap_marquee_dir) {
2700       W_L(" direction=\"");
2701       W_V(attr_wap_marquee_dir);
2702       W_L("\"");
2703     }
2704     if (attr_wap_marquee_loop) {
2705       W_L(" loop=\"");
2706       W_V(attr_wap_marquee_loop);
2707       W_L("\"");
2708     }
2709     W_L(">");
2710     flg->with_marquee_flag = 1;
2711   }
2712   node->userData = flg;
2713
2714   return chtml40->out;
2715 }
2716
2717
2718 /**
2719  * It is a handler who processes the DIV tag.
2720  *
2721  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
2722  *                     destination is specified.
2723  * @param node   [i]   The DIV tag node is specified.
2724  * @return The conversion result is returned.
2725  */
2726 static char *
2727 s_chtml40_end_div_tag(void *pdoc, Node *node)
2728 {
2729   chtml40_t    *chtml40 = GET_CHTML40(pdoc);
2730   Doc          *doc     = chtml40->doc;
2731
2732   chtml40_flags_t *flg = node->userData;
2733   if (flg && flg->with_marquee_flag) {
2734     W_L("</marquee>");
2735   }
2736   if (flg && flg->with_blink_flag) {
2737     W_L("</blink>");
2738   }
2739   if (flg && flg->with_font_flag) {
2740     W_L("</font>");
2741   }
2742   if (flg && flg->with_div_flag) {
2743     W_L("</div>");
2744   }
2745   if (IS_CSS_ON(chtml40->entryp)) {
2746     chxj_css_pop_prop_list(chtml40->css_prop_stack);
2747   }
2748   node->userData = NULL;
2749
2750   return chtml40->out;
2751 }
2752
2753
2754 /**
2755  * It is a handler who processes the UL tag.
2756  *
2757  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
2758  *                     destination is specified.
2759  * @param node   [i]   The UL tag node is specified.
2760  * @return The conversion result is returned.
2761  */
2762 static char *
2763 s_chtml40_start_ul_tag(void *pdoc, Node *node)
2764 {
2765   chtml40_t   *chtml40 = GET_CHTML40(pdoc);
2766   Doc         *doc     = chtml40->doc;
2767   Attr        *attr;
2768   char        *attr_type = NULL;
2769   char        *attr_style = NULL;
2770   /*--------------------------------------------------------------------------*/
2771   /* Get Attributes                                                           */
2772   /*--------------------------------------------------------------------------*/
2773   for (attr = qs_get_attr(doc,node);
2774        attr;
2775        attr = qs_get_next_attr(doc,attr)) {
2776     char *name   = qs_get_attr_name(doc,attr);
2777     char *value  = qs_get_attr_value(doc,attr);
2778     if (STRCASEEQ('t','T',"type",name)) {
2779       if (value && (STRCASEEQ('d','D',"disc",value) || STRCASEEQ('c','C',"circle",value) || STRCASEEQ('s','S',"square",value))) {
2780         attr_type = value;
2781       }
2782     }
2783     else if (value && *value && STRCASEEQ('s','S',"style", name)) {
2784       attr_style = value;
2785     }
2786   }
2787   if (IS_CSS_ON(chtml40->entryp)) {
2788     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
2789     if (style) {
2790       css_property_t *list_style_type_prop = chxj_css_get_property_value(doc, style, "list-style-type");
2791       css_property_t *cur;
2792       for (cur = list_style_type_prop->next; cur != list_style_type_prop; cur = cur->next) {
2793         if (STRCASEEQ('d','D',"disc",cur->value)) {
2794           attr_type = apr_pstrdup(doc->pool, "disc");
2795         }
2796         else if (STRCASEEQ('c','C',"circle",cur->value)) {
2797           attr_type = apr_pstrdup(doc->pool, "circle");
2798         }
2799         else if (STRCASEEQ('s','S',"square",cur->value)) {
2800           attr_type = apr_pstrdup(doc->pool, "square");
2801         }
2802       }
2803     }
2804   }
2805   W_L("<ul");
2806   if (attr_type) {
2807     W_L(" type=\"");
2808     W_V(attr_type);
2809     W_L("\"");
2810   }
2811   W_L(">");
2812
2813   return chtml40->out;
2814 }
2815
2816
2817 /**
2818  * It is a handler who processes the UL tag.
2819  *
2820  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
2821  *                     destination is specified.
2822  * @param node   [i]   The UL tag node is specified.
2823  * @return The conversion result is returned.
2824  */
2825 static char *
2826 s_chtml40_end_ul_tag(void *pdoc, Node *UNUSED(child)) 
2827 {
2828   chtml40_t     *chtml40 = GET_CHTML40(pdoc);
2829   Doc           *doc     = chtml40->doc;
2830
2831   W_L("</ul>");
2832   if (IS_CSS_ON(chtml40->entryp)) {
2833     chxj_css_pop_prop_list(chtml40->css_prop_stack);
2834   }
2835
2836   return chtml40->out;
2837 }
2838
2839
2840 /**
2841  * It is a handler who processes the PRE tag.
2842  *
2843  * @param pdoc  [i/o] The pointer to the XHTML structure at the output
2844  *                     destination is specified.
2845  * @param node   [i]   The PRE tag node is specified.
2846  * @return The conversion result is returned.
2847  */
2848 static char *
2849 s_chtml40_start_pre_tag(void *pdoc, Node *node)
2850 {
2851   chtml40_t *chtml40 = GET_CHTML40(pdoc);
2852   Doc       *doc     = chtml40->doc;
2853   Attr      *attr;
2854   char      *attr_style = NULL;
2855
2856   for (attr = qs_get_attr(doc,node);
2857        attr;
2858        attr = qs_get_next_attr(doc,attr)) {
2859     char *nm  = qs_get_attr_name(doc,attr);
2860     char *val = qs_get_attr_value(doc,attr);
2861     if (val && STRCASEEQ('s','S',"style", nm)) {
2862       attr_style = val;
2863     }
2864   }
2865
2866   if (IS_CSS_ON(chtml40->entryp)) {
2867     s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
2868   }
2869
2870   chtml40->pre_flag++;
2871   W_L("<pre>");
2872
2873   return chtml40->out;
2874 }
2875
2876
2877 /**
2878  * It is a handler who processes the PRE tag.
2879  *
2880  * @param pdoc  [i/o] The pointer to the XHTML structure at the output
2881  *                     destination is specified.
2882  * @param node   [i]   The PRE tag node is specified.
2883  * @return The conversion result is returned.
2884  */
2885 static char *
2886 s_chtml40_end_pre_tag(void *pdoc, Node *UNUSED(child)) 
2887 {
2888   chtml40_t     *chtml40 = GET_CHTML40(pdoc);
2889   Doc           *doc     = chtml40->doc;
2890
2891   W_L("</pre>");
2892   chtml40->pre_flag--;
2893   if (IS_CSS_ON(chtml40->entryp)) {
2894     chxj_css_pop_prop_list(chtml40->css_prop_stack);
2895   }
2896
2897   return chtml40->out;
2898 }
2899
2900
2901 /**
2902  * It is a handler who processes the P tag.
2903  *
2904  * @param pdoc  [i/o] The pointer to the XHTML structure at the output
2905  *                     destination is specified.
2906  * @param node   [i]   The P tag node is specified.
2907  * @return The conversion result is returned.
2908  */
2909 static char *
2910 s_chtml40_start_p_tag(void *pdoc, Node *node) 
2911 {
2912   chtml40_t   *chtml40;
2913   Doc         *doc;
2914   request_rec *r;
2915   Attr        *attr;
2916   char        *attr_align = NULL;
2917   char        *attr_style = NULL;
2918   char        *attr_color = NULL;
2919   char        *attr_blink = NULL;
2920
2921   chtml40 = GET_CHTML40(pdoc);
2922   doc     = chtml40->doc;
2923   r       = doc->r;
2924
2925   for (attr = qs_get_attr(doc,node);
2926        attr;
2927        attr = qs_get_next_attr(doc,attr)) {
2928     char *nm  = qs_get_attr_name(doc,attr);
2929     char *val = qs_get_attr_value(doc,attr);
2930     if (STRCASEEQ('a','A',"align", nm)) {
2931       /*----------------------------------------------------------------------*/
2932       /* CHTML 1.0 (W3C version 3.2)                                          */
2933       /*----------------------------------------------------------------------*/
2934       if (val && (STRCASEEQ('l','L',"left",val) || STRCASEEQ('r','R',"right",val) || STRCASEEQ('c','C',"center",val))) {
2935         attr_align = apr_pstrdup(doc->buf.pool, val);
2936         break;
2937       }
2938     }
2939     else if (STRCASEEQ('s','S',"style", nm) && val && *val) {
2940       attr_style = apr_pstrdup(doc->buf.pool, val);
2941     }
2942   }
2943   if (IS_CSS_ON(chtml40->entryp)) {
2944     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
2945     if (style) {
2946       css_property_t *text_align_prop = chxj_css_get_property_value(doc, style, "text-align");
2947       css_property_t *color_prop      = chxj_css_get_property_value(doc, style, "color");
2948       css_property_t *text_deco_prop  = chxj_css_get_property_value(doc, style, "text-decoration");
2949       css_property_t *cur;
2950       for (cur = text_align_prop->next; cur != text_align_prop; cur = cur->next) {
2951         if (STRCASEEQ('l','L',"left",cur->value)) {
2952           attr_align = apr_pstrdup(doc->pool, "left");
2953         }
2954         else if (STRCASEEQ('c','C',"center",cur->value)) {
2955           attr_align = apr_pstrdup(doc->pool, "center");
2956         }
2957         else if (STRCASEEQ('r','R',"right",cur->value)) {
2958           attr_align = apr_pstrdup(doc->pool, "right");
2959         }
2960       }
2961       for (cur = color_prop->next; cur != color_prop; cur = cur->next) {
2962         if (cur->value && *cur->value) {
2963           attr_color = apr_pstrdup(doc->pool, cur->value);
2964         }
2965       }
2966       for (cur = text_deco_prop->next; cur != text_deco_prop; cur = cur->next) {
2967         if (cur->value && *cur->value && STRCASEEQ('b','B',"blink",cur->value)) {
2968           attr_blink = apr_pstrdup(doc->pool, cur->value);
2969         }
2970       }
2971     }
2972   }
2973   W_L("<p");
2974   if (attr_align) {
2975     W_L(" align=\"");
2976     W_V(attr_align);
2977     W_L("\"");
2978   }
2979   W_L(">");
2980
2981   chtml40_flags_t *flg = (chtml40_flags_t *)apr_palloc(doc->pool, sizeof(chtml40_flags_t));
2982   memset(flg, 0, sizeof(*flg));
2983   if (attr_color) {
2984     attr_color = chxj_css_rgb_func_to_value(doc->pool, attr_color);
2985     W_L("<font color=\"");
2986     W_V(attr_color);
2987     W_L("\">");
2988     flg->with_font_flag = 1;
2989   }
2990   if (attr_blink) {
2991     W_L("<blink>");
2992     flg->with_blink_flag = 1;
2993   }
2994   node->userData = (void *)flg;
2995
2996   return chtml40->out;
2997 }
2998
2999
3000 /**
3001  * It is a handler who processes the P tag.
3002  *
3003  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3004  *                     destination is specified.
3005  * @param node   [i]   The P tag node is specified.
3006  * @return The conversion result is returned.
3007  */
3008 static char *
3009 s_chtml40_end_p_tag(void *pdoc, Node *node)
3010 {
3011   chtml40_t   *chtml40;
3012   Doc         *doc;
3013
3014   chtml40 = GET_CHTML40(pdoc);
3015   doc     = chtml40->doc;
3016
3017   chtml40_flags_t *flg = (chtml40_flags_t *)node->userData;
3018   if (flg->with_font_flag) {
3019     W_L("</font>");
3020   }
3021   if (flg->with_blink_flag) {
3022     W_L("</blink>");
3023   }
3024   W_L("</p>");
3025   if (IS_CSS_ON(chtml40->entryp)) {
3026     chxj_css_pop_prop_list(chtml40->css_prop_stack);
3027   }
3028
3029   return chtml40->out;
3030 }
3031
3032
3033 /**
3034  * It is a handler who processes the OL tag.
3035  *
3036  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3037  *                     destination is specified.
3038  * @param node   [i]   The OL tag node is specified.
3039  * @return The conversion result is returned.
3040  */
3041 static char *
3042 s_chtml40_start_ol_tag(void *pdoc, Node *node)
3043 {
3044   chtml40_t   *chtml40;
3045   Doc         *doc;
3046   request_rec *r;
3047   Attr        *attr;
3048   char        *attr_style = NULL;
3049   char        *attr_start = NULL;
3050   char        *attr_type = NULL;
3051
3052   chtml40 = GET_CHTML40(pdoc);
3053   doc     = chtml40->doc;
3054   r       = doc->r;
3055
3056   /*--------------------------------------------------------------------------*/
3057   /* Get Attributes                                                           */
3058   /*--------------------------------------------------------------------------*/
3059   for (attr = qs_get_attr(doc,node);
3060        attr;
3061        attr = qs_get_next_attr(doc,attr)) {
3062     char *name = qs_get_attr_name(doc,attr);
3063     char *value = qs_get_attr_value(doc,attr);
3064     if (STRCASEEQ('t','T',"type",name) && value && (*value == '1' || *value == 'a' || *value == 'A')) {
3065       attr_type = value;
3066     }
3067     else if (STRCASEEQ('s','S',"start",name) && value && *value) {
3068       attr_start = value;
3069     }
3070     else if (STRCASEEQ('s','S',"style", name) && value && *value) {
3071       attr_style = value;
3072     }
3073   }
3074   if (IS_CSS_ON(chtml40->entryp)) {
3075     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
3076     if (style) {
3077       css_property_t *list_style_type_prop = chxj_css_get_property_value(doc, style, "list-style-type");
3078       css_property_t *cur;
3079       for (cur = list_style_type_prop->next; cur != list_style_type_prop; cur = cur->next) {
3080         if (STRCASEEQ('d','D',"decimal", cur->value)) {
3081           attr_type = apr_pstrdup(doc->pool, "1");
3082         }
3083         else if (STRCASEEQ('u','U',"upper-alpha", cur->value)) {
3084           attr_type = apr_pstrdup(doc->pool, "A");
3085         }
3086         else if (STRCASEEQ('l','L',"lower-alpha", cur->value)) {
3087           attr_type = apr_pstrdup(doc->pool, "a");
3088         }
3089       }
3090     }
3091   }
3092   W_L("<ol");
3093   if (attr_type) {
3094     W_L(" type=\"");
3095     W_V(attr_type);
3096     W_L("\"");
3097   }
3098   if (attr_start) {
3099     W_L(" start=\"");
3100     W_V(attr_start);
3101     W_L("\"");
3102   }
3103   W_L(">");
3104
3105   return chtml40->out;
3106 }
3107
3108
3109 /**
3110  * It is a handler who processes the OL tag.
3111  *
3112  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3113  *                     destination is specified.
3114  * @param node   [i]   The OL tag node is specified.
3115  * @return The conversion result is returned.
3116  */
3117 static char *
3118 s_chtml40_end_ol_tag(void *pdoc, Node *UNUSED(node)) 
3119 {
3120   chtml40_t *chtml40 = GET_CHTML40(pdoc);
3121   Doc       *doc     = chtml40->doc;
3122
3123   W_L("</ol>");
3124   if (IS_CSS_ON(chtml40->entryp)) {
3125     chxj_css_pop_prop_list(chtml40->css_prop_stack);
3126   }
3127
3128   return chtml40->out;
3129 }
3130
3131
3132 /**
3133  * It is a handler who processes the LI tag.
3134  *
3135  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3136  *                     destination is specified.
3137  * @param node   [i]   The LI tag node is specified.
3138  * @return The conversion result is returned.
3139  */
3140 static char *
3141 s_chtml40_start_li_tag(void *pdoc, Node *node) 
3142 {
3143   chtml40_t   *chtml40 = GET_CHTML40(pdoc);
3144   Doc         *doc     = chtml40->doc;
3145   Attr        *attr;
3146   char        *attr_type = NULL;
3147   char        *attr_value = NULL;
3148   char        *attr_style = NULL;
3149
3150   /*--------------------------------------------------------------------------*/
3151   /* Get Attributes                                                           */
3152   /*--------------------------------------------------------------------------*/
3153   for (attr = qs_get_attr(doc,node);
3154        attr;
3155        attr = qs_get_next_attr(doc,attr)) {
3156     char *name  = qs_get_attr_name(doc,attr);
3157     char *value = qs_get_attr_value(doc,attr);
3158     if (STRCASEEQ('t','T',"type",name)) {
3159       if (value && (*value == '1' || *value == 'a' || *value == 'A' || STRCASEEQ('d','D',"disc",value) || STRCASEEQ('s','S',"square",value) || STRCASEEQ('c','C',"circle",value))) {
3160         attr_type = value;
3161       }
3162     }
3163     else if (STRCASEEQ('v','V',"value", name) && value && *value) {
3164       attr_value = value;
3165     }
3166     else if (STRCASEEQ('s','S',"style", name) && value && *value) {
3167       attr_style = value;
3168     }
3169   }
3170   if (IS_CSS_ON(chtml40->entryp)) {
3171     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
3172     if (style) {
3173       css_property_t *list_style_type_prop = chxj_css_get_property_value(doc, style, "list-style-type");
3174       css_property_t *cur;
3175       for (cur = list_style_type_prop->next; cur != list_style_type_prop; cur = cur->next) {
3176         if (STRCASEEQ('d','D',"decimal", cur->value)) {
3177           attr_type = apr_pstrdup(doc->pool, "1");
3178         }
3179         else if (STRCASEEQ('u','U',"upper-alpha", cur->value)) {
3180           attr_type = apr_pstrdup(doc->pool, "A");
3181         }
3182         else if (STRCASEEQ('l','L',"lower-alpha", cur->value)) {
3183           attr_type = apr_pstrdup(doc->pool, "a");
3184         }
3185         else if (STRCASEEQ('d','D',"disc", cur->value)) {
3186           attr_type = apr_pstrdup(doc->pool, "disc");
3187         }
3188         else if (STRCASEEQ('s','S',"square", cur->value)) {
3189           attr_type = apr_pstrdup(doc->pool, "square");
3190         }
3191         else if (STRCASEEQ('c','C',"circle", cur->value)) {
3192           attr_type = apr_pstrdup(doc->pool, "circle");
3193         }
3194       }
3195     }
3196   }
3197
3198   W_L("<li");
3199   if (attr_type) {
3200     W_L(" type=\"");
3201     W_V(attr_type);
3202     W_L("\"");
3203   }
3204   if (attr_value) {
3205     W_L(" value=\"");
3206     W_V(attr_value);
3207     W_L("\"");
3208   }
3209   W_L(">");
3210   return chtml40->out;
3211 }
3212
3213
3214 /**
3215  * It is a handler who processes the LI tag.
3216  *
3217  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3218  *                     destination is specified.
3219  * @param node   [i]   The LI tag node is specified.
3220  * @return The conversion result is returned.
3221  */
3222 static char *
3223 s_chtml40_end_li_tag(void *pdoc, Node *UNUSED(child)) 
3224 {
3225   chtml40_t *chtml40 = GET_CHTML40(pdoc);
3226
3227   if (IS_CSS_ON(chtml40->entryp)) {
3228     chxj_css_pop_prop_list(chtml40->css_prop_stack);
3229   }
3230   return chtml40->out;
3231 }
3232
3233
3234 /**
3235  * It is a handler who processes the H1 tag.
3236  *
3237  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3238  *                     destination is specified.
3239  * @param node   [i]   The H1 tag node is specified.
3240  * @return The conversion result is returned.
3241  */
3242 static char *
3243 s_chtml40_start_h1_tag(void *pdoc, Node *node)
3244 {
3245   chtml40_t   *chtml40;
3246   Doc         *doc;
3247   request_rec *r;
3248   Attr        *attr;
3249   char        *attr_style = NULL;
3250   char        *attr_align = NULL;
3251
3252   chtml40 = GET_CHTML40(pdoc);
3253   doc     = chtml40->doc;
3254   r       = doc->r;
3255
3256   for (attr = qs_get_attr(doc,node);
3257        attr;
3258        attr = qs_get_next_attr(doc,attr)) {
3259     char *name  = qs_get_attr_name(doc,attr);
3260     char *value = qs_get_attr_value(doc,attr);
3261     if (STRCASEEQ('a','A',"align", name)) {
3262       if (value && (STRCASEEQ('l','L',"left",value) || STRCASEEQ('r','R',"right",value) || STRCASEEQ('c','C',"center",value))) {
3263         attr_align = value;
3264       }
3265     }
3266     else if (STRCASEEQ('s','S',"style",name) && value && *value) {
3267       attr_style = value;
3268     }
3269   }
3270   if (IS_CSS_ON(chtml40->entryp)) {
3271     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
3272     if (style) {
3273       css_property_t *list_style_type_prop = chxj_css_get_property_value(doc, style, "text-align");
3274       css_property_t *cur;
3275       for (cur = list_style_type_prop->next; cur != list_style_type_prop; cur = cur->next) {
3276         if (STRCASEEQ('l','L',"left", cur->value)) {
3277           attr_align = apr_pstrdup(doc->pool, "left");
3278         }
3279         else if (STRCASEEQ('c','C',"center",cur->value)) {
3280           attr_align = apr_pstrdup(doc->pool, "center");
3281         }
3282         else if (STRCASEEQ('r','R',"right",cur->value)) {
3283           attr_align = apr_pstrdup(doc->pool, "right");
3284         }
3285       }
3286     }
3287   }
3288   W_L("<h1");
3289   if (attr_align) {
3290     W_L(" align=\"");
3291     W_V(attr_align);
3292     W_L("\"");
3293   }
3294   W_L(">");
3295
3296   return chtml40->out;
3297 }
3298
3299
3300 /**
3301  * It is a handler who processes the H1 tag.
3302  *
3303  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3304  *                     destination is specified.
3305  * @param node   [i]   The H1 tag node is specified.
3306  * @return The conversion result is returned.
3307  */
3308 static char *
3309 s_chtml40_end_h1_tag(void *pdoc, Node *UNUSED(child)) 
3310 {
3311   chtml40_t   *chtml40;
3312   Doc         *doc;
3313
3314   chtml40 = GET_CHTML40(pdoc);
3315   doc     = chtml40->doc;
3316
3317   W_L("</h1>");
3318   if (IS_CSS_ON(chtml40->entryp)) {
3319     chxj_css_pop_prop_list(chtml40->css_prop_stack);
3320   }
3321
3322   return chtml40->out;
3323 }
3324
3325
3326 /**
3327  * It is a handler who processes the H2 tag.
3328  *
3329  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3330  *                     destination is specified.
3331  * @param node   [i]   The H2 tag node is specified.
3332  * @return The conversion result is returned.
3333  */
3334 static char *
3335 s_chtml40_start_h2_tag(void *pdoc, Node *node)
3336 {
3337   chtml40_t   *chtml40;
3338   Doc         *doc;
3339   request_rec *r;
3340   Attr        *attr;
3341   char        *attr_style = NULL;
3342   char        *attr_align = NULL;
3343
3344   chtml40 = GET_CHTML40(pdoc);
3345   doc     = chtml40->doc;
3346   r       = doc->r;
3347
3348   for (attr = qs_get_attr(doc,node);
3349        attr;
3350        attr = qs_get_next_attr(doc,attr)) {
3351     char *name  = qs_get_attr_name(doc,attr);
3352     char *value = qs_get_attr_value(doc,attr);
3353     if (STRCASEEQ('a','A',"align", name)) {
3354       if (value && (STRCASEEQ('l','L',"left",value) || STRCASEEQ('r','R',"right",value) || STRCASEEQ('c','C',"center",value))) {
3355         attr_align = value;
3356       }
3357     }
3358     else if (STRCASEEQ('s','S',"style",name) && value && *value) {
3359       attr_style = value;
3360     }
3361   }
3362   if (IS_CSS_ON(chtml40->entryp)) {
3363     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
3364     if (style) {
3365       css_property_t *list_style_type_prop = chxj_css_get_property_value(doc, style, "text-align");
3366       css_property_t *cur;
3367       for (cur = list_style_type_prop->next; cur != list_style_type_prop; cur = cur->next) {
3368         if (STRCASEEQ('l','L',"left", cur->value)) {
3369           attr_align = apr_pstrdup(doc->pool, "left");
3370         }
3371         else if (STRCASEEQ('c','C',"center",cur->value)) {
3372           attr_align = apr_pstrdup(doc->pool, "center");
3373         }
3374         else if (STRCASEEQ('r','R',"right",cur->value)) {
3375           attr_align = apr_pstrdup(doc->pool, "right");
3376         }
3377       }
3378     }
3379   }
3380   W_L("<h2");
3381   if (attr_align) {
3382     W_L(" align=\"");
3383     W_V(attr_align);
3384     W_L("\"");
3385   }
3386   W_L(">");
3387
3388   return chtml40->out;
3389 }
3390
3391
3392 /**
3393  * It is a handler who processes the H2 tag.
3394  *
3395  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3396  *                     destination is specified.
3397  * @param node   [i]   The H2 tag node is specified.
3398  * @return The conversion result is returned.
3399  */
3400 static char *
3401 s_chtml40_end_h2_tag(void *pdoc, Node *UNUSED(child)) 
3402 {
3403   chtml40_t   *chtml40 = GET_CHTML40(pdoc);
3404   Doc         *doc     = chtml40->doc;
3405
3406   W_L("</h2>");
3407   if (IS_CSS_ON(chtml40->entryp)) {
3408     chxj_css_pop_prop_list(chtml40->css_prop_stack);
3409   }
3410
3411   return chtml40->out;
3412 }
3413
3414
3415 /**
3416  * It is a handler who processes the H3 tag.
3417  *
3418  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3419  *                     destination is specified.
3420  * @param node   [i]   The H3 tag node is specified.
3421  * @return The conversion result is returned.
3422  */
3423 static char *
3424 s_chtml40_start_h3_tag(void *pdoc, Node *node)
3425 {
3426   chtml40_t   *chtml40;
3427   Doc         *doc;
3428   request_rec *r;
3429   Attr        *attr;
3430   char        *attr_style = NULL;
3431   char        *attr_align = NULL;
3432
3433   chtml40 = GET_CHTML40(pdoc);
3434   doc     = chtml40->doc;
3435   r       = doc->r;
3436
3437   for (attr = qs_get_attr(doc,node);
3438        attr;
3439        attr = qs_get_next_attr(doc,attr)) {
3440     char *name  = qs_get_attr_name(doc,attr);
3441     char *value = qs_get_attr_value(doc,attr);
3442     if (STRCASEEQ('a','A',"align", name)) {
3443       if (value && (STRCASEEQ('l','L',"left",value) || STRCASEEQ('r','R',"right",value) || STRCASEEQ('c','C',"center",value))) {
3444         attr_align = value;
3445       }
3446     }
3447     else if (STRCASEEQ('s','S',"style",name) && value && *value) {
3448       attr_style = value;
3449     }
3450   }
3451   if (IS_CSS_ON(chtml40->entryp)) {
3452     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
3453     if (style) {
3454       css_property_t *list_style_type_prop = chxj_css_get_property_value(doc, style, "text-align");
3455       css_property_t *cur;
3456       for (cur = list_style_type_prop->next; cur != list_style_type_prop; cur = cur->next) {
3457         if (STRCASEEQ('l','L',"left", cur->value)) {
3458           attr_align = apr_pstrdup(doc->pool, "left");
3459         }
3460         else if (STRCASEEQ('c','C',"center",cur->value)) {
3461           attr_align = apr_pstrdup(doc->pool, "center");
3462         }
3463         else if (STRCASEEQ('r','R',"right",cur->value)) {
3464           attr_align = apr_pstrdup(doc->pool, "right");
3465         }
3466       }
3467     }
3468   }
3469   W_L("<h3");
3470   if (attr_align) {
3471     W_L(" align=\"");
3472     W_V(attr_align);
3473     W_L("\"");
3474   }
3475   W_L(">");
3476
3477   return chtml40->out;
3478 }
3479
3480
3481 /**
3482  * It is a handler who processes the H3 tag.
3483  *
3484  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3485  *                     destination is specified.
3486  * @param node   [i]   The H3 tag node is specified.
3487  * @return The conversion result is returned.
3488  */
3489 static char *
3490 s_chtml40_end_h3_tag(void *pdoc, Node *UNUSED(child))
3491 {
3492   chtml40_t *chtml40 = GET_CHTML40(pdoc);
3493   Doc       *doc   = chtml40->doc;
3494
3495   W_L("</h3>");
3496   if (IS_CSS_ON(chtml40->entryp)) {
3497     chxj_css_pop_prop_list(chtml40->css_prop_stack);
3498   }
3499
3500   return chtml40->out;
3501 }
3502
3503
3504 /**
3505  * It is a handler who processes the H4 tag.
3506  *
3507  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3508  *                     destination is specified.
3509  * @param node   [i]   The H4 tag node is specified.
3510  * @return The conversion result is returned.
3511  */
3512 static char *
3513 s_chtml40_start_h4_tag(void *pdoc, Node *node)
3514 {
3515   chtml40_t   *chtml40;
3516   Doc         *doc;
3517   request_rec *r;
3518   Attr        *attr;
3519   char        *attr_style = NULL;
3520   char        *attr_align = NULL;
3521
3522   chtml40 = GET_CHTML40(pdoc);
3523   doc     = chtml40->doc;
3524   r       = doc->r;
3525
3526   for (attr = qs_get_attr(doc,node);
3527        attr;
3528        attr = qs_get_next_attr(doc,attr)) {
3529     char *name  = qs_get_attr_name(doc,attr);
3530     char *value = qs_get_attr_value(doc,attr);
3531     if (STRCASEEQ('a','A',"align", name)) {
3532       if (value && (STRCASEEQ('l','L',"left",value) || STRCASEEQ('r','R',"right",value) || STRCASEEQ('c','C',"center",value))) {
3533         attr_align = value;
3534       }
3535     }
3536     else if (STRCASEEQ('s','S',"style",name) && value && *value) {
3537       attr_style = value;
3538     }
3539   }
3540   if (IS_CSS_ON(chtml40->entryp)) {
3541     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
3542     if (style) {
3543       css_property_t *list_style_type_prop = chxj_css_get_property_value(doc, style, "text-align");
3544       css_property_t *cur;
3545       for (cur = list_style_type_prop->next; cur != list_style_type_prop; cur = cur->next) {
3546         if (STRCASEEQ('l','L',"left", cur->value)) {
3547           attr_align = apr_pstrdup(doc->pool, "left");
3548         }
3549         else if (STRCASEEQ('c','C',"center",cur->value)) {
3550           attr_align = apr_pstrdup(doc->pool, "center");
3551         }
3552         else if (STRCASEEQ('r','R',"right",cur->value)) {
3553           attr_align = apr_pstrdup(doc->pool, "right");
3554         }
3555       }
3556     }
3557   }
3558   W_L("<h4");
3559   if (attr_align) {
3560     W_L(" align=\"");
3561     W_V(attr_align);
3562     W_L("\"");
3563   }
3564   W_L(">");
3565
3566   return chtml40->out;
3567 }
3568
3569
3570 /**
3571  * It is a handler who processes the H4 tag.
3572  *
3573  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3574  *                     destination is specified.
3575  * @param node   [i]   The H4 tag node is specified.
3576  * @return The conversion result is returned.
3577  */
3578 static char *
3579 s_chtml40_end_h4_tag(void *pdoc, Node *UNUSED(child)) 
3580 {
3581   chtml40_t *chtml40 = GET_CHTML40(pdoc);
3582   Doc       *doc     = chtml40->doc;
3583
3584   W_L("</h4>");
3585   if (IS_CSS_ON(chtml40->entryp)) {
3586     chxj_css_pop_prop_list(chtml40->css_prop_stack);
3587   }
3588
3589   return chtml40->out;
3590 }
3591
3592
3593 /**
3594  * It is a handler who processes the H5 tag.
3595  *
3596  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3597  *                     destination is specified.
3598  * @param node   [i]   The H5 tag node is specified.
3599  * @return The conversion result is returned.
3600  */
3601 static char *
3602 s_chtml40_start_h5_tag(void *pdoc, Node *node)
3603 {
3604   chtml40_t   *chtml40;
3605   Doc         *doc;
3606   request_rec *r;
3607   Attr        *attr;
3608   char        *attr_style = NULL;
3609   char        *attr_align = NULL;
3610
3611   chtml40 = GET_CHTML40(pdoc);
3612   doc     = chtml40->doc;
3613   r       = doc->r;
3614
3615   for (attr = qs_get_attr(doc,node);
3616        attr;
3617        attr = qs_get_next_attr(doc,attr)) {
3618     char *name  = qs_get_attr_name(doc,attr);
3619     char *value = qs_get_attr_value(doc,attr);
3620     if (STRCASEEQ('a','A',"align", name)) {
3621       if (value && (STRCASEEQ('l','L',"left",value) || STRCASEEQ('r','R',"right",value) || STRCASEEQ('c','C',"center",value))) {
3622         attr_align = value;
3623       }
3624     }
3625     else if (STRCASEEQ('s','S',"style",name) && value && *value) {
3626       attr_style = value;
3627     }
3628   }
3629   if (IS_CSS_ON(chtml40->entryp)) {
3630     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
3631     if (style) {
3632       css_property_t *list_style_type_prop = chxj_css_get_property_value(doc, style, "text-align");
3633       css_property_t *cur;
3634       for (cur = list_style_type_prop->next; cur != list_style_type_prop; cur = cur->next) {
3635         if (STRCASEEQ('l','L',"left", cur->value)) {
3636           attr_align = apr_pstrdup(doc->pool, "left");
3637         }
3638         else if (STRCASEEQ('c','C',"center",cur->value)) {
3639           attr_align = apr_pstrdup(doc->pool, "center");
3640         }
3641         else if (STRCASEEQ('r','R',"right",cur->value)) {
3642           attr_align = apr_pstrdup(doc->pool, "right");
3643         }
3644       }
3645     }
3646   }
3647   W_L("<h5");
3648   if (attr_align) {
3649     W_L(" align=\"");
3650     W_V(attr_align);
3651     W_L("\"");
3652   }
3653   W_L(">");
3654
3655   return chtml40->out;
3656 }
3657
3658
3659 /**
3660  * It is a handler who processes the H5 tag.
3661  *
3662  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3663  *                     destination is specified.
3664  * @param node   [i]   The H5 tag node is specified.
3665  * @return The conversion result is returned.
3666  */
3667 static char *
3668 s_chtml40_end_h5_tag(void *pdoc, Node *UNUSED(child)) 
3669 {
3670   chtml40_t *chtml40 = GET_CHTML40(pdoc);
3671   Doc       *doc     = chtml40->doc;
3672
3673   W_L("</h5>");
3674   if (IS_CSS_ON(chtml40->entryp)) {
3675     chxj_css_pop_prop_list(chtml40->css_prop_stack);
3676   }
3677
3678   return chtml40->out;
3679 }
3680
3681
3682 /**
3683  * It is a handler who processes the H6 tag.
3684  *
3685  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3686  *                     destination is specified.
3687  * @param node   [i]   The H6 tag node is specified.
3688  * @return The conversion result is returned.
3689  */
3690 static char *
3691 s_chtml40_start_h6_tag(void *pdoc, Node *node)
3692 {
3693   chtml40_t   *chtml40;
3694   Doc         *doc;
3695   request_rec *r;
3696   Attr        *attr;
3697   char        *attr_style = NULL;
3698   char        *attr_align = NULL;
3699
3700   chtml40 = GET_CHTML40(pdoc);
3701   doc     = chtml40->doc;
3702   r       = doc->r;
3703
3704   for (attr = qs_get_attr(doc,node);
3705        attr;
3706        attr = qs_get_next_attr(doc,attr)) {
3707     char *name  = qs_get_attr_name(doc,attr);
3708     char *value = qs_get_attr_value(doc,attr);
3709     if (STRCASEEQ('a','A',"align", name)) {
3710       if (value && (STRCASEEQ('l','L',"left",value) || STRCASEEQ('r','R',"right",value) || STRCASEEQ('c','C',"center",value))) {
3711         attr_align = value;
3712       }
3713     }
3714     else if (STRCASEEQ('s','S',"style",name) && value && *value) {
3715       attr_style = value;
3716     }
3717   }
3718   if (IS_CSS_ON(chtml40->entryp)) {
3719     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
3720     if (style) {
3721       css_property_t *list_style_type_prop = chxj_css_get_property_value(doc, style, "text-align");
3722       css_property_t *cur;
3723       for (cur = list_style_type_prop->next; cur != list_style_type_prop; cur = cur->next) {
3724         if (STRCASEEQ('l','L',"left", cur->value)) {
3725           attr_align = apr_pstrdup(doc->pool, "left");
3726         }
3727         else if (STRCASEEQ('c','C',"center",cur->value)) {
3728           attr_align = apr_pstrdup(doc->pool, "center");
3729         }
3730         else if (STRCASEEQ('r','R',"right",cur->value)) {
3731           attr_align = apr_pstrdup(doc->pool, "right");
3732         }
3733       }
3734     }
3735   }
3736   W_L("<h6");
3737   if (attr_align) {
3738     W_L(" align=\"");
3739     W_V(attr_align);
3740     W_L("\"");
3741   }
3742   W_L(">");
3743
3744   return chtml40->out;
3745 }
3746
3747
3748 /**
3749  * It is a handler who processes the H6 tag.
3750  *
3751  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3752  *                     destination is specified.
3753  * @param node   [i]   The H6 tag node is specified.
3754  * @return The conversion result is returned.
3755  */
3756 static char *
3757 s_chtml40_end_h6_tag(void *pdoc, Node *UNUSED(child)) 
3758 {
3759   chtml40_t *chtml40 = GET_CHTML40(pdoc);
3760   Doc       *doc     = chtml40->doc;
3761
3762   W_L("</h6>");
3763   if (IS_CSS_ON(chtml40->entryp)) {
3764     chxj_css_pop_prop_list(chtml40->css_prop_stack);
3765   }
3766
3767   return chtml40->out;
3768 }
3769
3770
3771 /**
3772  * It is a handler who processes the TEXTARE tag.
3773  *
3774  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3775  *                     destination is specified.
3776  * @param node   [i]   The TEXTAREA tag node is specified.
3777  * @return The conversion result is returned.
3778  */
3779 static char *
3780 s_chtml40_start_textarea_tag(void *pdoc, Node *node) 
3781 {
3782   chtml40_t     *chtml40;
3783   Doc           *doc;
3784   request_rec   *r;
3785   Attr          *attr;
3786   char          *attr_accesskey = NULL;
3787   char          *attr_name      = NULL;
3788   char          *attr_rows      = NULL;
3789   char          *attr_cols      = NULL;
3790   char          *attr_istyle    = NULL;
3791   char          *attr_style     = NULL;
3792
3793   chtml40 = GET_CHTML40(pdoc);
3794   doc     = chtml40->doc;
3795   r       = doc->r;
3796
3797   chtml40->textarea_flag++;
3798
3799   for (attr = qs_get_attr(doc,node);
3800        attr;
3801        attr = qs_get_next_attr(doc,attr)) {
3802     char *name  = qs_get_attr_name(doc,attr);
3803     char *value = qs_get_attr_value(doc,attr);
3804     if (STRCASEEQ('a','A',"accesskey",name) && value && *value != 0) {
3805       attr_accesskey = value;
3806     }
3807     else if (STRCASEEQ('i','I',"istyle", name) && value && (*value == '1' || *value == '2' || *value == '3' || *value == '4')) {
3808       attr_istyle = value;
3809     }
3810     else if (STRCASEEQ('n','N',"name", name) && value && *value) {
3811       attr_name = value;
3812     }
3813     else if (STRCASEEQ('r','R',"rows", name) && value && *value) {
3814       attr_rows = value;
3815     }
3816     else if (STRCASEEQ('c','C',"cols", name) && value && *value) {
3817       attr_cols = value;
3818     }
3819     else if (STRCASEEQ('s','S',"style", name) && value && *value) {
3820       attr_style = value;
3821     }
3822   }
3823   if (IS_CSS_ON(chtml40->entryp)) {
3824     css_prop_list_t *style = s_chtml40_nopush_and_get_now_style(pdoc, node, attr_style);
3825     if (style) {
3826       css_property_t *wap_input_format = chxj_css_get_property_value(doc, style, "-wap-input-format");
3827       css_property_t *cur;
3828       for (cur = wap_input_format->next; cur != wap_input_format; cur = cur->next) {
3829         if (strcasestr(cur->value, "<ja:n>")) {
3830           attr_istyle = "4";
3831         }
3832         else if (strcasestr(cur->value, "<ja:en>")) {
3833           attr_istyle = "3";
3834         }
3835         else if (strcasestr(cur->value, "<ja:hk>")) {
3836           attr_istyle = "2";
3837         }
3838         else if (strcasestr(cur->value, "<ja:h>")) {
3839           attr_istyle = "1";
3840         }
3841       }
3842     }
3843   }
3844   W_L("<textarea");
3845   if (attr_accesskey) {
3846     W_L(" accesskey=\"");
3847     W_V(attr_accesskey);
3848     W_L("\"");
3849   }
3850   if (attr_name) {
3851     W_L(" name=\"");
3852     W_V(attr_name);
3853     W_L("\"");
3854   }
3855   if (attr_rows) {
3856     W_L(" rows=\"");
3857     W_V(attr_rows);
3858     W_L("\"");
3859   }
3860   if (attr_cols) {
3861     W_L(" cols=\"");
3862     W_V(attr_cols);
3863     W_L("\"");
3864   }
3865   if (attr_istyle) {
3866     W_L(" istyle=\"");
3867     W_V(attr_istyle);
3868     W_L("\"");
3869   }
3870   W_L(">");
3871   return chtml40->out;
3872 }
3873
3874
3875 /**
3876  * It is a handler who processes the TEXTAREA tag.
3877  *
3878  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3879  *                     destination is specified.
3880  * @param node   [i]   The TEXTAREA tag node is specified.
3881  * @return The conversion result is returned.
3882  */
3883 static char *
3884 s_chtml40_end_textarea_tag(void *pdoc, Node *UNUSED(child)) 
3885 {
3886   chtml40_t *chtml40 = GET_CHTML40(pdoc);
3887   Doc       *doc     = chtml40->doc;
3888
3889   W_L("</textarea>");
3890   chtml40->textarea_flag--;
3891
3892   return chtml40->out;
3893 }
3894
3895
3896 static char *
3897 s_chtml40_chxjif_tag(void *pdoc, Node *node)
3898 {
3899   Node        *child;
3900   chtml40_t   *chtml40;
3901   Doc         *doc;
3902   request_rec *r;
3903
3904   chtml40 = GET_CHTML40(pdoc);
3905   doc     = chtml40->doc;
3906   r       = doc->r;
3907
3908   for (child = qs_get_child_node(doc, node);
3909        child;
3910        child = qs_get_next_node(doc, child)) {
3911     W_V(child->otext);
3912     s_chtml40_chxjif_tag(chtml40, child);
3913   }
3914
3915   return NULL;
3916 }
3917
3918
3919 static char *
3920 s_chtml40_text_tag(void *pdoc, Node *child)
3921 {
3922   chtml40_t   *chtml40;
3923   Doc         *doc;
3924   request_rec *r;
3925
3926   char        *textval;
3927   char        *tmp;
3928   char        *tdst;
3929   char        one_byte[2];
3930   int         ii;
3931   int         tdst_len;
3932
3933   chtml40 = GET_CHTML40(pdoc);
3934   doc     = chtml40->doc;
3935   r       = doc->r;
3936   
3937   textval = qs_get_node_value(doc,child);
3938   if (strlen(textval) == 0) {
3939     return chtml40->out;
3940   }
3941   
3942   tmp = apr_palloc(r->pool, qs_get_node_size(doc,child)+1);
3943   memset(tmp, 0, qs_get_node_size(doc,child)+1);
3944   
3945   tdst     = qs_alloc_zero_byte_string(doc->buf.pool);
3946   memset(one_byte, 0, sizeof(one_byte));
3947   tdst_len = 0;
3948   
3949   for (ii=0; ii<qs_get_node_size(doc,child); ii++) {
3950     char* out;
3951     int rtn = s_chtml40_search_emoji(chtml40, &textval[ii], &out);
3952     if (rtn) {
3953       tdst = qs_out_apr_pstrcat(r, tdst, out, &tdst_len);
3954       ii+=(rtn - 1);
3955       continue;
3956     }
3957   
3958     if (is_sjis_kanji(textval[ii])) {
3959       one_byte[0] = textval[ii+0];
3960       tdst = qs_out_apr_pstrcat(r, tdst, one_byte, &tdst_len);
3961       one_byte[0] = textval[ii+1];
3962       tdst = qs_out_apr_pstrcat(r, tdst, one_byte, &tdst_len);
3963       ii++;
3964     }
3965     else if (chtml40->pre_flag) {
3966       one_byte[0] = textval[ii+0];
3967       tdst = qs_out_apr_pstrcat(r, tdst, one_byte, &tdst_len);
3968     }
3969     else if (chtml40->textarea_flag) {
3970       one_byte[0] = textval[ii+0];
3971       tdst = qs_out_apr_pstrcat(r, tdst, one_byte, &tdst_len);
3972     }
3973     else if (textval[ii] != '\r' && textval[ii] != '\n') {
3974       one_byte[0] = textval[ii+0];
3975       tdst = qs_out_apr_pstrcat(r, tdst, one_byte, &tdst_len);
3976     }
3977   }
3978   W_V(tdst);
3979   return chtml40->out;
3980 }
3981
3982
3983 /**
3984  * It is a handler who processes the BLOCKQUOTE tag.
3985  *
3986  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
3987  *                     destination is specified.
3988  * @param node   [i]   The BLOCKQUOTE tag node is specified.
3989  * @return The conversion result is returned.
3990  */
3991 static char *
3992 s_chtml40_start_blockquote_tag(void *pdoc, Node *node)
3993 {
3994   chtml40_t *chtml40;
3995   Doc       *doc;
3996   Attr      *attr;
3997   char      *attr_style = NULL;
3998   char      *attr_color = NULL;
3999
4000   chtml40 = GET_CHTML40(pdoc);
4001   doc     = chtml40->doc;
4002   for (attr = qs_get_attr(doc,node);
4003        attr;
4004        attr = qs_get_next_attr(doc,attr)) {
4005     char *nm  = qs_get_attr_name(doc,attr);
4006     char *val = qs_get_attr_value(doc,attr);
4007     if (val && STRCASEEQ('s','S',"style", nm)) {
4008       attr_style = val;
4009     }
4010   }
4011   if (IS_CSS_ON(chtml40->entryp)) {
4012     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
4013     if (style) {
4014       css_property_t *color_prop = chxj_css_get_property_value(doc, style, "color");
4015       css_property_t *cur;
4016       for (cur = color_prop->next; cur != color_prop; cur = cur->next) {
4017         if (cur->value && *cur->value) {
4018           attr_color = apr_pstrdup(doc->pool, cur->value);
4019         }
4020       }
4021     }
4022   }
4023   W_L("<blockquote>");
4024   chtml40_flags_t *flg = (chtml40_flags_t *)apr_palloc(doc->pool, sizeof(chtml40_flags_t));
4025   memset(flg, 0, sizeof(*flg));
4026   if (attr_color) {
4027     attr_color = chxj_css_rgb_func_to_value(doc->pool, attr_color);
4028     W_L("<font color=\"");
4029     W_V(attr_color);
4030     W_L("\">");
4031     flg->with_font_flag = 1;
4032   }
4033   node->userData = (void *)flg;
4034   return chtml40->out;
4035 }
4036
4037
4038 /**
4039  * It is a handler who processes the BLOCKQUOTE tag.
4040  *
4041  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4042  *                     destination is specified.
4043  * @param node   [i]   The BLOCKQUOTE tag node is specified.
4044  * @return The conversion result is returned.
4045  */
4046 static char *
4047 s_chtml40_end_blockquote_tag(void *pdoc, Node *node)
4048 {
4049   chtml40_t *chtml40 = GET_CHTML40(pdoc);
4050   Doc       *doc     = chtml40->doc;
4051   chtml40_flags_t *flg = (chtml40_flags_t *)node->userData;
4052   if (flg && flg->with_font_flag) {
4053     W_L("</font>");
4054   }
4055   W_L("</blockquote>");
4056   if (IS_CSS_ON(chtml40->entryp)) {
4057     chxj_css_pop_prop_list(chtml40->css_prop_stack);
4058   }
4059   return chtml40->out;
4060 }
4061
4062
4063 /**
4064  * It is a handler who processes the DIR tag.
4065  *
4066  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4067  *                     destination is specified.
4068  * @param node   [i]   The DIR tag node is specified.
4069  * @return The conversion result is returned.
4070  */
4071 static char *
4072 s_chtml40_start_dir_tag(void *pdoc, Node *node)
4073 {
4074   chtml40_t *chtml40 = GET_CHTML40(pdoc);
4075   Doc       *doc     = chtml40->doc;
4076   Attr      *attr;
4077   char      *attr_style = NULL;
4078   char      *attr_color = NULL;
4079   char      *attr_type  = NULL;
4080   for (attr = qs_get_attr(doc,node);
4081        attr;
4082        attr = qs_get_next_attr(doc,attr)) {
4083     char *name   = qs_get_attr_name(doc,attr);
4084     char *value  = qs_get_attr_value(doc,attr);
4085     if (STRCASEEQ('t','T',"type",name)) {
4086       if (value && (STRCASEEQ('d','D',"disc",value) || STRCASEEQ('c','C',"circle",value) || STRCASEEQ('s','S',"square",value))) {
4087         attr_type = value;
4088       }
4089     }
4090     else if (STRCASEEQ('s','S',"style", name) && value && *value) {
4091       attr_style = value;
4092     }
4093   }
4094   CHTML40_GET_CSS_COLOR_AND_LIST_STYLE_TYPE();
4095   W_L("<dir");
4096   if (attr_type) {
4097     W_L(" type=\"");
4098     W_V(attr_type);
4099     W_L("\"");
4100   }
4101   W_L(">");
4102   chtml40_flags_t *flg = (chtml40_flags_t *)apr_palloc(doc->pool, sizeof(chtml40_flags_t));
4103   memset(flg, 0, sizeof(*flg));
4104   if (attr_color) {
4105     attr_color = chxj_css_rgb_func_to_value(doc->pool, attr_color);
4106     W_L("<font color=\"");
4107     W_V(attr_color);
4108     W_L("\">");
4109     flg->with_font_flag = 1;
4110   }
4111   node->userData = (void *)flg;
4112   return chtml40->out;
4113 }
4114
4115
4116 /**
4117  * It is a handler who processes the DIR tag.
4118  *
4119  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4120  *                     destination is specified.
4121  * @param node   [i]   The DIR tag node is specified.
4122  * @return The conversion result is returned.
4123  */
4124 static char *
4125 s_chtml40_end_dir_tag(void *pdoc, Node *node)
4126 {
4127   chtml40_t *chtml40 = GET_CHTML40(pdoc);
4128   Doc       *doc = chtml40->doc;
4129   chtml40_flags_t *flg = (chtml40_flags_t *)node->userData;
4130   if (flg && flg->with_font_flag) {
4131     W_L("</font>");
4132   }
4133   W_L("</dir>");
4134   if (IS_CSS_ON(chtml40->entryp)) {
4135     chxj_css_pop_prop_list(chtml40->css_prop_stack);
4136   }
4137   return chtml40->out;
4138 }
4139
4140
4141 /**
4142  * It is a handler who processes the DL tag.
4143  *
4144  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4145  *                     destination is specified.
4146  * @param node   [i]   The DL tag node is specified.
4147  * @return The conversion result is returned.
4148  */
4149 static char *
4150 s_chtml40_start_dl_tag(void *pdoc, Node *node)
4151 {
4152   chtml40_t *chtml40;
4153   Doc       *doc;
4154   Attr      *attr;
4155   char      *attr_style = NULL;
4156   char      *attr_color = NULL;
4157
4158   chtml40 = GET_CHTML40(pdoc);
4159   doc     = chtml40->doc;
4160   for (attr = qs_get_attr(doc,node);
4161        attr;
4162        attr = qs_get_next_attr(doc,attr)) {
4163     char *nm  = qs_get_attr_name(doc,attr);
4164     char *val = qs_get_attr_value(doc,attr);
4165     if (val && STRCASEEQ('s','S',"style", nm)) {
4166       attr_style = val;
4167     }
4168   }
4169   if (IS_CSS_ON(chtml40->entryp)) {
4170     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
4171     if (style) {
4172       css_property_t *color_prop = chxj_css_get_property_value(doc, style, "color");
4173       css_property_t *cur;
4174       for (cur = color_prop->next; cur != color_prop; cur = cur->next) {
4175         if (cur->value && *cur->value) {
4176           attr_color = apr_pstrdup(doc->pool, cur->value);
4177         }
4178       }
4179     }
4180   }
4181   W_L("<dl>");
4182   chtml40_flags_t *flg = (chtml40_flags_t *)apr_palloc(doc->pool, sizeof(chtml40_flags_t));
4183   memset(flg, 0, sizeof(*flg));
4184   if (attr_color) {
4185     attr_color = chxj_css_rgb_func_to_value(doc->pool, attr_color);
4186     W_L("<font color=\"");
4187     W_V(attr_color);
4188     W_L("\">");
4189     flg->with_font_flag = 1;
4190   }
4191   node->userData = (void *)flg;
4192   return chtml40->out;
4193 }
4194
4195
4196 /**
4197  * It is a handler who processes the DL tag.
4198  *
4199  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4200  *                     destination is specified.
4201  * @param node   [i]   The DL tag node is specified.
4202  * @return The conversion result is returned.
4203  */
4204 static char *
4205 s_chtml40_end_dl_tag(void *pdoc, Node *node)
4206 {
4207   chtml40_t *chtml40 = GET_CHTML40(pdoc);
4208   Doc       *doc     = chtml40->doc;
4209   chtml40_flags_t *flg = (chtml40_flags_t *)node->userData;
4210   if (flg && flg->with_font_flag) {
4211     W_L("</font>");
4212   }
4213   W_L("</dl>");
4214   if (IS_CSS_ON(chtml40->entryp)) {
4215     chxj_css_pop_prop_list(chtml40->css_prop_stack);
4216   }
4217   return chtml40->out;
4218 }
4219
4220
4221 /**
4222  * It is a handler who processes the DT tag.
4223  *
4224  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4225  *                     destination is specified.
4226  * @param node   [i]   The DT tag node is specified.
4227  * @return The conversion result is returned.
4228  */
4229 static char *
4230 s_chtml40_start_dt_tag(void *pdoc, Node *node)
4231 {
4232   chtml40_t *chtml40;
4233   Doc       *doc;
4234   Attr      *attr;
4235   char      *attr_style = NULL;
4236   char      *attr_color = NULL;
4237
4238   chtml40 = GET_CHTML40(pdoc);
4239   doc     = chtml40->doc;
4240   for (attr = qs_get_attr(doc,node);
4241        attr;
4242        attr = qs_get_next_attr(doc,attr)) {
4243     char *nm  = qs_get_attr_name(doc,attr);
4244     char *val = qs_get_attr_value(doc,attr);
4245     if (val && STRCASEEQ('s','S',"style", nm)) {
4246       attr_style = val;
4247     }
4248   }
4249   if (IS_CSS_ON(chtml40->entryp)) {
4250     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
4251     if (style) {
4252       css_property_t *color_prop = chxj_css_get_property_value(doc, style, "color");
4253       css_property_t *cur;
4254       for (cur = color_prop->next; cur != color_prop; cur = cur->next) {
4255         if (cur->value && *cur->value) {
4256           attr_color = apr_pstrdup(doc->pool, cur->value);
4257         }
4258       }
4259     }
4260   }
4261   W_L("<dt>");
4262   chtml40_flags_t *flg = (chtml40_flags_t *)apr_palloc(doc->pool, sizeof(chtml40_flags_t));
4263   memset(flg, 0, sizeof(*flg));
4264   if (attr_color) {
4265     attr_color = chxj_css_rgb_func_to_value(doc->pool, attr_color);
4266     W_L("<font color=\"");
4267     W_V(attr_color);
4268     W_L("\">");
4269     flg->with_font_flag = 1;
4270   }
4271   node->userData = (void *)flg;
4272   return chtml40->out;
4273 }
4274
4275
4276 /**
4277  * It is a handler who processes the DT tag.
4278  *
4279  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4280  *                     destination is specified.
4281  * @param node   [i]   The DT tag node is specified.
4282  * @return The conversion result is returned.
4283  */
4284 static char *
4285 s_chtml40_end_dt_tag(void *pdoc, Node *node)
4286 {
4287   chtml40_t *chtml40 = GET_CHTML40(pdoc);
4288   Doc       *doc     = chtml40->doc;
4289   chtml40_flags_t *flg = (chtml40_flags_t *)node->userData;
4290   if (flg && flg->with_font_flag) {
4291     W_L("</font>");
4292   }
4293   if (IS_CSS_ON(chtml40->entryp)) {
4294     chxj_css_pop_prop_list(chtml40->css_prop_stack);
4295   }
4296   return chtml40->out;
4297 }
4298
4299
4300 /**
4301  * It is a handler who processes the DD tag.
4302  *
4303  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4304  *                     destination is specified.
4305  * @param node   [i]   The DD tag node is specified.
4306  * @return The conversion result is returned.
4307  */
4308 static char *
4309 s_chtml40_start_dd_tag(void *pdoc, Node *node)
4310 {
4311   chtml40_t *chtml40;
4312   Doc       *doc;
4313   Attr      *attr;
4314   char      *attr_style = NULL;
4315   char      *attr_color = NULL;
4316
4317   chtml40 = GET_CHTML40(pdoc);
4318   doc     = chtml40->doc;
4319   for (attr = qs_get_attr(doc,node);
4320        attr;
4321        attr = qs_get_next_attr(doc,attr)) {
4322     char *nm  = qs_get_attr_name(doc,attr);
4323     char *val = qs_get_attr_value(doc,attr);
4324     if (val && STRCASEEQ('s','S',"style", nm)) {
4325       attr_style = val;
4326     }
4327   }
4328   if (IS_CSS_ON(chtml40->entryp)) {
4329     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
4330     if (style) {
4331       css_property_t *color_prop = chxj_css_get_property_value(doc, style, "color");
4332       css_property_t *cur;
4333       for (cur = color_prop->next; cur != color_prop; cur = cur->next) {
4334         if (cur->value && *cur->value) {
4335           attr_color = apr_pstrdup(doc->pool, cur->value);
4336         }
4337       }
4338     }
4339   }
4340   W_L("<dd>");
4341   chtml40_flags_t *flg = (chtml40_flags_t *)apr_palloc(doc->pool, sizeof(chtml40_flags_t));
4342   memset(flg, 0, sizeof(*flg));
4343   if (attr_color) {
4344     attr_color = chxj_css_rgb_func_to_value(doc->pool, attr_color);
4345     W_L("<font color=\"");
4346     W_V(attr_color);
4347     W_L("\">");
4348     flg->with_font_flag = 1;
4349   }
4350   node->userData = (void *)flg;
4351   return chtml40->out;
4352 }
4353
4354
4355 /**
4356  * It is a handler who processes the DD tag.
4357  *
4358  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4359  *                     destination is specified.
4360  * @param node   [i]   The DD tag node is specified.
4361  * @return The conversion result is returned.
4362  */
4363 static char *
4364 s_chtml40_end_dd_tag(void *pdoc, Node *node)
4365 {
4366   chtml40_t *chtml40 = GET_CHTML40(pdoc);
4367   Doc       *doc     = chtml40->doc;
4368   chtml40_flags_t *flg = (chtml40_flags_t *)node->userData;
4369   if (flg && flg->with_font_flag) {
4370     W_L("</font>");
4371   }
4372   if (IS_CSS_ON(chtml40->entryp)) {
4373     chxj_css_pop_prop_list(chtml40->css_prop_stack);
4374   }
4375   return chtml40->out;
4376 }
4377
4378
4379 /**
4380  * It is a handler who processes the MARQUEE tag.
4381  *
4382  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4383  *                     destination is specified.
4384  * @param node   [i]   The MARQUEE tag node is specified.
4385  * @return The conversion result is returned.
4386  */
4387 static char *
4388 s_chtml40_start_marquee_tag(void *pdoc, Node *node)
4389 {
4390   chtml40_t *chtml40 = GET_CHTML40(pdoc);
4391   Doc       *doc = chtml40->doc;
4392   Attr      *attr;
4393   char      *attr_direction = NULL;
4394   char      *attr_behavior  = NULL;
4395   char      *attr_loop      = NULL;
4396   char      *attr_style     = NULL;
4397   char      *attr_color     = NULL;
4398   /*--------------------------------------------------------------------------*/
4399   /* Get Attributes                                                           */
4400   /*--------------------------------------------------------------------------*/
4401   for (attr = qs_get_attr(doc,node);
4402        attr;
4403        attr = qs_get_next_attr(doc,attr)) {
4404     char *name   = qs_get_attr_name(doc,attr);
4405     char *value  = qs_get_attr_value(doc,attr);
4406     if (STRCASEEQ('d','D',"direction", name)) {
4407       if (value && (STRCASEEQ('l','L',"left",value) || STRCASEEQ('r','R',"right",value))) {
4408         attr_direction = value;
4409       }
4410     }
4411     else if (STRCASEEQ('b','B',"behavior",name)) {
4412       if (value && (STRCASEEQ('s','S',"scroll",value) || STRCASEEQ('s','S',"slide",value) || STRCASEEQ('a','A',"alternate",value))) {
4413         attr_behavior = value;
4414       }
4415     }
4416     else if (STRCASEEQ('l','L',"loop",name)) {
4417       if (value && *value) {
4418         attr_loop = value;
4419       }
4420     }
4421     else if (STRCASEEQ('s','S',"style",name) && value && *value) {
4422       attr_style = value;
4423     }
4424   }
4425   if (IS_CSS_ON(chtml40->entryp)) {
4426     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
4427     if (style) {
4428       css_property_t *color_prop = chxj_css_get_property_value(doc, style, "color");
4429       css_property_t *direction_prop = chxj_css_get_property_value(doc, style, "-wap-marquee-dir");
4430       css_property_t *style_prop     = chxj_css_get_property_value(doc, style, "-wap-marquee-style");
4431       css_property_t *loop_prop      = chxj_css_get_property_value(doc, style, "-wap-marquee-loop");
4432       css_property_t *cur;
4433       for (cur = color_prop->next; cur != color_prop; cur = cur->next) {
4434         if (cur->value && *cur->value) {
4435           attr_color = apr_pstrdup(doc->pool, cur->value);
4436         }
4437       }
4438       for (cur = style_prop->next; cur != style_prop; cur = cur->next) {
4439         if (cur->value && *cur->value) {
4440           attr_behavior = apr_pstrdup(doc->pool, cur->value);
4441         }
4442       }
4443       for (cur = loop_prop->next; cur != loop_prop; cur = cur->next) {
4444         if (cur->value && *cur->value) {
4445           attr_loop = apr_pstrdup(doc->pool, cur->value);
4446           if (STRCASEEQ('i','I',"infinite",attr_loop)) {
4447             attr_loop = "16";
4448           }
4449         }
4450       }
4451       for (cur = direction_prop->next; cur != direction_prop; cur = cur->next) {
4452         if (cur->value && *cur->value) {
4453           if (STRCASEEQ('l','L',"ltr",cur->value)) {
4454             attr_direction = "right";
4455           }
4456           else if (STRCASEEQ('r','R',"rtl",cur->value)) {
4457             attr_direction = "left";
4458           }
4459         }
4460       }
4461     }
4462   }
4463   W_L("<marquee");
4464   if (attr_direction) {
4465     W_L(" direction=\"");
4466     W_V(attr_direction);
4467     W_L("\"");
4468   }
4469   if (attr_behavior) {
4470     W_L(" behavior=\"");
4471     W_V(attr_behavior);
4472     W_L("\"");
4473   }
4474   if (attr_loop) {
4475     W_L(" loop=\"");
4476     W_V(attr_loop);
4477     W_L("\"");
4478   }
4479   W_L(">");
4480
4481   chtml40_flags_t *flg = (chtml40_flags_t *)apr_palloc(doc->pool, sizeof(chtml40_flags_t));
4482   memset(flg, 0, sizeof(*flg));
4483   if (attr_color) {
4484     attr_color = chxj_css_rgb_func_to_value(doc->pool, attr_color);
4485     W_L("<font color=\"");
4486     W_V(attr_color);
4487     W_L("\">");
4488     flg->with_font_flag = 1;
4489   }
4490   node->userData = (void *)flg;
4491   return chtml40->out;
4492 }
4493
4494
4495 /**
4496  * It is a handler who processes the MARQUEE tag.
4497  *
4498  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4499  *                     destination is specified.
4500  * @param node   [i]   The MARQUEE tag node is specified.
4501  * @return The conversion result is returned.
4502  */
4503 static char *
4504 s_chtml40_end_marquee_tag(void *pdoc, Node *node)
4505 {
4506   chtml40_t *chtml40 = GET_CHTML40(pdoc);
4507   Doc       *doc     = chtml40->doc;
4508   chtml40_flags_t *flg = (chtml40_flags_t *)node->userData;
4509   if (flg && flg->with_font_flag) {
4510     W_L("</font>");
4511   }
4512   W_L("</marquee>");
4513   if (IS_CSS_ON(chtml40->entryp)) {
4514     chxj_css_pop_prop_list(chtml40->css_prop_stack);
4515   }
4516   return chtml40->out;
4517 }
4518
4519
4520 /**
4521  * It is a handler who processes the BLINK tag.
4522  *
4523  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4524  *                     destination is specified.
4525  * @param node   [i]   The BLINK tag node is specified.
4526  * @return The conversion result is returned.
4527  */
4528 static char *
4529 s_chtml40_start_blink_tag(void *pdoc, Node *node)
4530 {
4531   chtml40_t *chtml40;
4532   Doc       *doc;
4533   Attr      *attr;
4534   char      *attr_style = NULL;
4535   char      *attr_color = NULL;
4536
4537   chtml40 = GET_CHTML40(pdoc);
4538   doc     = chtml40->doc;
4539   for (attr = qs_get_attr(doc,node);
4540        attr;
4541        attr = qs_get_next_attr(doc,attr)) {
4542     char *nm  = qs_get_attr_name(doc,attr);
4543     char *val = qs_get_attr_value(doc,attr);
4544     if (val && STRCASEEQ('s','S',"style", nm)) {
4545       attr_style = val;
4546     }
4547   }
4548   if (IS_CSS_ON(chtml40->entryp)) {
4549     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
4550     if (style) {
4551       css_property_t *color_prop = chxj_css_get_property_value(doc, style, "color");
4552       css_property_t *cur;
4553       for (cur = color_prop->next; cur != color_prop; cur = cur->next) {
4554         if (cur->value && *cur->value) {
4555           attr_color = apr_pstrdup(doc->pool, cur->value);
4556         }
4557       }
4558     }
4559   }
4560   W_L("<blink>");
4561   chtml40_flags_t *flg = (chtml40_flags_t *)apr_palloc(doc->pool, sizeof(chtml40_flags_t));
4562   memset(flg, 0, sizeof(*flg));
4563   if (attr_color) {
4564     attr_color = chxj_css_rgb_func_to_value(doc->pool, attr_color);
4565     W_L("<font color=\"");
4566     W_V(attr_color);
4567     W_L("\">");
4568     flg->with_font_flag = 1;
4569   }
4570   node->userData = (void *)flg;
4571   return chtml40->out;
4572 }
4573
4574
4575 /**
4576  * It is a handler who processes the BLINK tag.
4577  *
4578  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4579  *                     destination is specified.
4580  * @param node   [i]   The BLINK tag node is specified.
4581  * @return The conversion result is returned.
4582  */
4583 static char *
4584 s_chtml40_end_blink_tag(void *pdoc, Node *node)
4585 {
4586   chtml40_t *chtml40 = GET_CHTML40(pdoc);
4587   Doc       *doc     = chtml40->doc;
4588   chtml40_flags_t *flg = (chtml40_flags_t *)node->userData;
4589   if (flg && flg->with_font_flag) {
4590     W_L("</font>");
4591   }
4592   W_L("</blink>");
4593   if (IS_CSS_ON(chtml40->entryp)) {
4594     chxj_css_pop_prop_list(chtml40->css_prop_stack);
4595   }
4596   return chtml40->out;
4597 }
4598
4599
4600 /**
4601  * It is a handler who processes the MENU tag.
4602  *
4603  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4604  *                     destination is specified.
4605  * @param node   [i]   The MENU tag node is specified.
4606  * @return The conversion result is returned.
4607  */
4608 static char *
4609 s_chtml40_start_menu_tag(void *pdoc, Node *node)
4610 {
4611   chtml40_t *chtml40 = GET_CHTML40(pdoc);
4612   Doc       *doc     = chtml40->doc;
4613   Attr      *attr;
4614   char      *attr_style = NULL;
4615   char      *attr_type  = NULL;
4616   char      *attr_color = NULL;
4617   /*--------------------------------------------------------------------------*/
4618   /* Get Attributes                                                           */
4619   /*--------------------------------------------------------------------------*/
4620   for (attr = qs_get_attr(doc,node);
4621        attr;
4622        attr = qs_get_next_attr(doc,attr)) {
4623     char *name   = qs_get_attr_name(doc,attr);
4624     char *value  = qs_get_attr_value(doc,attr);
4625     if (STRCASEEQ('t','T',"type",name)) {
4626       if (value && (STRCASEEQ('d','D',"disc",value) || STRCASEEQ('c','C',"circle",value) || STRCASEEQ('s','S',"square",value))) {
4627         attr_type = value;
4628       }
4629     }
4630     else if (STRCASEEQ('s','S',"style", name) && value && *value) {
4631       attr_style = value;
4632     }
4633   }
4634   CHTML40_GET_CSS_COLOR_AND_LIST_STYLE_TYPE();
4635   W_L("<menu");
4636   if (attr_type) {
4637     W_L(" type=\"");
4638     W_V(attr_type);
4639     W_L("\"");
4640   }
4641   W_L(">");
4642   chtml40_flags_t *flg = (chtml40_flags_t *)apr_palloc(doc->pool, sizeof(chtml40_flags_t));
4643   memset(flg, 0, sizeof(*flg));
4644   if (attr_color) {
4645     attr_color = chxj_css_rgb_func_to_value(doc->pool, attr_color);
4646     W_L("<font color=\"");
4647     W_V(attr_color);
4648     W_L("\">");
4649     flg->with_font_flag = 1;
4650   }
4651   node->userData = (void *)flg;
4652
4653   return chtml40->out;
4654 }
4655
4656
4657 /**
4658  * It is a handler who processes the MENU tag.
4659  *
4660  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4661  *                     destination is specified.
4662  * @param node   [i]   The MENU tag node is specified.
4663  * @return The conversion result is returned.
4664  */
4665 static char *
4666 s_chtml40_end_menu_tag(void *pdoc, Node *node)
4667 {
4668   chtml40_t *chtml40 = GET_CHTML40(pdoc);
4669   Doc       *doc     = chtml40->doc;
4670   chtml40_flags_t *flg = (chtml40_flags_t *)node->userData;
4671   if (flg && flg->with_font_flag) {
4672     W_L("</font>");
4673   }
4674   W_L("</menu>");
4675   if (IS_CSS_ON(chtml40->entryp)) {
4676     chxj_css_pop_prop_list(chtml40->css_prop_stack);
4677   }
4678   return chtml40->out;
4679 }
4680
4681
4682 /**
4683  * It is a handler who processes the PLAINTEXT tag.
4684  *
4685  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4686  *                     destination is specified.
4687  * @param node   [i]   The PLAINTEXT tag node is specified.
4688  * @return The conversion result is returned.
4689  */
4690 static char *
4691 s_chtml40_start_plaintext_tag(void *pdoc, Node *node)
4692 {
4693   chtml40_t *chtml40 = GET_CHTML40(pdoc);
4694   Doc       *doc     = chtml40->doc;
4695   W_L("<plaintext>");
4696   s_chtml40_start_plaintext_tag_inner(pdoc,node);
4697   return chtml40->out;
4698 }
4699
4700 static char *
4701 s_chtml40_start_plaintext_tag_inner(void *pdoc, Node *node)
4702 {
4703   chtml40_t *chtml40 = GET_CHTML40(pdoc);
4704   Doc       *doc     = chtml40->doc;
4705   Node      *child;
4706   for (child = qs_get_child_node(doc, node);
4707        child;
4708        child = qs_get_next_node(doc, child)) {
4709     W_V(child->otext);
4710     s_chtml40_start_plaintext_tag_inner(pdoc, child);
4711   }
4712   return chtml40->out;
4713 }
4714
4715
4716 /**
4717  * It is a handler who processes the PLAINTEXT tag.
4718  *
4719  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4720  *                     destination is specified.
4721  * @param node   [i]   The PLAINTEXT tag node is specified.
4722  * @return The conversion result is returned.
4723  */
4724 static char *
4725 s_chtml40_end_plaintext_tag(void *pdoc, Node *UNUSED(child))
4726 {
4727   chtml40_t *chtml40 = GET_CHTML40(pdoc);
4728   return chtml40->out;
4729 }
4730
4731
4732 /**
4733  * It is handler who processes the New Line Code.
4734  */
4735 static char *
4736 s_chtml40_newline_mark(void *pdoc, Node *UNUSED(node))
4737 {
4738   chtml40_t *chtml40 = GET_CHTML40(pdoc);
4739   Doc *doc = chtml40->doc;
4740   W_NLCODE();
4741   return chtml40->out;
4742 }
4743
4744
4745 /**
4746  * It is a handler who processes the LINK tag.
4747  *
4748  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4749  *                     destination is specified.
4750  * @param node   [i]   The LINK tag node is specified.
4751  * @return The conversion result is returned.
4752  */
4753 static char *
4754 s_chtml40_link_tag(void *pdoc, Node *node)
4755 {
4756   chtml40_t     *chtml40;
4757   Doc           *doc;
4758   Attr          *attr;
4759   char          *rel  = NULL;
4760   char          *href = NULL;
4761   char          *type = NULL;
4762
4763   chtml40 = GET_CHTML40(pdoc);
4764   doc     = chtml40->doc;
4765
4766   if (! IS_CSS_ON(chtml40->entryp)) {
4767     return chtml40->out;
4768   }
4769
4770   for (attr = qs_get_attr(doc,node);
4771        attr;
4772        attr = qs_get_next_attr(doc,attr)) {
4773     char *name  = qs_get_attr_name(doc,attr);
4774     char *value = qs_get_attr_value(doc,attr);
4775     if (STRCASEEQ('r','R',"rel", name)) {
4776       if (value && *value && STRCASEEQ('s','S',"stylesheet", value)) {
4777         rel = value;
4778       }
4779     }
4780     else if (STRCASEEQ('h','H',"href", name)) {
4781       if (value && *value) {
4782         href = value;
4783       }
4784     }
4785     else if (STRCASEEQ('t','T',"type", name)) {
4786       if (value && *value && STRCASEEQ('t','T',"text/css",value)) {
4787         type = value;
4788       }
4789     }
4790   }
4791
4792   if (rel && href && type) {
4793     DBG(doc->r, "start load CSS. url:[%s]", href);
4794     chtml40->style = chxj_css_parse_from_uri(doc->r, doc->pool, chtml40->style, href);
4795     DBG(doc->r, "end load CSS. url:[%s]", href);
4796   }
4797
4798   return chtml40->out;
4799 }
4800
4801 static css_prop_list_t *
4802 s_chtml40_push_and_get_now_style(void *pdoc, Node *node, const char *style_attr_value)
4803 {
4804   chtml40_t *chtml40 = GET_CHTML40(pdoc);
4805   Doc *doc = chtml40->doc;
4806   css_prop_list_t *last_css = NULL;
4807   if (IS_CSS_ON(chtml40->entryp)) {
4808     css_prop_list_t *dup_css;
4809     css_selector_t  *selector;
4810
4811     last_css = chxj_css_get_last_prop_list(chtml40->css_prop_stack);
4812     dup_css  = chxj_dup_css_prop_list(doc, last_css);
4813     selector = chxj_css_find_selector(doc, chtml40->style, node);
4814     if (selector) {
4815       chxj_css_prop_list_merge_property(doc, dup_css, selector);
4816     }
4817     chxj_css_push_prop_list(chtml40->css_prop_stack, dup_css);
4818     last_css = chxj_css_get_last_prop_list(chtml40->css_prop_stack);
4819
4820     if (style_attr_value) {
4821       css_stylesheet_t *ssheet = chxj_css_parse_style_attr(doc, NULL, apr_pstrdup(doc->pool, node->name), NULL, NULL, apr_pstrdup(doc->pool, style_attr_value));
4822       if (ssheet) {
4823         chxj_css_prop_list_merge_property(doc, last_css, ssheet->selector_head.next);
4824       }
4825     }
4826   }
4827   return last_css;
4828 }
4829
4830
4831 static css_prop_list_t *
4832 s_chtml40_nopush_and_get_now_style(void *pdoc, Node *node, const char *style_attr_value)
4833 {
4834   chtml40_t *chtml40 = GET_CHTML40(pdoc);
4835   Doc *doc = chtml40->doc;
4836   css_prop_list_t *last_css = NULL;
4837   if (IS_CSS_ON(chtml40->entryp)) {
4838     css_prop_list_t *dup_css;
4839     css_selector_t  *selector;
4840
4841     last_css = chxj_css_get_last_prop_list(chtml40->css_prop_stack);
4842     dup_css  = chxj_dup_css_prop_list(doc, last_css);
4843     selector = chxj_css_find_selector(doc, chtml40->style, node);
4844     if (selector) {
4845       chxj_css_prop_list_merge_property(doc, dup_css, selector);
4846     }
4847     last_css = dup_css;
4848
4849     if (style_attr_value) {
4850       css_stylesheet_t *ssheet = chxj_css_parse_style_attr(doc, NULL, apr_pstrdup(doc->pool, node->name), NULL, NULL, apr_pstrdup(doc->pool, style_attr_value));
4851       if (ssheet) {
4852         chxj_css_prop_list_merge_property(doc, last_css, ssheet->selector_head.next);
4853       }
4854     }
4855   }
4856   return last_css;
4857 }
4858
4859
4860
4861 /**
4862  * It is a handler who processes the SPAN tag.
4863  *
4864  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
4865  *                     destination is specified.
4866  * @param node   [i]   The SPAN tag node is specified.
4867  * @return The conversion result is returned.
4868  */
4869 static char *
4870 s_chtml40_start_span_tag(void *pdoc, Node *node)
4871 {
4872   chtml40_t *chtml40;
4873   Doc *doc;
4874   Attr *attr;
4875   char *attr_style = NULL;
4876   char *attr_color = NULL;
4877   char *attr_align = NULL;
4878   char *attr_blink = NULL;
4879   char *attr_marquee = NULL;
4880   char *attr_marquee_dir = NULL;
4881   char *attr_marquee_style = NULL;
4882   char *attr_marquee_loop = NULL;
4883
4884   chtml40 = GET_CHTML40(pdoc);
4885   doc     = chtml40->doc;
4886
4887   for (attr = qs_get_attr(doc,node);
4888        attr;
4889        attr = qs_get_next_attr(doc,attr)) {
4890     char *nm  = qs_get_attr_name(doc,attr);
4891     char *val = qs_get_attr_value(doc,attr);
4892     if (val && STRCASEEQ('s','S',"style", nm)) {
4893       attr_style = val;
4894     }
4895   }
4896   if (IS_CSS_ON(chtml40->entryp)) {
4897     css_prop_list_t *style = s_chtml40_push_and_get_now_style(pdoc, node, attr_style);
4898     if (style) {
4899       css_property_t *color_prop = chxj_css_get_property_value(doc, style, "color");
4900       css_property_t *text_align_prop = chxj_css_get_property_value(doc, style, "text-align");
4901       css_property_t *decoration_prop = chxj_css_get_property_value(doc, style, "text-decoration");
4902       css_property_t *display_prop = chxj_css_get_property_value(doc, style, "display");
4903       css_property_t *marquee_dir_prop = chxj_css_get_property_value(doc, style, "-wap-marquee-dir");
4904       css_property_t *marquee_style_prop = chxj_css_get_property_value(doc, style, "-wap-marquee-style");
4905       css_property_t *marquee_loop_prop = chxj_css_get_property_value(doc, style, "-wap-marquee-loop");
4906       css_property_t *cur;
4907       for (cur = color_prop->next; cur != color_prop; cur = cur->next) {
4908         attr_color = apr_pstrdup(doc->pool, cur->value);
4909       }
4910       for (cur = decoration_prop->next; cur != decoration_prop; cur = cur->next) {
4911         if (cur->value && STRCASEEQ('b','B',"blink",cur->value)) {
4912           attr_blink = apr_pstrdup(doc->pool, cur->value);
4913         }
4914       }
4915       for (cur = display_prop->next; cur != display_prop; cur = cur->next) {
4916         if (cur->value && strcasecmp("-wap-marquee",cur->value) == 0) {
4917           attr_marquee = apr_pstrdup(doc->pool, cur->value);
4918         }
4919       }
4920       for (cur = marquee_dir_prop->next; cur != marquee_dir_prop; cur = cur->next) {
4921         if (cur->value && *cur->value) {
4922           if (STRCASEEQ('l','L',"ltr",cur->value)) {
4923             attr_marquee_dir = "right";
4924           }
4925           else if (STRCASEEQ('r','R',"rtl",cur->value)) {
4926             attr_marquee_dir = "left";
4927           }
4928         }
4929       }
4930       for (cur = marquee_style_prop->next; cur != marquee_style_prop; cur = cur->next) {
4931         if (cur->value && *cur->value) {
4932           if ( STRCASEEQ('s','S',"scroll",cur->value)
4933             || STRCASEEQ('s','S',"slide",cur->value)
4934             || STRCASEEQ('a','A',"alternate",cur->value)) {
4935             attr_marquee_style = apr_pstrdup(doc->pool, cur->value);
4936           }
4937         }
4938       }
4939       for (cur = marquee_loop_prop->next; cur != marquee_loop_prop; cur = cur->next) {
4940         if (cur->value && *cur->value) {
4941           if (STRCASEEQ('i','I',"infinite",cur->value)) {
4942             attr_marquee_loop = "16";
4943           }
4944           else {
4945             attr_marquee_loop = apr_pstrdup(doc->pool, cur->value);
4946           }
4947         }
4948       }
4949       for (cur = text_align_prop->next; cur != text_align_prop; cur = cur->next) {
4950         if (STRCASEEQ('l','L',"left", cur->value)) {
4951           attr_align = apr_pstrdup(doc->pool, "left");
4952         }
4953         else if (STRCASEEQ('c','C',"center",cur->value)) {
4954           attr_align = apr_pstrdup(doc->pool, "center");
4955         }
4956         else if (STRCASEEQ('r','R',"right",cur->value)) {
4957           attr_align = apr_pstrdup(doc->pool, "right");
4958         }
4959       }
4960     }
4961   }
4962   if (attr_color || attr_align || attr_blink || attr_marquee) {
4963     chtml40_flags_t *flg = apr_palloc(doc->pool, sizeof(*flg));
4964     memset(flg, 0, sizeof(*flg));
4965     if (attr_blink) {
4966       W_L("<blink>");
4967       flg->with_blink_flag = 1;
4968     }
4969     if (attr_marquee) {
4970       W_L("<marquee");
4971       if (attr_marquee_dir) {
4972         W_L(" direction=\"");
4973         W_V(attr_marquee_dir);
4974         W_L("\"");
4975       }
4976       if (attr_marquee_style) {
4977         W_L(" behavior=\"");
4978         W_V(attr_marquee_style);
4979         W_L("\"");
4980       }
4981       if (attr_marquee_loop) {
4982         W_L(" loop=\"");
4983         W_V(attr_marquee_loop);
4984         W_L("\"");
4985       }
4986       W_L(">");
4987       flg->with_marquee_flag = 1;
4988     }
4989     if (attr_color) {
4990       attr_color = chxj_css_rgb_func_to_value(doc->pool, attr_color);
4991       W_L("<font color=\"");
4992       W_V(attr_color);
4993       W_L("\">");
4994       flg->with_font_flag = 1;
4995     }
4996     if (attr_align) {
4997       W_L("<div align=\"");
4998       W_V(attr_align);
4999       W_L("\">");
5000       flg->with_div_flag = 1;
5001     }
5002     node->userData = flg;
5003   }
5004   else {
5005     node->userData = NULL;
5006   }
5007   return chtml40->out;
5008 }
5009
5010
5011 /**
5012  * It is a handler who processes the SPAN tag.
5013  *
5014  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
5015  *                     destination is specified.
5016  * @param node   [i]   The SPAN tag node is specified.
5017  * @return The conversion result is returned.
5018  */
5019 static char *
5020 s_chtml40_end_span_tag(void *pdoc, Node *node)
5021 {
5022   chtml40_t *chtml40 = GET_CHTML40(pdoc);
5023   Doc *doc = chtml40->doc;
5024
5025   chtml40_flags_t *flg = (chtml40_flags_t *)node->userData;
5026   if (flg && flg->with_div_flag) {
5027     W_L("</div>");
5028   }
5029   if (flg && flg->with_font_flag) {
5030     W_L("</font>");
5031   }
5032   if (flg && flg->with_marquee_flag) {
5033     W_L("</marquee>");
5034   }
5035   if (flg && flg->with_blink_flag) {
5036     W_L("</blink>");
5037   }
5038   if (IS_CSS_ON(chtml40->entryp)) {
5039     chxj_css_pop_prop_list(chtml40->css_prop_stack);
5040   }
5041   return chtml40->out;
5042 }
5043
5044
5045 /**
5046  * It is a handler who processes the STYLE tag.
5047  *
5048  * @param pdoc  [i/o] The pointer to the CHTML structure at the output
5049  *                     destination is specified.
5050  * @param node   [i]   The STYLE tag node is specified.
5051  * @return The conversion result is returned.
5052  */
5053 static char *
5054 s_chtml40_style_tag(void *pdoc, Node *node)
5055 {
5056   chtml40_t     *chtml40;
5057   Doc           *doc;
5058   Attr          *attr;
5059   char          *type = NULL;
5060
5061   chtml40 = GET_CHTML40(pdoc);
5062   doc     = chtml40->doc;
5063
5064   if (! IS_CSS_ON(chtml40->entryp)) {
5065     return chtml40->out;
5066   }
5067
5068   for (attr = qs_get_attr(doc,node);
5069        attr;
5070        attr = qs_get_next_attr(doc,attr)) {
5071     char *name  = qs_get_attr_name(doc,attr);
5072     char *value = qs_get_attr_value(doc,attr);
5073     if (STRCASEEQ('t','T',"type", name)) {
5074       if (value && *value && STRCASEEQ('t','T',"text/css",value)) {
5075         type = value;
5076       }
5077     }
5078   }
5079
5080   Node *child = qs_get_child_node(doc, node);
5081   if (type && child) {
5082     char *name  = qs_get_node_name(doc, child);
5083     if (STRCASEEQ('t','T',"text", name)) {
5084       char *value = qs_get_node_value(doc, child);
5085       DBG(doc->r, "start load CSS. buf:[%s]", value);
5086       chtml40->style = chxj_css_parse_style_value(doc, chtml40->style, value);
5087       DBG(doc->r, "end load CSS. value:[%s]", value);
5088     }
5089   }
5090   return chtml40->out;
5091 }
5092 /*
5093  * vim:ts=2 et
5094  */