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