1 ;;; egg-mlh.el --- Modeless Conversion Facility in Egg Input
2 ;;; Method Architecture
4 ;; Copyright (C) 1997, 1998 Mule Project, Powered by Electrotechnical
6 ;; Project Leader: Satoru Tomura <tomura@etl.go.jp>
8 ;; Author: NIIBE Yutaka <gniibe@mri.co.jp>
9 ;; KATAYAMA Yoshio <kate@pfu.co.jp> ; Multilingual Enhancement
10 ;; Maintainer: NIIBE Yutaka <gniibe@mri.co.jp>
11 ;; Keywords: mule, multilingual, input method
13 ;; This file is part of EGG.
15 ;; EGG is free software; you can redistribute it and/or modify
16 ;; it under the terms of the GNU General Public License as published by
17 ;; the Free Software Foundation; either version 2, or (at your option)
20 ;; EGG is distributed in the hope that it will be useful,
21 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 ;; GNU General Public License for more details.
25 ;; You should have received a copy of the GNU General Public License
26 ;; along with GNU Emacs; see the file COPYING. If not, write to the
27 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
28 ;; Boston, MA 02111-1307, USA.
31 ;; Once written by NIIBE Yutaka in mlh-1.002 distribution.
32 ;; Then, assigned to Mule Project.
36 (defvar mlh-default-backend "wnn")
38 (defun mlh-space-bar-backward-henkan ()
39 "If the character preceding point is / (slash),
40 Do `mlh-backward-henkan'. Then, invoke appropriate conversion, if needed.
41 Or else, execute command that space-bar invokes usually."
43 (let ((henkan-begin nil)
45 (its-disable-special-action t))
46 (if (null egg-conversion-backend)
48 (setq egg-mode-preference nil)
49 (activate-input-method (concat "japanese-egg-" mlh-default-backend)))
51 (its-select-hiragana))
54 (if (or inhibit-henkan (= henkan-begin (point)))
56 (egg-convert-region henkan-begin (point)))
57 (setq this-command 'self-insert-command)
58 (call-interactively 'self-insert-command))))
60 (defvar mlh-punctuations nil)
63 (setq mlh-punctuations "!()?;:"))
65 (defvar mlh-conversion-scheme-table
82 (?d . mlh-user-defined-conversion)
93 ; (?n . mlh-no-conversion)
95 (?p . mlh-upcase-letter)
98 (?s . mlh-small-letter)
99 (?t . mlh-zhongwen-tw)
102 (?w . mlh-white-space)
106 (?H . mlh-hiragana-to-kanji)
107 (?L . mlh-lisp-expression)
108 (?W . mlh-zenkaku-white)
113 (defun mlh-zenkaku-white ()
115 (skip-chars-backward "0-9")
116 (mlh-backward-henkan)
118 (goto-char end-marker)
119 (backward-delete-char 2)
120 (let* ((str (buffer-substring beg (point)))
121 (val (string-to-int str)))
122 (delete-region beg (point))
126 (insert "
\e$B!!
\e(B")
127 (setq val (1- val))))
128 (if (null henkan-begin)
129 (setq henkan-begin beg)))
132 (goto-char end-marker)
133 (backward-delete-char 2)
135 (setq henkan-begin (point)))
137 (defun mlh-upcase-letter ()
139 (skip-chars-backward "a-zA-Z0-9")
140 (mlh-backward-henkan)
142 (goto-char end-marker)
143 (backward-delete-char 2)
144 (upcase-region beg (point))
145 (if (null henkan-begin)
146 (setq henkan-begin beg)))
148 (defun mlh-capitalize ()
150 (skip-chars-backward "a-zA-Z1-9")
151 (mlh-backward-henkan)
153 (goto-char end-marker)
154 (backward-delete-char 2)
155 (capitalize-region beg (point))
156 (if (null henkan-begin)
157 (setq henkan-begin beg)))
159 (defun mlh-jis-code ()
161 (skip-chars-backward "0-9a-fA-F")
162 (mlh-backward-henkan)
164 (goto-char end-marker)
165 (backward-delete-char 2)
166 (let* ((str (buffer-substring beg (point)))
167 (val (read-jis-code-from-string str)))
168 ;; ^--- this function is in egg.el
169 (delete-region beg (point))
171 (insert (make-character lc-jp (car val) (cdr val)))
173 (if (null henkan-begin)
174 (setq henkan-begin beg)))
176 (defun mlh-lisp-expression ()
178 (let ((stab (syntax-table)))
181 (set-syntax-table emacs-lisp-mode-syntax-table)
183 (set-syntax-table stab)))
184 (mlh-backward-henkan)
186 (goto-char end-marker)
187 (backward-delete-char 2)
189 (buffer-substring beg (point)))
190 (exp (car (read-from-string exp-str)))
192 (delete-region beg (point))
193 (insert (format "%s" result)))
194 (if (null henkan-begin)
195 (setq henkan-begin beg)))
198 (goto-char end-marker)
199 (backward-delete-char 2)
200 (setq henkan-begin (point)))
202 (defun mlh-no-conversion ()
204 (skip-chars-backward "\041-\056\060-\176")
205 (mlh-backward-henkan)
207 (goto-char end-marker)
208 (backward-delete-char 2)
209 (if (null henkan-begin)
210 (setq henkan-begin beg)))
212 (fset 'mlh-small-letter (symbol-function 'mlh-no-conversion))
214 (defun mlh-white-space ()
216 (skip-chars-backward "0-9")
217 (mlh-backward-henkan)
219 (goto-char end-marker)
220 (backward-delete-char 2)
221 (let* ((str (buffer-substring beg (point)))
222 (val (string-to-int str)))
223 (delete-region beg (point))
226 (insert (make-string val ?\ )))
227 (if (null henkan-begin)
228 (setq henkan-begin beg)))
230 (defun mlh-execute ()
232 (if (fboundp 'mlh-userdef-function)
233 (mlh-userdef-function)
234 (mlh-backward-henkan)
236 (goto-char end-marker)
237 (backward-delete-char 2)
238 (if (null henkan-begin)
239 (setq henkan-begin beg))))
241 (defun mlh-backward-henkan ()
242 "For each words seperated by / (slash), do conversion.
243 Accoding to a character preceding slash, conversion scheme are selected.
245 CHAR. MNEMONIC CONVERSION SCHEME
247 H Hiragana to kanji Convert Hiragana to Kanji
248 L Lisp Evaluate as Emacs-Lisp expression
249 W zenkaku White space Insert Zenkaku spaces
250 X eXit Quit going backward, insert space
251 Z Zenkaku Convert to Zenkaku
252 c Capitalize Capitalize
253 d user Definition Convert with user definition table
254 f Firagana ?? Convert to Hiragana
255 g Greek letter Convert to single greek letter
256 h Hangul Convert to Hangul
257 j Jis-code Convert to character which has code
258 k Katakana Convert to Katakana
259 l Ligature Ligature (not implemented yet)
260 p uPcase letter uPcase
261 q Quit Quit going backward
262 s Small letter No conversion
263 w White space Insert spaces
264 x eXecute Call user defined function
265 z Zhongwen Convert to Zhongwen
266 OTHERWISE Convert to KANJI
268 (if (eq (preceding-char) ?/)
269 (let ((end-marker (point-marker))
272 (set-marker-insertion-type end-marker t)
276 (setq char (preceding-char))
278 ((setq scheme (assq char mlh-conversion-scheme-table))
279 (funcall (cdr scheme)))
281 (goto-char end-marker)))
286 (goto-char end-marker))))
287 (set-marker end-marker nil)))))
290 (defvar mlh-syntax-table nil
291 "Syntax table of mlh, which are used to determine spacing.")
294 (setq mlh-syntax-table (copy-syntax-table emacs-lisp-mode-syntax-table))
295 (modify-syntax-entry ?! "." mlh-syntax-table)
296 (modify-syntax-entry ?$ "'" mlh-syntax-table)
297 (modify-syntax-entry ?% "'" mlh-syntax-table)
298 (modify-syntax-entry ?& "'" mlh-syntax-table)
299 (modify-syntax-entry ?{ "(}" mlh-syntax-table)
300 (modify-syntax-entry ?} "){" mlh-syntax-table)
303 ;;; XXX RTFM, gniibe!
304 (defvar mlh-space-control
306 (("al".?w).("al".?w))
307 (("al".?w).("al".?_))
308 (("al".?w).("Hj|".?e))
309 (("al".?w).("Cj|".?e))
310 (("al".?_).("al".?w))
311 (("al".?_).("al".?_))
312 (("al".?_).("Hj|".?e))
313 (("al".?_).("Cj|".?e))
314 (("al".?.).("al".?w))
315 (("al".?.).("al".?_))
316 (("al".?_).("Hj|".?e))
317 (("al".?_).("Cj|".?e))
318 (("Hj|".?e).("al".?w))
319 (("Cj|".?e).("al".?w))
320 (("Hj|".?e).("al".?_))
321 (("Cj|".?e).("al".?_))
323 "Alist that determines inserting space.")
325 (defun mlh-do-spacing ()
326 "Arrange spacing as you like."
329 (let ((s-tab (syntax-table))
334 (set-syntax-table mlh-syntax-table)
335 (setq s-pc (char-syntax (preceding-char))
336 s-fc (char-syntax (following-char))))
337 (set-syntax-table s-tab))
338 (setq c-pc (category-set-mnemonics (char-category-set (preceding-char)))
339 c-fc (category-set-mnemonics (char-category-set (following-char))))
340 (if (member (cons (cons c-pc s-pc) (cons c-fc s-fc)) mlh-space-control)
343 (>= henkan-begin (point))
344 (setq henkan-begin (1+ henkan-begin)))
347 (defvar mlh-select-mode-map (make-keymap))
349 ;;; acutually this map is not necessary now. for future extention
350 (defvar mlh-select-mode-esc-map (make-keymap))
352 (define-key mlh-select-mode-map [t] 'undefined)
353 (define-key mlh-select-mode-esc-map [t] 'undefined)
357 (define-key mlh-select-mode-map (char-to-string ch)
358 'mlh-select-kakutei-and-self-insert)
361 (define-key mlh-select-mode-map "\C-m" 'mlh-select-kakutei-and-self-insert)
362 (define-key mlh-select-mode-map "\C-b" 'mlh-select-prev-candidate)
363 (define-key mlh-select-mode-map "\C-f" 'mlh-select-next-candidate)
364 (define-key mlh-select-mode-map "\177" 'mlh-select-prev-candidate)
365 (define-key mlh-select-mode-map " " 'mlh-select-next-candidate)
366 (define-key mlh-select-mode-map "/" 'mlh-select-kakutei)
368 (if (eq window-system 'x)
370 (define-key mlh-select-mode-map [return] 'mlh-select-kakutei-and-self-insert)
371 (define-key mlh-select-mode-map [delete] 'mlh-select-prev-candidate)
374 (defun mlh-select-insert-candidate (n)
375 (delete-region beg (point))
376 (insert (nth n candidates)))
378 (defun mlh-select-prev-candidate ()
380 (setq current-candidate (1- current-candidate))
381 (if (< current-candidate 0)
382 (setq current-candidate (1- number-of-candidates)))
383 (mlh-select-insert-candidate current-candidate))
385 (defun mlh-select-next-candidate ()
387 (setq current-candidate (1+ current-candidate))
388 (if (>= current-candidate number-of-candidates)
389 (setq current-candidate 0))
390 (mlh-select-insert-candidate current-candidate))
392 (defun mlh-recursive-edit-select (beg end candidates)
393 (mlh-select-insert-candidate 0)
394 (and (boundp 'disable-undo) (setq disable-undo t))
395 (let ((old-local-map (current-local-map))
396 (number-of-candidates (length candidates))
397 (current-candidate 0))
398 (use-local-map mlh-select-mode-map)
400 (use-local-map old-local-map)))
402 (defun mlh-select-kakutei-and-self-insert ()
404 (setq unread-command-events (list last-command-event))
405 (mlh-select-kakutei))
407 (defun mlh-select-kakutei ()
409 (and (boundp 'disable-undo) (setq disable-undo nil))
410 (exit-recursive-edit))
412 (defun mlh-user-defined-conversion ()
414 (skip-chars-backward "-a-zA-Z")
415 (mlh-backward-henkan)
417 (goto-char end-marker)
418 (backward-delete-char 2)
419 (let* ((str (buffer-substring beg (point)))
420 (userdef (mlh-userdef<==string str)))
421 (cond ((stringp userdef)
422 (delete-region beg (point))
425 (delete-region beg (point))
426 ;; (add-userdef) (insert new-userdef)
429 (mlh-recursive-edit-select beg (point) userdef))))
430 (if (null henkan-begin)
431 (setq henkan-begin beg)))
433 (defvar mlh-userdef-table nil
434 "Convertion table of words(string) to another words(string).")
436 (defun mlh-userdef<==string (str)
437 "Convert string to another string with `mlh-userdef-table'"
438 (cdr (assoc str mlh-userdef-table)))
440 (defvar mlh-kanji-function 'mlh-kanji-with-henkan-region-function)
443 (funcall mlh-kanji-function))
445 (defun mlh-kanji-with-henkan-region-function ()
446 (skip-chars-backward "-a-z,.'N[]")
447 (mlh-backward-henkan)
448 (setq inhibit-henkan nil)
450 (goto-char end-marker)
452 (its-translate-region-internal beg (point))
453 (delete-region (point) end-marker)
454 (if (null henkan-begin)
455 (setq henkan-begin beg)))
457 (defun mlh-hiragana ()
459 (skip-chars-backward "-a-z,.'N[]")
460 (mlh-backward-henkan)
462 (goto-char end-marker)
464 (its-translate-region-internal beg (point))
465 (delete-region (point) end-marker)
466 (setq henkan-begin (point)))
468 (defun mlh-hiragana-to-kanji ()
470 (skip-chars-backward "
\e$B$!
\e(B-
\e$B$s!<
\e(B")
471 (mlh-backward-henkan)
473 (setq inhibit-henkan nil)
474 (goto-char end-marker)
475 (backward-delete-char 2)
476 (if (null henkan-begin)
477 (setq henkan-begin beg)))
479 (defun mlh-katakana ()
481 (skip-chars-backward "-a-z,.'N[]")
482 (mlh-backward-henkan)
484 (goto-char end-marker)
486 (its-translate-region-internal beg (point))
487 (japanese-katakana-region beg (point))
488 (delete-region (point) end-marker)
489 (if (null henkan-begin)
490 (setq henkan-begin beg)))
492 (defun mlh-zenkaku ()
494 (skip-chars-backward "\041-\056\060-\176")
495 (mlh-backward-henkan)
497 (goto-char end-marker)
498 (backward-delete-char 2)
499 (japanese-zenkaku-region beg (point))
500 (if (null henkan-begin)
501 (setq henkan-begin beg)))
505 (skip-chars-backward "a-zEO-RTW,.[]")
506 (mlh-backward-henkan)
508 (setq inhibit-henkan nil)
509 (goto-char end-marker)
511 (let (its-current-map its-current-language)
512 (its-select-hangul t)
513 (its-translate-region-internal beg (point)))
514 (delete-region (point) end-marker)
515 (if (null henkan-begin)
516 (setq henkan-begin beg)))
518 (defun mlh-zhongwen ()
520 (skip-chars-backward "a-z0-4 ,.[]")
521 (mlh-backward-henkan)
523 (setq inhibit-henkan nil)
524 (goto-char end-marker)
526 (let (its-current-map its-current-language)
527 (its-select-pinyin-cn t)
528 (its-translate-region-internal beg (point)))
529 (delete-region (point) end-marker)
530 (if (null henkan-begin)
531 (setq henkan-begin beg)))
533 (defun mlh-zhongwen-tw ()
535 (skip-chars-backward "a-z0-4,.[]")
536 (mlh-backward-henkan)
538 (setq inhibit-henkan nil)
539 (goto-char end-marker)
541 (let (its-current-map its-current-language)
542 (its-select-pinyin-tw t)
543 (its-translate-region-internal beg (point)))
544 (delete-region (point) end-marker)
545 (if (null henkan-begin)
546 (setq henkan-begin beg)))
549 ;;; egg-mlh.el ends here.