(TAGS, tags): Include new lisp subdirectories.
[emacs.git] / leim / quail / lrt.el
blob76ae460dbb907b7e90261bae27e24b9250e572e7
1 ;;; quail/lrt.el --- Quail package for inputting Lao characters by LRT method
3 ;; Copyright (C) 1997 Electrotechnical Laboratory, JAPAN.
4 ;; Licensed to the Free Software Foundation.
6 ;; Keywords: multilingual, input method, Lao, LRT.
8 ;; This file is part of GNU Emacs.
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;; Code:
27 (require 'quail)
28 (require 'lao-util)
30 ;; LRT (Lao Roman Transcription) input method accepts the following
31 ;; key sequence:
32 ;; consonant [+ semi-vowel-sign-lo ] + vowel [+ maa-sakod ] [+ tone-mark ]
34 (eval-and-compile
36 ;; Upper vowels and tone-marks are put on the letter.
37 ;; Semi-vowel-sign-lo and lower vowels are put under the letter.
38 (defconst lrt-single-consonant-table
39 '(("k" . ?\e(1!\e(B)
40 ("kh" . ?\e(1"\e(B)
41 ("qh" . ?\e(1$\e(B)
42 ("ng" . ?\e(1'\e(B)
43 ("j" . ?\e(1(\e(B)
44 ("s" . ?\e(1J\e(B)
45 ("x" . ?\e(1*\e(B)
46 ("y" . ?\e(1-\e(B)
47 ("d" . ?\e(14\e(B)
48 ("t" . ?\e(15\e(B)
49 ("th" . ?\e(16\e(B)
50 ("dh" . ?\e(17\e(B)
51 ("n" . ?\e(19\e(B)
52 ("b" . ?\e(1:\e(B)
53 ("p" . ?\e(1;\e(B)
54 ("hp" . ?\e(1<\e(B)
55 ("fh" . ?\e(1=\e(B)
56 ("ph" . ?\e(1>\e(B)
57 ("f" . ?\e(1?\e(B)
58 ("m" . ?\e(1A\e(B)
59 ("gn" . ?\e(1B\e(B)
60 ("l" . ?\e(1E\e(B)
61 ("r" . ?\e(1C\e(B)
62 ("v" . ?\e(1G\e(B)
63 ("w" . ?\e(1G\e(B)
64 ("hh" . ?\e(1K\e(B)
65 ("O" . ?\e(1M\e(B)
66 ("h" . ?\e(1N\e(B)
67 ("nh" . ?\e(1|\e(B)
68 ("mh" . ?\e(1}\e(B)
69 ("lh" . ?\e0\e(1K\\e1\e(B)
72 ;; Semi-vowel-sign-lo is put under the first letter.
73 ;; Lower vowels are put under the last letter.
74 ;; Upper vowels and tone-marks are put on the last letter.
75 (defconst lrt-double-consonant-table
76 '(("ngh" . "\e(1K'\e(B")
77 ("yh" . "\e(1K]\e(B")
78 ("wh" . "\e(1KG\e(B")
79 ("hl" . "\e(1KE\e(B")
80 ("hy" . "\e(1K-\e(B")
81 ("hn" . "\e(1K9\e(B")
82 ("hm" . "\e(1KA\e(B")
85 (defconst lrt-semi-vowel-sign-lo
86 '("r" . ?\e(1\\e(B))
88 (defconst lrt-vowel-table
89 '(("a" "\e(1P\e(B" (0 ?\e(1P\e(B) (0 ?\e(1Q\e(B))
90 ("ar" "\e(1R\e(B" (0 ?\e(1R\e(B))
91 ("i" "\e(1T\e(B" (0 ?\e(1T\e(B))
92 ("ii" "\e(1U\e(B" (0 ?\e(1U\e(B))
93 ("eu" "\e(1V\e(B" (0 ?\e(1V\e(B))
94 ("ur" "\e(1W\e(B" (0 ?\e(1W\e(B))
95 ("u" "\e(1X\e(B" (0 ?\e(1X\e(B))
96 ("uu" "\e(1Y\e(B" (0 ?\e(1Y\e(B))
97 ("e" "\e(1`\e(B \e(1P\e(B" (?\e(1`\e(B 0 ?\e(1P\e(B) (?\e(1`\e(B 0 ?\e(1Q\e(B))
98 ("ee" "\e(1`\e(B" (?\e(1`\e(B 0))
99 ("ae" "\e(1a\e(B \e(1P\e(B" (?\e(1a\e(B 0 ?\e(1P\e(B) (?\e(1a\e(B 0 ?\e(1Q\e(B))
100 ("aa" "\e(1a\e(B" (?\e(1a\e(B 0))
101 ("o" "\e(1b\e(B \e(1P\e(B" (?\e(1b\e(B 0 ?\e(1P\e(B) (0 ?\e(1[\e(B) (?\e(1-\e(B ?\e(1b\e(B 0 ?\e(1Q\e(B) (?\e(1G\e(B ?\e(1b\e(B 0 ?\e(1Q\e(B))
102 ("oo" "\e(1b\e(B" (?\e(1b\e(B 0))
103 ("oe" "\e(1`\e(B \e(1RP\e(B" (?\e(1`\e(B 0 ?\e(1R\e(B ?\e(1P\e(B) (0 ?\e(1Q\e(B ?\e(1M\e(B))
104 ("or" "\e(1m\e(B" (0 ?\e(1m\e(B) (0 ?\e(1M\e(B))
105 ("er" "\e(1`\e(B \e(1T\e(B" (?\e(1`\e(B 0 ?\e(1T\e(B))
106 ("ir" "\e(1`\e(B \e(1U\e(B" (?\e(1`\e(B 0 ?\e(1U\e(B))
107 ("oua" "\e(1[GP\e(B" (0 ?\e(1[\e(B ?\e(1G\e(B ?\e(1P\e(B) (0 ?\e(1Q\e(B ?\e(1G\e(B))
108 ("ua" "\e(1[G\e(B" (0 ?\e(1[\e(B ?\e(1G\e(B) (0 ?\e(1G\e(B))
109 ("ie" "\e(1`Q]P\e(B" (?\e(1`\e(B 0 ?\e(1Q\e(B ?\e(1]\e(B ?\e(1P\e(B) (0 ?\e(1Q\e(B ?\e(1]\e(B))
110 ("ia" "\e(1`Q]\e(B" (?\e(1`\e(B 0 ?\e(1Q\e(B ?\e(1]\e(B) (0 ?\e(1]\e(B))
111 ("eua" "\e(1`VM\e(B" (?\e(1`\e(B 0 ?\e(1V\e(B ?\e(1M\e(B))
112 ("ea" "\e(1`WM\e(B" (?\e(1`\e(B 0 ?\e(1W\e(B ?\e(1M\e(B))
113 ("ai" "\e(1d\e(B" (?\e(1d\e(B 0))
114 ("ei" "\e(1c\e(B" (?\e(1c\e(B 0))
115 ("ow" "\e(1`[R\e(B" (?\e(1`\e(B 0 ?\e(1[\e(B ?\e(1R\e(B))
116 ("am" "\e(1S\e(B" (?\e(1S\e(B 0))))
118 ;; Maa-sakod is put at the tail.
119 (defconst lrt-maa-sakod-table
120 '((?k . ?\e(1!\e(B)
121 (?g . ?\e(1'\e(B)
122 (?y . ?\e(1-\e(B)
123 (?d . ?\e(14\e(B)
124 (?n . ?\e(19\e(B)
125 (?b . ?\e(1:\e(B)
126 (?m . ?\e(1A\e(B)
127 (?v . ?\e(1G\e(B)
128 (?w . ?\e(1G\e(B)
131 (defconst lrt-tone-mark-table
132 '(("'" . ?\e(1h\e(B)
133 ("\"" . ?\e(1i\e(B)
134 ("^" . ?\e(1j\e(B)
135 ("+" . ?\e(1k\e(B)
136 ("~" . ?\e(1l\e(B)))
138 ;; Return list of composing patterns for normal (without maa-sakod)
139 ;; key sequence and with-maa-sakod key sequence starting with single
140 ;; consonant C and optional SEMI-VOWEL.
141 (defun lrt-composing-pattern-single-c (c semi-vowel vowel-pattern)
142 (let* ((patterns (copy-sequence vowel-pattern))
143 (tail patterns)
144 place)
145 ;; Embed C and SEMI-VOWEL (if any) at the place of 0.
146 (while tail
147 ;; At first, make a copy.
148 (setcar tail (copy-sequence (car tail)))
149 ;; Then, do embedding.
150 (setq place (memq 0 (car tail)))
151 (setcar place c)
152 (if semi-vowel
153 (setcdr place (cons semi-vowel (cdr place))))
154 (setq tail (cdr tail)))
155 patterns))
157 ;; Return list of composing patterns for normal (without maa-sakod)
158 ;; key sequence and with-maa-sakod key sequence starting with double
159 ;; consonant STR and optional SEMI-VOWEL.
160 (defun lrt-composing-pattern-double-c (str semi-vowel vowel-pattern)
161 (let* ((patterns (copy-sequence vowel-pattern))
162 (tail patterns)
163 (chars (string-to-list str))
164 place)
165 ;; Embed C and SEMI-VOWEL (if any) at the place of 0.
166 (while tail
167 ;; At first, make a copy.
168 (setcar tail (copy-sequence (car tail)))
169 ;; Then, do embedding.
170 (setq place (memq 0 (car tail)))
171 (setcar place (car chars))
172 (setcdr place (cons (nth 1 chars) (cdr place)))
173 (if semi-vowel
174 ;; Embed SEMI-VOWEL in between CHARS.
175 (setcdr place (cons semi-vowel (cdr place))))
176 (setq tail (cdr tail)))
177 patterns))
179 ;; Return a string made of characters in CHAR-LIST while composing
180 ;; such characters as vowel-upper, vowel-lower, semi-vowel(lower),
181 ;; and tone-mark with the preceding base character.
182 (defun lrt-compose-string (char-list)
183 ;; Make a copy because the following work alters it.
184 (setq char-list (copy-sequence char-list))
185 (let ((i -1)
186 (l char-list))
187 (while l
188 (if (memq (get-char-code-property (car l) 'phonetic-type)
189 '(vowel-upper vowel-lower semivowel-lower tone))
190 (let (composed-char)
191 (if (< i 0)
192 ;; No preceding base character.
193 (error "Invalid CHAR-LIST: %s" char-list))
194 (setq composed-char
195 (string-to-char (compose-chars (nth i char-list) (car l))))
196 (setcar (nthcdr i char-list) composed-char)
197 (setq l (cdr l))
198 (setcdr (nthcdr i char-list) l))
199 (setq l (cdr l))
200 (setq i (1+ i))))
201 (concat (apply 'vector char-list))))
203 (defun lrt-compose-c-s-v (consonant semi-vowel vowel-pattern)
204 (let ((pattern-list
205 (if (integerp consonant)
206 (lrt-composing-pattern-single-c
207 consonant semi-vowel vowel-pattern)
208 (lrt-composing-pattern-double-c
209 consonant semi-vowel vowel-pattern))))
210 (cons (vector (lrt-compose-string (car pattern-list)))
211 (cons t pattern-list))))
215 (defun lrt-handle-maa-sakod ()
216 (interactive)
217 (if (= (length quail-current-key) 0)
218 (quail-self-insert-command)
219 (if (not (and quail-current-data (car quail-current-data)))
220 (progn
221 (setq quail-current-data nil)
222 (setq unread-command-events
223 (cons last-command-event unread-command-events))
224 (quail-terminate-translation))
225 (if (not (integerp last-command-event))
226 (error "Bogus calling sequence"))
227 (let* ((maa-sakod (cdr (assq last-command-event lrt-maa-sakod-table)))
228 (maa-sakod-pattern (append
229 (or (cdr (assq maa-sakod
230 (nthcdr 3 quail-current-data)))
231 (nth 2 quail-current-data)
232 (nth 1 quail-current-data))
233 (list maa-sakod))))
234 (quail-delete-region)
235 (setq quail-current-str (lrt-compose-string maa-sakod-pattern))
236 (insert quail-current-str)
237 (setq quail-current-key " ")
238 (quail-show-translations)
239 (setq quail-current-data (list nil maa-sakod-pattern))))))
241 (defun lrt-handle-tone-mark ()
242 (interactive)
243 (if (= (length quail-current-key) 0)
244 (quail-self-insert-command)
245 (if (not quail-current-data)
246 (progn
247 (setq unread-command-events
248 (cons last-command-event unread-command-events))
249 (quail-terminate-translation))
250 (if (not (integerp last-command-event))
251 (error "Bogus calling sequence"))
252 (let* ((tone-mark (cdr (assoc (char-to-string last-command-event)
253 lrt-tone-mark-table)))
254 (tone-mark-pattern
255 (if (car quail-current-data)
256 (copy-sequence (nth 1 quail-current-data))
257 ;; No need of copy because lrt-handle-maa-sakod should
258 ;; have already done it.
259 (nth 1 quail-current-data)))
260 (tail tone-mark-pattern)
261 place)
262 ;; Find a place to embed TONE-MARK. It should be after a
263 ;; single or double consonant.
264 (while (and tail (not place))
265 (if (and
266 ;; Skip `\e(1K\e(B', the first letter of double consonant.
267 (/= (car tail) ?\e(1K\e(B)
268 (eq (get-char-code-property (car tail) 'phonetic-type)
269 'consonant))
270 (progn
271 (setq place tail)
272 (setq tail (cdr tail))
273 (while (and tail
274 (memq (get-char-code-property (car tail)
275 'phonetic-type)
276 '(vowel-upper vowel-lower semivowel-lower)))
277 (setq place tail tail (cdr tail))))
278 (setq tail (cdr tail))))
279 ;; Embed TONE-MARK.
280 (setcdr place (cons tone-mark (cdr place)))
281 (quail-delete-region)
282 (insert (lrt-compose-string tone-mark-pattern))
283 (setq quail-current-data nil)
284 (quail-terminate-translation)))))
286 (defmacro lrt-generate-quail-map ()
287 `(quail-install-map
288 ',(let ((map (list nil))
289 (semi-vowel-key (car lrt-semi-vowel-sign-lo))
290 (semi-vowel-char (cdr lrt-semi-vowel-sign-lo))
291 l1 e1 l2 e2 pattern key)
292 ;; Single consonants.
293 (setq l1 lrt-single-consonant-table)
294 (while l1
295 (setq e1 (car l1))
296 (quail-defrule-internal (car e1) (cdr e1) map)
297 (quail-defrule-internal
298 (concat (car e1) semi-vowel-key)
299 (compose-string (format "%c%c" (cdr e1) semi-vowel-char))
300 map)
301 (setq l2 lrt-vowel-table)
302 (while l2
303 (setq e2 (car l2))
304 (setq key (concat (car e1) (car e2))
305 pattern (lrt-compose-c-s-v (cdr e1) nil (nthcdr 2 e2)))
306 (quail-defrule-internal key pattern map)
307 (quail-defrule-internal
308 (concat key " ")
309 (vector (concat (aref (car pattern) 0) " ")) map)
310 (setq key (concat (car e1) semi-vowel-key (car e2))
311 pattern (lrt-compose-c-s-v (cdr e1) semi-vowel-char
312 (nthcdr 2 e2)))
313 (quail-defrule-internal key pattern map)
314 (quail-defrule-internal
315 (concat key " ")
316 (vector (concat (aref (car pattern) 0) " ")) map)
317 (setq l2 (cdr l2)))
318 (setq l1 (cdr l1)))
320 ;; Double consonants.
321 (setq l1 lrt-double-consonant-table)
322 (while l1
323 (setq e1 (car l1))
324 (quail-defrule-internal (car e1) (vector (cdr e1)) map)
325 (quail-defrule-internal
326 (concat (car e1) semi-vowel-key)
327 (vector (concat (compose-string
328 (format "%c%c" (sref (cdr e1) 0) semi-vowel-char))
329 (substring (cdr e1) (charset-bytes 'lao))))
330 map)
331 (setq l2 lrt-vowel-table)
332 (while l2
333 (setq e2 (car l2))
334 (setq key (concat (car e1) (car e2))
335 pattern (lrt-compose-c-s-v (cdr e1) nil (nthcdr 2 e2)))
336 (quail-defrule-internal key pattern map)
337 (quail-defrule-internal
338 (concat key " ")
339 (vector (concat (aref (car pattern) 0) " ")) map)
340 (setq key (concat (car e1) semi-vowel-key (car e2))
341 pattern (lrt-compose-c-s-v (cdr e1) semi-vowel-char
342 (nthcdr 2 e2)))
343 (quail-defrule-internal key pattern map)
344 (quail-defrule-internal
345 (concat key " ")
346 (vector (concat (aref (car pattern) 0) " ")) map)
347 (setq l2 (cdr l2)))
348 (setq l1 (cdr l1)))
350 ;; Vowels.
351 (setq l1 lrt-vowel-table)
352 (while l1
353 (setq e1 (car l1) l1 (cdr l1))
354 (quail-defrule-internal (car e1) (vector (nth 1 e1)) map))
356 ;; Tone-marks.
357 (setq l1 lrt-tone-mark-table)
358 (while l1
359 (setq e1 (car l1) l1 (cdr l1))
360 (quail-defrule-internal (car e1) (cdr e1) map))
362 map)))
364 (quail-define-package
365 "lao-lrt" "Lao" "\e(1"\e(BR" t
366 "Lao input method using LRT (Lao Roman Transcription)"
367 '(("k" . lrt-handle-maa-sakod)
368 ("g" . lrt-handle-maa-sakod)
369 ("y" . lrt-handle-maa-sakod)
370 ("d" . lrt-handle-maa-sakod)
371 ("n" . lrt-handle-maa-sakod)
372 ("b" . lrt-handle-maa-sakod)
373 ("m" . lrt-handle-maa-sakod)
374 ("v" . lrt-handle-maa-sakod)
375 ("w" . lrt-handle-maa-sakod)
376 ("'" . lrt-handle-tone-mark)
377 ("\"" . lrt-handle-tone-mark)
378 ("^" . lrt-handle-tone-mark)
379 ("+" . lrt-handle-tone-mark)
380 ("~" . lrt-handle-tone-mark))
381 'forget-last-selection 'deterministic 'kbd-translate 'show-layout)
383 (lrt-generate-quail-map)