(www-format-encode-string): Display &{G-|g2-|R-}RUI6-hhhh;.
[chise/est.git] / cwiki-common.el
1 ;; -*- coding: utf-8-mcs-er -*-
2 (require 'char-db-util)
3 ;; (require 'concord-images)
4
5 (setq file-name-coding-system 'utf-8-mcs-er)
6
7
8 (concord-assign-genre 'image-resource "/usr/local/var/photo/db")
9 (concord-assign-genre 'glyph-image "/usr/local/var/photo/db")
10
11 (concord-assign-genre 'creator@ruimoku "/usr/local/var/ruimoku/db")
12 (concord-assign-genre 'person-name@ruimoku "/usr/local/var/ruimoku/db")
13
14 (concord-assign-genre 'journal-volume@ruimoku "/usr/local/var/ruimoku/db")
15 (concord-assign-genre 'article@ruimoku "/usr/local/var/ruimoku/db")
16 (concord-assign-genre 'book@ruimoku "/usr/local/var/ruimoku/db")
17
18 (concord-assign-genre 'classification@ruimoku "/usr/local/var/ruimoku/db")
19 (concord-assign-genre 'region@ruimoku "/usr/local/var/ruimoku/db")
20 (concord-assign-genre 'era@ruimoku "/usr/local/var/ruimoku/db")
21 (concord-assign-genre 'period@ruimoku "/usr/local/var/ruimoku/db")
22 (concord-assign-genre 'journal@ruimoku "/usr/local/var/ruimoku/db")
23 (concord-assign-genre 'journal-name@ruimoku "/usr/local/var/ruimoku/db")
24 (concord-assign-genre 'publisher@ruimoku "/usr/local/var/ruimoku/db")
25 (concord-assign-genre 'publisher-name@ruimoku "/usr/local/var/ruimoku/db")
26
27 (mount-char-attribute-table '*instance@ruimoku/bibliography/title)
28 ;; (mount-char-attribute-table '*instance@ruimoku/bibliography/content*note)
29
30 (concord-assign-genre 'entry@zh-classical "/usr/local/var/kanbun/db")
31 ;; (concord-assign-genre 'morpheme-entry@zh-classical "/usr/local/var/kanbun/db")
32 (concord-assign-genre 'word-class@zh-classical "/usr/local/var/kanbun/db")
33 (concord-assign-genre 'morpheme@zh-classical "/usr/local/var/kanbun/db")
34 (concord-assign-genre 'sentence@zh-classical "/usr/local/var/kanbun/db")
35 ;; (concord-assign-genre 'sentence-entry@zh-classical "/usr/local/var/kanbun/db")
36
37 (mount-char-attribute-table '*instance@morpheme-entry/zh-classical)
38
39
40 (concord-assign-genre 'hng-card "/usr/local/var/hng-card/db")
41
42 (mount-char-attribute-table '->HNG)
43 (mount-char-attribute-table '<-HNG)
44
45
46 (defvar est-hide-cgi-mode nil)
47 (defvar est-view-url-prefix "..")
48 (defvar chise-wiki-view-url "view.cgi")
49 (defvar chise-wiki-edit-url "edit.cgi")
50
51 (defvar chise-wiki-bitmap-glyphs-url
52   "http://www.chise.org/glyphs")
53
54 (defvar chise-wiki-hng-bitmap-glyphs-url
55   "http://hng.chise.org/glyphs/HNG")
56
57 (defvar chise-wiki-glyph-cgi-url
58   "http://www.chise.org/chisewiki/glyph.cgi")
59
60 (defvar chise-wiki-displayed-features nil)
61
62 (defvar est-coded-charset-priority-list
63   '(; =ucs
64     =cns11643-1 =cns11643-2 =cns11643-3
65     =cns11643-4 =cns11643-5 =cns11643-6 =cns11643-7
66     =gb2312 =gb12345
67     =jis-x0208 =jis-x0208@1990
68     =jis-x0213-2
69     =jis-x0212
70     =adobe-japan1
71     =cbeta =jef-china3
72     =jis-x0213-1@2000 =jis-x0213-1@2004
73     =jis-x0208@1983 =jis-x0208@1978
74     =zinbun-oracle =>zinbun-oracle
75     =daikanwa
76     =gt =gt-k
77     =>>>adobe-japan1
78     =>>>jis-x0208 =>>>jis-x0213-1 =>>>jis-x0213-2
79     =>>jis-x0208 =>>jis-x0213-1 =>>jis-x0213-2
80     =>>adobe-japan1
81     =+>jis-x0208 =+>jis-x0213-1 =+>jis-x0213-2
82     =+>jis-x0208@1978
83     =+>adobe-japan1
84     =>jis-x0208 =>jis-x0213-1
85     =>>gt
86     =>ucs@iso =>ucs@unicode
87     =>ucs@jis =>ucs@cns =>ucs@ks
88     =>>ucs@iso =>>ucs@unicode
89     =>>ucs@jis =>>ucs@cns =>>ucs@ks
90     =>>>ucs@iso =>>>ucs@unicode
91     =>>>ucs@jis =>>>ucs@cns =>>>ucs@ks
92     ===ucs@iso
93     =ruimoku-v6
94     =big5
95     =big5-cdp
96     =>cbeta
97     =mj
98     ==mj
99     ===mj
100     =ucs-itaiji-001
101     =ucs-itaiji-002
102     =ucs-itaiji-003
103     =ucs@unicode
104     ==ucs@unicode
105     ===ucs@unicode
106     ==>ucs@bucs
107     ===daikanwa/+p
108     ===gt))
109
110 (defun decode-uri-string (string &optional coding-system)
111   (if (> (length string) 0)
112       (let ((i 0)
113             dest)
114         (setq string
115               (mapconcat (lambda (char)
116                            (if (eq char ?+)
117                                " "
118                              (char-to-string char)))
119                          string ""))
120         (while (string-match "%\\([0-9A-F][0-9A-F]\\)" string i)
121           (setq dest (concat dest
122                              (substring string i (match-beginning 0))
123                              (char-to-string
124                               (int-char
125                                (string-to-int (match-string 1 string) 16))))
126                 i (match-end 0)))
127         (decode-coding-string
128          (concat dest (substring string i))
129          coding-system))))
130
131 (defun www-feature-type (feature-name)
132   (or (char-feature-property feature-name 'type)
133       (let ((str (symbol-name feature-name)))
134         (cond
135          ((string-match "\\*note\\(@[^*]+\\)?$" str)
136           'stext)
137          ((string-match "\\*sources\\(@[^*]+\\)?$" str)
138           'domain-list)
139          ((string-match "\\*" str)
140           nil)
141          ((string-match "^\\(->\\|<-\\)" str)
142           'relation)
143          ((string-match "^ideographic-structure\\(@\\|$\\)" str)
144           'structure)
145          ))))
146
147 (defun www-feature-format (feature-name)
148   (or (char-feature-property feature-name 'presentation-format)
149       (char-feature-property feature-name 'format)
150       (let (fn parent ret)
151         (setq fn feature-name)
152         (while (and (setq parent (char-feature-name-parent fn))
153                     (null (setq ret
154                                 (char-feature-property
155                                  parent 'format))))
156           (setq fn parent))
157         ret)
158       '((name) " : " (value))))
159
160 (defun www-feature-value-format (feature-name)
161   (or (char-feature-property feature-name 'value-presentation-format)
162       (char-feature-property feature-name 'value-format)
163       (let (fn parent ret)
164         (setq fn feature-name)
165         (while (and (setq parent (char-feature-name-parent fn))
166                     (null (setq ret
167                                 (or (char-feature-property
168                                      parent 'value-presentation-format)
169                                     (char-feature-property
170                                      parent 'value-format)))))
171           (setq fn parent))
172         ret)
173       (let ((type (www-feature-type feature-name)))
174         (cond ((eq type 'relation)
175                'space-separated)
176               ((eq type 'structure)
177                'space-separated-ids)
178               ((eq type 'stext)
179                'wiki-text)
180               ))
181       (if (find-charset feature-name)
182           (if (and (= (charset-dimension feature-name) 2)
183                    (= (charset-chars feature-name) 94))
184               '("0x" (HEX)
185                 " (" (decimal) ") <" (ku-ten) "> " (prev-char) (next-char))
186             '("0x" (HEX) " (" (decimal) ") " (prev-char) (next-char))))
187       'space-separated))
188
189 (defun char-feature-name-at-domain (feature-name domain)
190   (if domain
191       (let ((name (symbol-name feature-name)))
192         (cond
193          ((string-match "@[^*]+$" name)
194           (intern (format "%s/%s" name domain))
195           )
196          (t
197           (intern (format "%s@%s" name domain))
198           )))
199     feature-name))
200
201 (defun char-feature-name-parent (feature-name)
202   (let ((name (symbol-name feature-name)))
203     (if (string-match "@[^@/*]+\\(/[^@/*]+\\)*$" name)
204         (intern (substring name 0 (car (last (match-data) 2)))))))
205
206 (defun char-feature-name-domain (feature-name)
207   (let ((name (symbol-name feature-name)))
208     (if (string-match "@[^@/*]+\\(/[^@/*]+\\)*$" name)
209         (intern (substring name (1+ (match-beginning 0)))))))
210
211 (defun char-feature-name-sans-versions (feature)
212   (let ((feature-name (symbol-name feature)))
213     (if (string-match "[@/]\\$rev=latest$" feature-name)
214         (intern (substring feature-name 0 (match-beginning 0)))
215       feature)))
216
217 (defun est-object-genre (object)
218   (if (characterp object)
219       'character
220     (concord-object-genre object)))
221
222 (defun www-get-feature-value (object feature)
223   (let ((latest-feature (char-feature-name-at-domain feature '$rev=latest)))
224     (cond
225      ((characterp object)
226       (mount-char-attribute-table latest-feature)
227       (or (char-feature object latest-feature)
228           (char-feature object feature))
229       )
230      (t
231       (or (condition-case nil
232               (concord-object-get object latest-feature)
233             (error nil))
234           (condition-case nil
235               (concord-object-get object feature)
236             (error nil)))
237       ))))
238
239 (defun get-previous-code-point (ccs code)
240   (let ((chars (charset-chars ccs))
241         (dim (charset-dimension ccs))
242         (i 0)
243         mask byte-min byte-max
244         bytes dest)
245     (cond
246      ((= chars 94)
247       (setq mask #x7F
248             byte-min 33
249             byte-max 126)
250       )
251      ((= chars 96)
252       (setq mask #x7F
253             byte-min 32
254             byte-max 127)
255       )
256      ((= chars 128)
257       (setq mask #x7F
258             byte-min 0
259             byte-max #xFF)
260       )
261      (t ; (= chars 256)
262       (setq mask #xFF
263             byte-min 0
264             byte-max #xFF)
265       ))
266     (setq bytes (make-vector dim 0))
267     (while (< i dim)
268       (aset bytes i (logand (lsh code (* i -8)) mask))
269       (setq i (1+ i)))
270     (setq i 0)
271     (while (and (< i dim)
272                 (progn
273                   (aset bytes i (1- (aref bytes i)))
274                   (< (aref bytes i) byte-min)))
275       (aset bytes i byte-max)
276       (setq i (1+ i)))
277     (when (< i dim)
278       (setq dest (aref bytes 0)
279             i 1)
280       (while (< i dim)
281         (setq dest (logior dest (lsh (aref bytes i) (* i 8)))
282               i (1+ i)))
283       dest)))
284
285 (defun get-next-code-point (ccs code)
286   (let ((chars (charset-chars ccs))
287         (dim (charset-dimension ccs))
288         (i 0)
289         mask byte-min byte-max
290         bytes dest)
291     (cond
292      ((= chars 94)
293       (setq mask #x7F
294             byte-min 33
295             byte-max 126)
296       )
297      ((= chars 96)
298       (setq mask #x7F
299             byte-min 32
300             byte-max 127)
301       )
302      ((= chars 128)
303       (setq mask #x7F
304             byte-min 0
305             byte-max #xFF)
306       )
307      (t ; (= chars 256)
308       (setq mask #xFF
309             byte-min 0
310             byte-max #xFF)
311       ))
312     (setq bytes (make-vector dim 0))
313     (while (< i dim)
314       (aset bytes i (logand (lsh code (* i -8)) mask))
315       (setq i (1+ i)))
316     (setq i 0)
317     (while (and (< i dim)
318                 (progn
319                   (aset bytes i (1+ (aref bytes i)))
320                   (> (aref bytes i) byte-max)))
321       (aset bytes i byte-min)
322       (setq i (1+ i)))
323     (when (< i dim)
324       (setq dest (aref bytes 0)
325             i 1)
326       (while (< i dim)
327         (setq dest (logior dest (lsh (aref bytes i) (* i 8)))
328               i (1+ i)))
329       dest)))
330
331 (defun find-previous-defined-code-point (ccs code)
332   (let ((i (get-previous-code-point ccs code))
333         char)
334     (cond
335      ((eq ccs '=jis-x0208)
336       (setq ccs '=jis-x0208@1990))
337      ((eq ccs '=jis-x0213-1)
338       (setq ccs '=jis-x0213-1@2004)))
339     (while (and i
340                 (>= i 0)
341                 (null (setq char (decode-char ccs i
342                                               (unless (eq ccs '=ucs)
343                                                 'defined-only)))))
344       (setq i (get-previous-code-point ccs i)))
345     char))
346
347 (defun find-next-defined-code-point (ccs code)
348   (let ((i (get-next-code-point ccs code))
349         max char)
350     (setq max (+ code 1000))
351     (cond
352      ((eq ccs '=jis-x0208)
353       (setq ccs '=jis-x0208@1990))
354      ((eq ccs '=jis-x0213-1)
355       (setq ccs '=jis-x0213-1@2004)))
356     (while (and i
357                 (<= i max)
358                 (null (setq char (decode-char ccs i
359                                               (unless (eq ccs '=ucs)
360                                                 'defined-only)))))
361       (setq i (get-next-code-point ccs i)))
362     char))
363
364
365 ;;; @ URI representation
366 ;;;
367
368 (defun est-uri-decode-feature-name-body (uri-feature)
369   (let ((len (length uri-feature))
370         (i 0)
371         ch dest)
372     (while (< i len)
373       (setq dest
374             (concat
375              dest
376              (if (eq (aref uri-feature i) ?\.)
377                  (if (and (< (+ i 2) len)
378                           (eq (aref uri-feature (+ i 2)) ?\.))
379                      (prog1
380                          (cond
381                           ((eq (setq ch (aref uri-feature (1+ i))) ?\.)
382                            "/")
383                           ((eq ch ?-)
384                            "*")
385                           (t
386                            (substring uri-feature i (+ i 3))
387                            ))
388                        (setq i (+ i 3)))
389                    (setq i (1+ i))
390                    ".")
391                (prog1
392                    (char-to-string (aref uri-feature i))
393                  (setq i (1+ i)))))))
394     dest))
395
396 (defun est-uri-encode-feature-name-body (feature)
397   (mapconcat (lambda (c)
398                (cond ((eq c ?*)
399                       ".-.")
400                      ((eq c ?/)
401                       "...")
402                      (t (char-to-string c))))
403              feature ""))
404
405 (defun www-uri-decode-feature-name (uri-feature)
406   (let (feature)
407     (setq uri-feature (decode-uri-string uri-feature 'utf-8-mcs-er))
408     (cond
409      ((string-match "^from\\." uri-feature)
410       (intern (format "<-%s"
411                       (est-uri-decode-feature-name-body
412                        (substring uri-feature (match-end 0)))))
413       )
414      ((string-match "^to\\." uri-feature)
415       (intern (format "->%s"
416                       (est-uri-decode-feature-name-body
417                        (substring uri-feature (match-end 0)))))
418       )
419      ((string-match "^rep\\." uri-feature)
420       (intern (format "=%s"
421                       (est-uri-decode-feature-name-body
422                        (substring uri-feature (match-end 0)))))
423       )
424      ((string-match "^rep[2i]\\." uri-feature)
425       (intern (format "===%s"
426                       (est-uri-decode-feature-name-body
427                        (substring uri-feature (match-end 0)))))
428       )
429      ((string-match "^g\\." uri-feature)
430       (intern (format "=>>%s"
431                       (est-uri-decode-feature-name-body
432                        (substring uri-feature (match-end 0)))))
433       )
434      ((string-match "^g[i2]\\." uri-feature)
435       (intern (format "==%s"
436                       (est-uri-decode-feature-name-body
437                        (substring uri-feature (match-end 0)))))
438       )
439      ((string-match "^gi\\([0-9]+\\)\\." uri-feature)
440       (intern (format "=>>%s%s"
441                       (make-string (string-to-int
442                                     (match-string 1 uri-feature))
443                                    ?>)
444                       (est-uri-decode-feature-name-body
445                        (substring uri-feature (match-end 0)))))
446       )
447      ((string-match "^o\\." uri-feature)
448       (intern (format "=+>%s"
449                       (est-uri-decode-feature-name-body
450                        (substring uri-feature (match-end 0)))))
451       )
452      ((string-match "^a\\." uri-feature)
453       (intern (format "=>%s"
454                       (est-uri-decode-feature-name-body
455                        (substring uri-feature (match-end 0)))))
456       )
457      ((string-match "^a\\([0-9]+\\)\\." uri-feature)
458       (intern (format "%s>%s"
459                       (make-string (string-to-int
460                                     (match-string 1 uri-feature))
461                                    ?=)
462                       (est-uri-decode-feature-name-body
463                        (substring uri-feature (match-end 0)))))
464       )
465      ((and (setq uri-feature (est-uri-decode-feature-name-body uri-feature))
466            (setq feature (intern (format "=>%s" uri-feature)))
467            (find-charset feature))
468       feature)
469      ((and (setq feature (intern (format "=>>%s" uri-feature)))
470            (find-charset feature))
471       feature)
472      ((and (setq feature (intern (format "=>>>%s" uri-feature)))
473            (find-charset feature))
474       feature)
475      ((and (setq feature (intern (format "=%s" uri-feature)))
476            (find-charset feature))
477       feature)
478      (t (intern uri-feature)))))
479
480 (defun www-uri-encode-feature-name (feature-name)
481   (setq feature-name (symbol-name feature-name))
482   (cond
483    ((string-match "^=\\+>\\([^=>]+\\)" feature-name)
484     (concat "o."
485             (est-uri-encode-feature-name-body
486              (substring feature-name (match-beginning 1))))
487     )
488    ((string-match "^=\\([^=>]+\\)" feature-name)
489     (concat "rep."
490             (est-uri-encode-feature-name-body
491              (substring feature-name (match-beginning 1))))
492     )
493    ((string-match "^==\\([^=>]+\\)" feature-name)
494     (concat "g2."
495             (est-uri-encode-feature-name-body
496              (substring feature-name (match-beginning 1))))
497     )
498    ((string-match "^===\\([^=>]+\\)" feature-name)
499     (concat "repi."
500             (est-uri-encode-feature-name-body
501              (substring feature-name (match-beginning 1))))
502     )
503    ((string-match "^=>>\\([^=>]+\\)" feature-name)
504     (concat "g."
505             (est-uri-encode-feature-name-body
506              (substring feature-name (match-beginning 1))))
507     )
508    ((string-match "^=>>>\\([^=>]+\\)" feature-name)
509     (concat "gi."
510             (est-uri-encode-feature-name-body
511              (substring feature-name (match-beginning 1))))
512     )
513    ((string-match "^=>>\\(>+\\)" feature-name)
514     (format "gi%d.%s"
515             (length (match-string 1 feature-name))
516             (est-uri-encode-feature-name-body
517              (substring feature-name (match-end 1))))
518     )
519    ((string-match "^=>\\([^=>]+\\)" feature-name)
520     (concat "a."
521             (est-uri-encode-feature-name-body
522              (substring feature-name (match-beginning 1))))
523     )
524    ((string-match "^\\(=+\\)>" feature-name)
525     (format "a%d.%s"
526             (length (match-string 1 feature-name))
527             (est-uri-encode-feature-name-body
528              (substring feature-name (match-end 0))))
529     )
530    ((string-match "^->" feature-name)
531     (concat "to."
532             (est-uri-encode-feature-name-body
533              (substring feature-name (match-end 0))))
534     )
535    ((string-match "^<-" feature-name)
536     (concat "from."
537             (est-uri-encode-feature-name-body
538              (substring feature-name (match-end 0))))
539     )
540    (t (est-uri-encode-feature-name-body feature-name))))
541
542 (defun www-uri-make-feature-name-url (uri-genre uri-feature-name uri-object)
543   (if est-hide-cgi-mode
544       (format "../feature/%s&%s/%s"
545               uri-feature-name uri-genre uri-object)
546     (format "%s?feature=%s&%s=%s"
547             chise-wiki-view-url uri-feature-name uri-genre uri-object)))
548
549 (defun www-uri-decode-object (genre char-rep)
550   (let (ccs cpos)
551     (cond
552      ((string-match (if est-hide-cgi-mode
553                         "\\(%3D\\|=\\|%3A\\|:\\)"
554                       "\\(%3A\\|:\\)") char-rep)
555       (setq ccs (substring char-rep 0 (match-beginning 0))
556             cpos (substring char-rep (match-end 0)))
557       (setq ccs (www-uri-decode-feature-name ccs))
558       (setq cpos (est-uri-decode-feature-name-body cpos))
559       (cond
560        ((string-match "^0x" cpos)
561         (setq cpos
562               (string-to-number (substring cpos (match-end 0)) 16))
563         )
564        (t
565         (setq cpos (car (read-from-string
566                          (decode-uri-string
567                           cpos file-name-coding-system))))
568         ))
569       (if (and (eq genre 'character)
570                (numberp cpos))
571           (decode-char ccs cpos)
572         (concord-decode-object ccs cpos genre))
573       )
574      (t
575       (setq char-rep (decode-uri-string char-rep 'utf-8-mcs-er))
576       (cond
577        ((eq genre 'character)
578         (when (= (length char-rep) 1)
579           (aref char-rep 0))
580         )
581        ((eq genre 'feature)
582         (concord-decode-object
583          '=id (www-uri-decode-feature-name char-rep) 'feature)
584         )
585        (t
586         (concord-decode-object
587          '=id (car (read-from-string char-rep)) genre)
588         ))))))
589
590 (defun www-uri-encode-object (object)
591   (if (characterp object)
592       (if (encode-char object '=ucs)
593           (mapconcat
594            (lambda (byte)
595              (format "%%%02X" byte))
596            (encode-coding-string (char-to-string object) 'utf-8-mcs-er)
597            "")
598         (let ((ccs-list est-coded-charset-priority-list)
599               ccs ret)
600           (while (and ccs-list
601                       (setq ccs (pop ccs-list))
602                       (not (setq ret (encode-char object ccs 'defined-only)))))
603           (cond (ret
604                  (format (if est-hide-cgi-mode
605                              "%s=0x%X"
606                            "%s:0x%X")
607                          (www-uri-encode-feature-name ccs)
608                          ret))
609                 ((and (setq ccs (car (split-char object)))
610                       (setq ret (encode-char object ccs)))
611                  (format (if est-hide-cgi-mode
612                              "%s=0x%X"
613                            "%s:0x%X")
614                          (www-uri-encode-feature-name ccs)
615                          ret))
616                 (t
617                  (format (if est-hide-cgi-mode
618                              "system-char-id=0x%X"
619                            "system-char-id:0x%X")
620                          (encode-char object 'system-char-id))
621                  ))))
622     (format (if est-hide-cgi-mode
623                 "rep.id=%s"
624               "rep.id:%s")
625             (est-uri-encode-feature-name-body
626              (format "%s" (concord-object-id object))))))
627
628 (defun est-format-object (object &optional readable)
629   (if (characterp object)
630       (char-to-string object)
631     (let ((ret (or (if readable
632                        (or (concord-object-get object 'name)
633                            (concord-object-get object '=name)
634                            (concord-object-get object 'title)))
635                    (concord-object-id object))))
636       (format "%s" ret))))
637
638 (defun www-uri-make-object-url (object &optional uri-object)
639   (if est-hide-cgi-mode
640       (format "%s/%s/%s"
641               est-view-url-prefix
642               (est-object-genre object)
643               (or uri-object
644                   (www-uri-encode-object object)))
645     (format "%s?%s=%s"
646             chise-wiki-view-url
647             (est-object-genre object)
648             (or uri-object
649                 (www-uri-encode-object object)))))
650
651
652 ;;; @ Feature name presentation
653 ;;;
654
655 (defun www-format-feature-name-default (feature-name)
656   (mapconcat
657    #'capitalize
658    (split-string
659     (symbol-name feature-name)
660     "-")
661    " "))
662
663 (defun www-format-feature-name-as-metadata (feature-name &optional lang)
664   (let ((str (symbol-name feature-name))
665         base meta)
666     (cond
667      ((string-match "\\*[^*]+$" str)
668       (setq base (substring str 0 (match-beginning 0))
669             meta (substring str (match-beginning 0)))
670       (concat (www-format-feature-name* (intern base) lang)
671               meta))
672      (t
673       (www-format-feature-name-default feature-name)
674       ))))
675
676 (defun www-format-feature-name-as-rel-to (feature-name)
677   (concat "\u2192" (substring (symbol-name feature-name) 2)))
678
679 (defun www-format-feature-name-as-rel-from (feature-name)
680   (concat "\u2190" (substring (symbol-name feature-name) 2)))
681
682 (defun www-format-feature-name-as-CCS (feature-name)
683   (let* ((rest
684           (split-string
685            (symbol-name feature-name)
686            "-"))
687          (dest (upcase (pop rest))))
688     (when (string-match "^=+>*" dest)
689       (setq dest (concat (substring dest 0 (match-end 0))
690                          " "
691                          (substring dest (match-end 0)))))
692     (cond
693      (rest
694       (while (cdr rest)
695         (setq dest (concat dest " " (upcase (pop rest)))))
696       (if (string-match "^[0-9]+$" (car rest))
697           (concat dest "-" (car rest))
698         (concat dest " " (upcase (car rest))))
699       )
700      (t dest))))
701
702 (defun www-format-feature-name* (feature-name &optional lang)
703   (let (name fn parent ret)
704     (cond
705      ((or (and lang
706                (char-feature-property
707                 feature-name
708                 (intern (format "name@%s" lang))))
709           (char-feature-property
710            feature-name 'name)))
711      ((and (setq name (symbol-name feature-name))
712            (string-match "\\*" name))
713       (www-format-feature-name-as-metadata feature-name lang))
714      (t
715       (setq fn feature-name)
716       (while (and (setq parent (char-feature-name-parent fn))
717                   (null (setq ret
718                               (or (and lang
719                                        (char-feature-property
720                                         parent
721                                         (intern (format "name@%s" lang))))
722                                   (char-feature-property
723                                    parent 'name)))))
724         (setq fn parent))
725       (cond
726        (ret
727         (concat ret (substring (symbol-name feature-name)
728                                (length (symbol-name parent)))))
729        ((find-charset feature-name)
730         (www-format-feature-name-as-CCS feature-name))
731        ((string-match "^\\(->\\)" name)
732         (www-format-feature-name-as-rel-to feature-name))
733        ((string-match "^\\(<-\\)" name)
734         (www-format-feature-name-as-rel-from feature-name))
735        (t
736         (www-format-feature-name-default feature-name)
737         ))
738       ))))
739
740 (defun www-format-feature-name (feature-name &optional lang)
741   (www-format-encode-string
742    (www-format-feature-name* feature-name lang)))
743
744
745 ;;; @ HTML generator
746 ;;;
747
748 (defvar www-format-char-img-style "vertical-align:bottom;")
749
750 (defun www-format-encode-string (string &optional without-tags as-body)
751   (with-temp-buffer
752     (insert string)
753     (let (plane code subcode start end char variants ret rret)
754       (when as-body
755         (goto-char (point-min))
756         (while (search-forward "&" nil t)
757           (replace-match "&amp;" nil t)))
758       (goto-char (point-min))
759       (while (search-forward "<" nil t)
760         (replace-match "&lt;" nil t))
761       (goto-char (point-min))
762       (while (search-forward ">" nil t)
763         (replace-match "&gt;" nil t))
764       (if without-tags
765           (encode-coding-region (point-min)(point-max) 'utf-8-mcs-er)
766         (let ((coded-charset-entity-reference-alist
767                (list*
768                 '(=gt                   "GT-" 5 d)
769                 '(=mj                    "MJ" 6 d)
770                 '(=hanyo-denshi/ja   "HD-JA-" 4 X)
771                 '(=hanyo-denshi/jb   "HD-JB-" 4 X)
772                 '(=hanyo-denshi/jc   "HD-JC-" 4 X)
773                 '(=hanyo-denshi/jd   "HD-JD-" 4 X)
774                 '(=hanyo-denshi/ft   "HD-FT-" 4 X)
775                 '(=hanyo-denshi/ia   "HD-IA-" 4 X)
776                 '(=hanyo-denshi/ib   "HD-IB-" 4 X)
777                 '(=hanyo-denshi/hg   "HD-HG-" 4 X)
778                 '(=hanyo-denshi/ip   "HD-IP-" 4 X)
779                 '(=hanyo-denshi/jt   "HD-JT-" 4 X)
780                 '(=hanyo-denshi/ks   "HD-KS-" 6 d)
781                 '(=>>hanyo-denshi/ja "G-HD-JA-" 4 X)
782                 '(=>>hanyo-denshi/jb "G-HD-JB-" 4 X)
783                 '(=>>hanyo-denshi/jc "G-HD-JC-" 4 X)
784                 '(=>>hanyo-denshi/jd "G-HD-JD-" 4 X)
785                 '(=>>hanyo-denshi/ft "G-HD-FT-" 4 X)
786                 '(=>>hanyo-denshi/ia "G-HD-IA-" 4 X)
787                 '(=>>hanyo-denshi/ib "G-HD-IB-" 4 X)
788                 '(=>>hanyo-denshi/hg "G-HD-HG-" 4 X)
789                 '(=>>hanyo-denshi/ip "G-HD-IP-" 4 X)
790                 '(=>>hanyo-denshi/jt "G-HD-JT-" 4 X)
791                 '(=>>hanyo-denshi/ks "G-HD-KS-" 6 d)
792                 '(==mj                  "g2-MJ" 6 d)
793                 '(==hanyo-denshi/ja "g2-HD-JA-" 4 X)
794                 '(==hanyo-denshi/jb "g2-HD-JB-" 4 X)
795                 '(==hanyo-denshi/jc "g2-HD-JC-" 4 X)
796                 '(==hanyo-denshi/jd "g2-HD-JD-" 4 X)
797                 '(==hanyo-denshi/ft "g2-HD-FT-" 4 X)
798                 '(==hanyo-denshi/ia "g2-HD-IA-" 4 X)
799                 '(==hanyo-denshi/ib "g2-HD-IB-" 4 X)
800                 '(==hanyo-denshi/hg "g2-HD-HG-" 4 X)
801                 '(==hanyo-denshi/ip "g2-HD-IP-" 4 X)
802                 '(==hanyo-denshi/jt "g2-HD-JT-" 4 X)
803                 '(==hanyo-denshi/ks "g2-HD-KS-" 6 d)
804                 '(=cns11643-1           "C1-" 4 X)
805                 '(=cns11643-2           "C2-" 4 X)
806                 '(=cns11643-3           "C3-" 4 X)
807                 '(=cns11643-4           "C4-" 4 X)
808                 '(=cns11643-5           "C5-" 4 X)
809                 '(=cns11643-6           "C6-" 4 X)
810                 '(=cns11643-7           "C7-" 4 X)
811                 '(=adobe-japan1-6       "AJ1-" 5 d)
812                 '(=big5-cdp             "CDP-" 4 X)
813                 '(=gb2312               "G0-" 4 X)
814                 '(=gb12345              "G1-" 4 X)
815                 '(=jis-x0208@1990       "J90-" 4 X)
816                 '(=jis-x0212            "JSP-" 4 X)
817                 '(=cbeta                "CB" 5 d)
818                 '(=jis-x0208@1997       "J97-" 4 X)
819                 '(=jis-x0208@1978       "J78-" 4 X)
820                 '(=jis-x0208@1983       "J83-" 4 X)
821                 '(=ruimoku-v6           "RUI6-" 4 X)
822                 '(=zinbun-oracle        "ZOB-" 4 d)
823                 '(=jef-china3           "JC3-" 4 X)
824                 '(=ucs@unicode          "UU+" 4 X)
825                 '(=ucs@JP/hanazono  "hanaJU+" 4 X)
826                 '(==cns11643-1        "R-C1-" 4 X)
827                 '(==cns11643-2        "R-C2-" 4 X)
828                 '(==cns11643-3        "R-C3-" 4 X)
829                 '(==cns11643-4        "R-C4-" 4 X)
830                 '(==cns11643-5        "R-C5-" 4 X)
831                 '(==cns11643-6        "R-C6-" 4 X)
832                 '(==cns11643-7        "R-C7-" 4 X)
833                 '(=hanziku-1         "HZK01-" 4 X)
834                 '(=hanziku-2         "HZK02-" 4 X)
835                 '(=hanziku-3         "HZK03-" 4 X)
836                 '(=hanziku-4         "HZK04-" 4 X)
837                 '(=hanziku-5         "HZK05-" 4 X)
838                 '(=hanziku-6         "HZK06-" 4 X)
839                 '(=hanziku-7         "HZK07-" 4 X)
840                 '(=hanziku-8         "HZK08-" 4 X)
841                 '(=hanziku-9         "HZK09-" 4 X)
842                 '(=hanziku-10        "HZK10-" 4 X)
843                 '(=hanziku-11        "HZK11-" 4 X)
844                 '(=hanziku-12        "HZK12-" 4 X)
845                 '(=big5                  "B-" 4 X)
846                 '(=daikanwa              "M-" 5 d)
847                 coded-charset-entity-reference-alist)))
848           (encode-coding-region (point-min)(point-max) 'utf-8-mcs-er)
849
850           (goto-char (point-min))
851           (while (re-search-forward "&\\(A-\\|G-\\|g2-\\)?CB\\([0-9]+\\);" nil t)
852             (setq code (string-to-int (match-string 2)))
853             (replace-match
854              (format "<img alt=\"CB%05d\" src=\"%s/cb-gaiji/%02d/CB%05d.gif\"
855 style=\"%s\">"
856                      code
857                      chise-wiki-bitmap-glyphs-url
858                      (/ code 1000) code
859                      www-format-char-img-style)
860              t 'literal))
861
862           (goto-char (point-min))
863           (while (re-search-forward "&\\(o-\\|G-\\|g2-\\|R-\\)?J\\(78\\|83\\|90\\|97\\|SP\\)-\\([0-9A-F][0-9A-F][0-9A-F][0-9A-F]\\);" nil t)
864             (setq plane (match-string 2)
865                   code (string-to-int (match-string 3) 16))
866             (replace-match
867              (format "<img alt=\"J%s-%04X\" src=\"%s/JIS-%s/%02d-%02d.gif\"
868 style=\"%s\">"
869                      plane code
870                      chise-wiki-bitmap-glyphs-url
871                      plane
872                      (- (lsh code -8) 32)
873                      (- (logand code 255) 32)
874                      www-format-char-img-style)
875              t 'literal))
876
877           (goto-char (point-min))
878           (while (re-search-forward "&\\(o-\\|G-\\|g2-\\|R-\\)?J0-\\([0-9A-F][0-9A-F][0-9A-F][0-9A-F]\\);" nil t)
879             (setq code (string-to-int (match-string 2) 16))
880             (replace-match
881              (format "<img alt=\"J0-%04X\" src=\"%s/JIS-90/%02d-%02d.gif\"
882 style=\"%s\">"
883                      code
884                      chise-wiki-bitmap-glyphs-url
885                      (- (lsh code -8) 32)
886                      (- (logand code 255) 32)
887                      www-format-char-img-style)
888              t 'literal))
889
890           (goto-char (point-min))
891           (while (re-search-forward "&\\(o-\\|G-\\|g2-\\|R-\\)?HD-\\(JA\\|JB\\|JC\\|JD\\|FT\\|IA\\|IB\\|HG\\)-\\([0-9A-F][0-9A-F][0-9A-F][0-9A-F]\\);" nil t)
892             (setq plane (match-string 2)
893                   code (string-to-int (match-string 3) 16))
894             (replace-match
895              (format "<img alt=\"HD-%s-%04X\" src=\"%s/IVD/HanyoDenshi/%s%02d%02d.png\"
896 style=\"%s\">"
897                      plane code
898                      chise-wiki-bitmap-glyphs-url
899                      plane
900                      (- (lsh code -8) 32)
901                      (- (logand code 255) 32)
902                      www-format-char-img-style)
903              t 'literal))
904
905           (goto-char (point-min))
906           (while (re-search-forward "&\\(o-\\|G-\\|g2-\\|R-\\)?HD-\\(IP\\|JT\\)-\\([0-9A-F][0-9A-F][0-9A-F][0-9A-F]\\);" nil t)
907             (setq plane (match-string 2)
908                   code (string-to-int (match-string 3) 16))
909             (replace-match
910              (format "<img alt=\"HD-%s-%04X\" src=\"%s/IVD/HanyoDenshi/%s%04X.png\"
911 style=\"%s\">"
912                      plane code
913                      chise-wiki-bitmap-glyphs-url
914                      plane code
915                      www-format-char-img-style)
916              t 'literal))
917
918           (goto-char (point-min))
919           (while (re-search-forward "&\\(o-\\|G-\\|g2-\\|R-\\)?HD-KS-\\([0-9]+\\);" nil t)
920             (setq code (string-to-int (match-string 2)))
921             (replace-match
922              (format "<img alt=\"HD-KS%06d\" src=\"%s/IVD/HanyoDenshi/KS%06d.png\"
923 style=\"vertical-align:middle\">"
924                      code
925                      chise-wiki-bitmap-glyphs-url
926                      code
927                      www-format-char-img-style)
928              t 'literal))
929
930           (goto-char (point-min))
931           (while (re-search-forward "&G\\([01]\\)-\\([0-9A-F][0-9A-F][0-9A-F][0-9A-F]\\);" nil t)
932             (setq plane (string-to-int (match-string 1))
933                   code (string-to-int (match-string 2) 16))
934             (replace-match
935              (format "<img alt=\"GB%d-%04X\" src=\"%s/GB%d/%02d-%02d.gif\"
936 style=\"%s\">"
937                      plane code
938                      chise-wiki-bitmap-glyphs-url
939                      plane
940                      (- (lsh code -8) 32)
941                      (- (logand code 255) 32)
942                      www-format-char-img-style)
943              t 'literal))
944
945           (goto-char (point-min))
946           (while (re-search-forward "&\\(R-\\)?C\\([1-7]\\)-\\([0-9A-F][0-9A-F][0-9A-F][0-9A-F]\\);" nil t)
947             (setq plane (string-to-int (match-string 2))
948                   code (string-to-int (match-string 3) 16))
949             (replace-match
950              (format "<img alt=\"CNS%d-%04X\" src=\"%s/CNS%d/%04X.gif\"
951 style=\"%s\">"
952                      plane code
953                      chise-wiki-bitmap-glyphs-url
954                      plane code
955                      www-format-char-img-style)
956              t 'literal))
957
958           (goto-char (point-min))
959           (while (re-search-forward "&\\(R-\\)?JC3-\\([0-9A-F][0-9A-F][0-9A-F][0-9A-F]\\);" nil t)
960             (setq code (string-to-int (match-string 2) 16))
961             (replace-match
962              (format "<img alt=\"JC3-%04X\" src=\"http://kanji.zinbun.kyoto-u.ac.jp/db/CHINA3/Gaiji/%04x.gif\">"
963                      code code)
964              t 'literal))
965
966           (goto-char (point-min))
967           (while (re-search-forward "&\\(A-\\)?ZOB-\\([0-9]+\\);" nil t)
968             (setq code (string-to-int (match-string 2)))
969             (replace-match
970              (format "<img alt=\"ZOB-%04d\" src=\"%s/ZOB-1968/%04d.png\"
971 style=\"vertical-align:middle\">"
972                      code
973                      chise-wiki-bitmap-glyphs-url
974                      code
975                      www-format-char-img-style)
976              t 'literal))
977
978           (goto-char (point-min))
979           (while (re-search-forward "&HNG\\([0-9]+\\)-\\([0-9][0-9][0-9][0-9]\\)\\([0-9]\\);" nil t)
980             (setq plane (match-string 1)
981                   code (string-to-int (match-string 2))
982                   subcode (string-to-int (match-string 3)))
983             (setq subcode
984                   (if (eq subcode 0)
985                       ""
986                     (char-to-string (decode-char 'ascii (+ 96 subcode)))))
987             (replace-match
988              (format
989               "<div class=\"tooltip\"><img alt=\"HNG%s-%04d%s\" src=\"%s/%s/%04d%s.png\" style=\"
990 vertical-align:middle; width: 48px; height: 48px\"><span
991 class=\"tooltiptext\">%s</span></div>"
992               plane code subcode
993               chise-wiki-hng-bitmap-glyphs-url
994               plane code subcode
995               (charset-description
996                (car (find (format "HNG%s-" plane)
997                           coded-charset-entity-reference-alist
998                           :test (lambda (key cell)
999                                   (string= key (nth 1 cell))))))
1000               )
1001              t 'literal))
1002
1003           (goto-char (point-min))
1004           (while (re-search-forward "&\\(o-\\|G-\\|g2-\\|R-\\)?AJ1-\\([0-9]+\\);" nil t)
1005             (setq code (string-to-int (match-string 2)))
1006             (replace-match
1007              (format "<img alt=\"AJ1-%05d\" src=\"%s/IVD/AdobeJapan1/CID+%d.png\"
1008 style=\"vertical-align:middle\">"
1009                      code
1010                      chise-wiki-bitmap-glyphs-url
1011                      code
1012                      www-format-char-img-style)
1013              t 'literal))
1014
1015           (goto-char (point-min))
1016           (while (re-search-forward "&\\(o-\\|G-\\|g2-\\|R-\\)?MJ\\([0-9]+\\);" nil t)
1017             (setq code (string-to-int (match-string 2)))
1018             (replace-match
1019              (format "<img alt=\"MJ%06d\" src=\"http://mojikiban.ipa.go.jp/search/MJ%06d\"
1020 style=\"vertical-align:middle; width: 48px; height: 48px\">"
1021                      code
1022                      code
1023                      www-format-char-img-style)
1024              t 'literal))
1025
1026           (goto-char (point-min))
1027           (while (re-search-forward "&\\(o-\\|G-\\|g2-\\)?IU[+-]\\([0-9A-F]+\\);" nil t)
1028             (setq code (string-to-int (match-string 2) 16))
1029             (replace-match
1030              (format "<img alt=\"u%04x\" src=\"http://glyphwiki.org/glyph/u%04x.100px.png\"
1031 style=\"vertical-align:middle; width: 48px; height: 48px\">"
1032                      code
1033                      code
1034                      www-format-char-img-style)
1035              t 'literal))
1036
1037           (goto-char (point-min))
1038           (while (re-search-forward "&U-i\\([0-9]+\\)\\+\\([0-9A-F]+\\);" nil t)
1039             (setq plane (string-to-int (match-string 1))
1040                   code (string-to-int (match-string 2) 16))
1041             (replace-match
1042              (format "<img alt=\"u%04x-itaiji-%03d\" src=\"http://glyphwiki.org/glyph/u%04x-itaiji-%03d.100px.png\"
1043 style=\"vertical-align:middle; width: 48px; height: 48px\">"
1044                      code
1045                      plane
1046                      code
1047                      plane
1048                      www-format-char-img-style)
1049              t 'literal))
1050
1051           (goto-char (point-min))
1052           (while (re-search-forward "&A-IWDSU\\+\\([0-9A-F]+\\);" nil t)
1053             (setq code (string-to-int (match-string 1) 16))
1054             (replace-match
1055              (format "<img alt=\"A-IWDSU+%04x\" src=\"http://glyphwiki.org/glyph/u%04x.100px.png\"
1056 style=\"vertical-align:middle; width: 48px; height: 48px\">"
1057                      code
1058                      code
1059                      www-format-char-img-style)
1060              t 'literal))
1061
1062           (goto-char (point-min))
1063           (while (re-search-forward "&U-v\\([0-9]+\\)\\+\\([0-9A-F]+\\);" nil t)
1064             (setq plane (string-to-int (match-string 1))
1065                   code (string-to-int (match-string 2) 16))
1066             (replace-match
1067              (format "<img alt=\"u%04x-itaiji-%03d\" src=\"http://glyphwiki.org/glyph/u%04x-var-%03d.100px.png\"
1068 style=\"vertical-align:middle; width: 48px; height: 48px\">"
1069                      code
1070                      plane
1071                      code
1072                      plane
1073                      www-format-char-img-style)
1074              t 'literal))
1075
1076           (goto-char (point-min))
1077           (while (re-search-forward "&\\(A-\\|G-\\|R-\\|g2-\\)?GT-\\([0-9]+\\);" nil t)
1078             (setq code (string-to-int (match-string 2)))
1079             (replace-match
1080              (format "<img alt=\"GT-%05d\" src=\"%s?char=GT-%05d\"
1081 style=\"%s\">"
1082                      code
1083                      chise-wiki-glyph-cgi-url
1084                      code
1085                      www-format-char-img-style)
1086              t 'literal))
1087
1088           (goto-char (point-min))
1089           (while (re-search-forward "&\\(G-\\)?GT-K\\([0-9]+\\);" nil t)
1090             (setq code (string-to-int (match-string 2)))
1091             (replace-match
1092              (format "<img alt=\"GT-K%05d\" src=\"%s?char=GT-K%05d\"
1093 style=\"%s\">"
1094                      code
1095                      chise-wiki-glyph-cgi-url
1096                      code
1097                      www-format-char-img-style)
1098              t 'literal))
1099
1100           (goto-char (point-min))
1101           (while (re-search-forward "&B-\\([0-9A-F]+\\);" nil t)
1102             (setq code (string-to-int (match-string 1) 16))
1103             (replace-match
1104              (format "<img alt=\"B-%04X\" src=\"%s?char=B-%04X\"
1105 style=\"%s\">"
1106                      code
1107                      chise-wiki-glyph-cgi-url
1108                      code
1109                      www-format-char-img-style)
1110              t 'literal))
1111
1112           (goto-char (point-min))
1113           (while (re-search-forward "&\\(G-\\|g2-\\|R-\\)?CDP-\\([0-9A-F]+\\);" nil t)
1114             (setq code (string-to-int (match-string 2) 16))
1115             (replace-match
1116              (format "<img alt=\"CDP-%04X\" src=\"%s?char=CDP-%04X\"
1117 style=\"%s\">"
1118                      code
1119                      chise-wiki-glyph-cgi-url
1120                      code
1121                      www-format-char-img-style)
1122              t 'literal))
1123
1124           (goto-char (point-min))
1125           (while (re-search-forward
1126                   "&\\(I-\\)?HZK\\(0[1-9]\\|1[0-2]\\)-\\([0-9A-F]+\\);" nil t)
1127             (setq plane (match-string 2)
1128                   code (string-to-int (match-string 3) 16))
1129             (replace-match
1130              (format "<img alt=\"HZK%s-%04X\" src=\"%s?char=HZK%s-%04X\"
1131 style=\"%s\">"
1132                      plane
1133                      code
1134                      chise-wiki-glyph-cgi-url
1135                      plane
1136                      code
1137                      www-format-char-img-style)
1138              t 'literal))
1139
1140           (goto-char (point-min))
1141           (while (re-search-forward "&\\(G-\\|g2-\\|R-\\)?RUI6-\\([0-9A-F]+\\);" nil t)
1142             (setq code (string-to-int (match-string 2) 16))
1143             (replace-match
1144              (format "<img alt=\"RUI6-%04X\" src=\"%s?char=RUI6-%04X\"
1145 style=\"vertical-align:middle\">"
1146                      code
1147                      chise-wiki-glyph-cgi-url
1148                      code
1149                      www-format-char-img-style)
1150              t 'literal))
1151
1152           (goto-char (point-min))
1153           (while (re-search-forward "&hanaJU\\+\\([0-9A-F]+\\);" nil t)
1154             (setq code (string-to-int (match-string 1) 16))
1155             (replace-match
1156              (format "<img alt=\"hanaJU+%04X\" src=\"%s?char=hana-JU+%04X\"
1157 style=\"vertical-align:middle\">"
1158                      code
1159                      chise-wiki-glyph-cgi-url
1160                      code
1161                      www-format-char-img-style)
1162              t 'literal))
1163
1164           (goto-char (point-min))
1165           (while (re-search-forward "&\\(A-\\|G-\\|g2-\\|R-\\)?\\(UU\\+\\|U-\\)\\([0-9A-F]+\\);" nil t)
1166             (setq code (string-to-int (match-string 3) 16))
1167             (replace-match
1168              (format "<img alt=\"UU+%04X\" src=\"http://www.unicode.org/cgi-bin/refglyph?24-%04X\"
1169 style=\"vertical-align:middle\">"
1170                      code
1171                      code
1172                      www-format-char-img-style)
1173              t 'literal))
1174
1175           (goto-char (point-min))
1176           (while (re-search-forward "&MCS-\\([0-9A-F]+\\);" nil t)
1177             (setq code (string-to-int (match-string 1) 16))
1178             (setq start (match-beginning 0)
1179                   end (match-end 0))
1180             (setq char (decode-char 'system-char-id code))
1181             (cond
1182              ((and (setq variants
1183                          (or (www-get-feature-value char '->subsumptive)
1184                              (www-get-feature-value char '->denotational)))
1185                    (progn
1186                      (while (and variants
1187                                  (setq ret (www-format-encode-string
1188                                             (char-to-string (car variants))))
1189                                  (string-match "&MCS-\\([0-9A-F]+\\);" ret))
1190                        (setq variants (cdr variants)))
1191                      ret))
1192               (unless (string-match "&MCS-\\([0-9A-F]+\\);" ret)
1193                 (goto-char start)
1194                 (delete-region start end)
1195                 (insert ret))
1196               )
1197              ((setq ret (or (www-get-feature-value char 'ideographic-combination)
1198                             (www-get-feature-value char 'ideographic-structure)))
1199               (setq ret
1200                     (mapconcat
1201                      (lambda (ch)
1202                        (if (listp ch)
1203                            (if (characterp (setq rret (find-char ch)))
1204                                (setq ch rret)))
1205                        (if (characterp ch)
1206                            (www-format-encode-string
1207                             (char-to-string ch) without-tags)
1208                          (www-format-encode-string
1209                           (format "%S" ch) without-tags)))
1210                      ret ""))
1211               (when ret
1212                 (goto-char start)
1213                 (delete-region start end)
1214                 (insert ret))
1215               )))
1216           ))
1217       ;; (goto-char (point-min))
1218       ;; (while (search-forward "&GT-" nil t)
1219       ;;   (replace-match "&amp;GT-" t 'literal))
1220       (buffer-string))))
1221
1222 (defun www-html-display-text (text)
1223   (princ
1224    (with-temp-buffer
1225      (insert text)
1226      (goto-char (point-min))
1227      (while (search-forward "<" nil t)
1228        (replace-match "&lt;" nil t))
1229      (goto-char (point-min))
1230      (while (search-forward ">" nil t)
1231        (replace-match "&gt;" nil t))
1232      (goto-char (point-min))
1233      (while (re-search-forward "\\[\\[\\([^]|[]+\\)|\\([^][]+\\)\\]\\]" nil t)
1234        (replace-match
1235         (format "<a href=\"%s\">%s</a>"
1236                 (match-string 2)
1237                 (match-string 1))
1238         nil t))
1239      (encode-coding-region (point-min)(point-max) 'utf-8-mcs-er)
1240      (goto-char (point-min))
1241      (while (search-forward "&GT-" nil t)
1242        (replace-match "&amp;GT-" nil t))
1243      (buffer-string))))
1244
1245 (defun www-html-display-paragraph (text)
1246   (princ "<p>")
1247   (www-html-display-text text)
1248   (princ "</p>\n"))
1249
1250
1251 ;;; @ for GlyphWiki
1252 ;;;
1253
1254 (defvar coded-charset-GlyphWiki-id-alist
1255   '((===adobe-japan1-0  "aj1-"  5 d nil)
1256     (===adobe-japan1-1  "aj1-"  5 d nil)
1257     (===adobe-japan1-2  "aj1-"  5 d nil)
1258     (===adobe-japan1-3  "aj1-"  5 d nil)
1259     (===adobe-japan1-4  "aj1-"  5 d nil)
1260     (===adobe-japan1-5  "aj1-"  5 d nil)
1261     (===adobe-japan1-6  "aj1-"  5 d nil)
1262     (===ucs@jis         "u"     4 x nil)
1263     (===daikanwa        "dkw-"  5 d nil)
1264     (===ucs@ks          "u"     4 x "-k")
1265     (=ucs-var-001       "u"     4 x "-var-001")
1266     (=ucs-var-002       "u"     4 x "-var-002")
1267     (=ucs-var-003       "u"     4 x "-var-003")
1268     (=ucs-itaiji-001    "u"     4 x "-itaiji-001")
1269     (=ucs-itaiji-002    "u"     4 x "-itaiji-002")
1270     (=ucs-itaiji-003    "u"     4 x "-itaiji-003")
1271     (=ucs-itaiji-084    "u"     4 x "-itaiji-084")
1272     (==adobe-japan1-0   "aj1-"  5 d nil)
1273     (==adobe-japan1-1   "aj1-"  5 d nil)
1274     (==adobe-japan1-2   "aj1-"  5 d nil)
1275     (==adobe-japan1-3   "aj1-"  5 d nil)
1276     (==adobe-japan1-4   "aj1-"  5 d nil)
1277     (==adobe-japan1-5   "aj1-"  5 d nil)
1278     (==adobe-japan1-6   "aj1-"  5 d nil)
1279     (==ucs@jis          "u"     4 x nil)
1280     (==ucs@iso          "u"     4 x nil)
1281     (==ucs@cns          "u"     4 x "-t")
1282     (==ucs@unicode      "u"     4 x "-us")
1283     (==daikanwa         "dkw-"  5 d nil)
1284     (==ucs@ks           "u"     4 x "-k")
1285     (==jis-x0208@1978   "j78-"  4 x nil)
1286     (==jis-x0208        "j90-"  4 x nil)
1287     (==jis-x0208@1990   "j90-"  4 x nil)
1288     (==jis-x0208@1983   "j83-"  4 x nil)
1289     (==cbeta           "cbeta-" 5 d nil)
1290     (=>>hanyo-denshi/ks "koseki-" 6 d nil)
1291     (=>>jis-x0208@1978  "j78-"  4 x nil)
1292     (=>>big5-cdp        "cdp-"  4 x nil)
1293     (=>>jis-x0208       "j90-"  4 x nil)
1294     (=>>jis-x0208@1990  "j90-"  4 x nil)
1295     (=>>jis-x0208@1983  "j83-"  4 x nil)
1296     (=>>daikanwa        "dkw-"  5 d nil)
1297     (=adobe-japan1-0    "aj1-"  5 d nil)
1298     (=adobe-japan1-1    "aj1-"  5 d nil)
1299     (=adobe-japan1-2    "aj1-"  5 d nil)
1300     (=adobe-japan1-3    "aj1-"  5 d nil)
1301     (=adobe-japan1-4    "aj1-"  5 d nil)
1302     (=adobe-japan1-5    "aj1-"  5 d nil)
1303     (=adobe-japan1-6    "aj1-"  5 d nil)
1304     (=decomposition@cid)
1305     (=decomposition@hanyo-denshi)
1306     (=hanyo-denshi/ks   "koseki-" 6 d nil)
1307     (=koseki            "koseki-" 6 d nil)
1308     (=ucs@jis           "u"     4 x nil)
1309     (=ucs@cns           "u"     4 x "-t")
1310     (=ucs@ks            "u"     4 x "-k")
1311     (=ucs@JP            "u"     4 x nil)
1312     (=ucs@gb            "u"     4 x "-g")
1313     (=ucs@iso           "u"     4 x "-u")
1314     (=ucs@unicode       "u"     4 x "-us")
1315     (=big5-cdp          "cdp-"  4 x nil)
1316     (=cbeta            "cbeta-" 5 d nil)
1317     (=big5-cdp-var-3    "cdp-"  4 x "-var-3")
1318     (=big5-cdp-var-5    "cdp-"  4 x "-var-5")
1319     (=jef-china3        "jc3-"  4 x nil)
1320     (=jis-x0212         "jsp-"  4 x nil)
1321     (=jis-x0213-1@2000  "jx1-2000-" 4 x nil)
1322     (=jis-x0213-1@2004  "jx1-2004-" 4 x nil)
1323     (=jis-x0213-2       "jx2-"  4 x nil)
1324     (=gt-k              "gt-k"  5 d nil)
1325     (=jis-x0208@1978/1pr "j78-" 4 x nil)
1326     (=jis-x0208@1978/-4pr "j78-" 4 x nil)
1327     (=jis-x0208@1978    "j78-"  4 x nil)
1328     (=+>jis-x0208@1978  "j78-"  4 x nil)
1329     (=+>jis-x0208       "j90-"  4 x nil)
1330     (=+>jis-x0208@1990  "j90-"  4 x nil)
1331     (=+>jis-x0208@1983  "j83-"  4 x nil)
1332     (=ucs               "u"     4 x nil)
1333     (=big5              "b-"    4 x nil)
1334     (=daikanwa          "dkw-"  5 d nil)
1335     (=gt                "gt-"   5 d nil)
1336     (=ks-x1001          "k0-"   4 x nil)
1337     (=cns11643-1        "c1-"   4 x nil)
1338     (=cns11643-2        "c2-"   4 x nil)
1339     (=cns11643-3        "c3-"   4 x nil)
1340     (=cns11643-4        "c4-"   4 x nil)
1341     (=cns11643-5        "c5-"   4 x nil)
1342     (=cns11643-6        "c6-"   4 x nil)
1343     (=cns11643-7        "c7-"   4 x nil)
1344     (=jis-x0208         "j90-"  4 x nil)
1345     (=jis-x0208@1990    "j90-"  4 x nil)
1346     (=jis-x0208@1983    "j83-"  4 x nil)
1347     ))
1348
1349 (defun char-GlyphWiki-id (char)
1350   (let ((rest coded-charset-GlyphWiki-id-alist)
1351         spec ret code)
1352     (while (and rest
1353                 (setq spec (pop rest))
1354                 (null (setq ret (char-feature char (car spec))))))
1355     (when ret
1356       (or
1357        (and (listp ret)
1358             (mapconcat #'char-GlyphWiki-id ret "-"))
1359        (and (memq (car spec) '(=ucs@unicode '=ucs@iso))
1360             (cond
1361              ((and (or (encode-char char '=jis-x0208@1990)
1362                        (encode-char char '=jis-x0212)
1363                        (encode-char char '=jis-x0213-1)
1364                        (encode-char char '=jis-x0213-2))
1365                    (setq code (encode-char char '=ucs@jis)))
1366               (format "u%04x" code)
1367               )
1368              ((and (or (encode-char char '=gb2312)
1369                        (encode-char char '=gb12345))
1370                    (setq code (encode-char char '=ucs@gb)))
1371               (format "u%04x-g" code)
1372               )
1373              ((and (or (encode-char char '=cns11643-1)
1374                        (encode-char char '=cns11643-2)
1375                        (encode-char char '=cns11643-3)
1376                        (encode-char char '=cns11643-4)
1377                        (encode-char char '=cns11643-5)
1378                        (encode-char char '=cns11643-6)
1379                        (encode-char char '=cns11643-7))
1380                    (setq code (encode-char char '=ucs@cns)))
1381               (format "u%04x-t" code)
1382               )
1383              ((and (encode-char char '=ks-x1001)
1384                    (setq code (encode-char char '=ucs@ks)))
1385               (format "u%04x-k" code)
1386               )))
1387        (format (format "%s%%0%d%s%s"
1388                        (nth 1 spec)
1389                        (nth 2 spec)
1390                        (nth 3 spec)
1391                        (or (nth 4 spec) ""))
1392                ret)))))
1393
1394
1395 ;;; @ End.
1396 ;;;
1397
1398 (provide 'cwiki-common)
1399
1400 ;;; cwiki-common.el ends here