OSDN Git Service

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