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 will be part of GNU Emacs (in future).
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 (defun mlh-space-bar-backward-henkan ()
37 "If the character preceding point is / (slash),
38 Do `mlh-backward-henkan'. Then, invoke appropriate conversion, if needed.
39 Or else, execute command that space-bar invokes usually."
41 (let ((henkan-begin nil)
43 (its-disable-special-action t))
44 (its-select-hiragana) ;; force to Japanese
47 (if (or inhibit-henkan (= henkan-begin (point)))
50 (message "Converting...")
52 (egg-convert-region henkan-begin (point))
54 (setq this-command 'self-insert-command)
55 (call-interactively 'self-insert-command))))
57 (defvar mlh-punctuations nil)
60 (setq mlh-punctuations "!()?;:"))
62 (defvar mlh-conversion-scheme-table
79 (?d . mlh-user-defined-conversion)
90 ; (?n . mlh-no-conversion)
92 (?p . mlh-upcase-letter)
95 (?s . mlh-small-letter)
96 (?t . mlh-zhongwen-tw)
99 (?w . mlh-white-space)
103 (?H . mlh-hiragana-to-kanji)
104 (?L . mlh-lisp-expression)
105 (?W . mlh-zenkaku-white)
110 (defun mlh-zenkaku-white ()
112 (skip-chars-backward "0-9")
113 (mlh-backward-henkan)
115 (goto-char end-marker)
116 (backward-delete-char 2)
117 (let* ((str (buffer-substring beg (point)))
118 (val (string-to-int str)))
119 (delete-region beg (point))
123 (insert "
\e$B!!
\e(B")
124 (setq val (1- val))))
125 (if (null henkan-begin)
126 (setq henkan-begin beg)))
129 (goto-char end-marker)
130 (backward-delete-char 2)
132 (setq henkan-begin (point)))
134 (defun mlh-upcase-letter ()
136 (skip-chars-backward "a-zA-Z0-9")
137 (mlh-backward-henkan)
139 (goto-char end-marker)
140 (backward-delete-char 2)
141 (upcase-region beg (point))
142 (if (null henkan-begin)
143 (setq henkan-begin beg)))
145 (defun mlh-capitalize ()
147 (skip-chars-backward "a-zA-Z1-9")
148 (mlh-backward-henkan)
150 (goto-char end-marker)
151 (backward-delete-char 2)
152 (capitalize-region beg (point))
153 (if (null henkan-begin)
154 (setq henkan-begin beg)))
156 (defun mlh-jis-code ()
158 (skip-chars-backward "0-9a-fA-F")
159 (mlh-backward-henkan)
161 (goto-char end-marker)
162 (backward-delete-char 2)
163 (let* ((str (buffer-substring beg (point)))
164 (val (read-jis-code-from-string str)))
165 ;; ^--- this function is in egg.el
166 (delete-region beg (point))
168 (insert (make-character lc-jp (car val) (cdr val)))
170 (if (null henkan-begin)
171 (setq henkan-begin beg)))
173 (defun mlh-lisp-expression ()
175 (let ((stab (syntax-table)))
178 (set-syntax-table emacs-lisp-mode-syntax-table)
180 (set-syntax-table stab)))
181 (mlh-backward-henkan)
183 (goto-char end-marker)
184 (backward-delete-char 2)
186 (buffer-substring beg (point)))
187 (exp (car (read-from-string exp-str)))
189 (delete-region beg (point))
190 (insert (format "%s" result)))
191 (if (null henkan-begin)
192 (setq henkan-begin beg)))
195 (goto-char end-marker)
196 (backward-delete-char 2)
197 (setq henkan-begin (point)))
199 (defun mlh-no-conversion ()
201 (skip-chars-backward "\041-\056\060-\176")
202 (mlh-backward-henkan)
204 (goto-char end-marker)
205 (backward-delete-char 2)
206 (if (null henkan-begin)
207 (setq henkan-begin beg)))
209 (fset 'mlh-small-letter (symbol-function 'mlh-no-conversion))
211 (defun mlh-white-space ()
213 (skip-chars-backward "0-9")
214 (mlh-backward-henkan)
216 (goto-char end-marker)
217 (backward-delete-char 2)
218 (let* ((str (buffer-substring beg (point)))
219 (val (string-to-int str)))
220 (delete-region beg (point))
223 (insert (make-string val ?\ )))
224 (if (null henkan-begin)
225 (setq henkan-begin beg)))
227 (defun mlh-execute ()
229 (if (fboundp 'mlh-userdef-function)
230 (mlh-userdef-function)
231 (mlh-backward-henkan)
233 (goto-char end-marker)
234 (backward-delete-char 2)
235 (if (null henkan-begin)
236 (setq henkan-begin beg))))
238 (defun mlh-backward-henkan ()
239 "For each words seperated by / (slash), do conversion.
240 Accoding to a character preceding slash, conversion scheme are selected.
242 CHAR. MNEMONIC CONVERSION SCHEME
244 H Hiragana to kanji Convert Hiragana to Kanji
245 L Lisp Evaluate as Emacs-Lisp expression
246 W zenkaku White space Insert Zenkaku spaces
247 X eXit Quit going backward, insert space
248 Z Zenkaku Convert to Zenkaku
249 c Capitalize Capitalize
250 d user Definition Convert with user definition table
251 f Firagana ?? Convert to Hiragana
252 g Greek letter Convert to single greek letter
253 h Hangul Convert to Hangul
254 j Jis-code Convert to character which has code
255 k Katakana Convert to Katakana
256 l Ligature Ligature (not implemented yet)
257 p uPcase letter uPcase
258 q Quit Quit going backward
259 s Small letter No conversion
260 w White space Insert spaces
261 x eXecute Call user defined function
262 z Zhongwen Convert to Zhongwen
263 OTHERWISE Convert to KANJI
265 (if (eq (preceding-char) ?/)
266 (let ((end-marker (point-marker))
269 (set-marker-insertion-type end-marker t)
273 (setq char (preceding-char))
275 ((setq scheme (assq char mlh-conversion-scheme-table))
276 (funcall (cdr scheme)))
278 (goto-char end-marker)))
283 (goto-char end-marker))))
284 (set-marker end-marker nil)))))
287 (defvar mlh-syntax-table nil
288 "Syntax table of mlh, which are used to determine spacing.")
291 (setq mlh-syntax-table (copy-syntax-table emacs-lisp-mode-syntax-table))
292 (modify-syntax-entry ?! "." mlh-syntax-table)
293 (modify-syntax-entry ?$ "'" mlh-syntax-table)
294 (modify-syntax-entry ?% "'" mlh-syntax-table)
295 (modify-syntax-entry ?& "'" mlh-syntax-table)
296 (modify-syntax-entry ?{ "(}" mlh-syntax-table)
297 (modify-syntax-entry ?} "){" mlh-syntax-table)
300 ;;; XXX RTFM, gniibe!
301 (defvar mlh-space-control
303 (("al".?w).("al".?w))
304 (("al".?w).("al".?_))
305 (("al".?w).("Hj|".?e))
306 (("al".?w).("Cj|".?e))
307 (("al".?_).("al".?w))
308 (("al".?_).("al".?_))
309 (("al".?_).("Hj|".?e))
310 (("al".?_).("Cj|".?e))
311 (("al".?.).("al".?w))
312 (("al".?.).("al".?_))
313 (("al".?_).("Hj|".?e))
314 (("al".?_).("Cj|".?e))
315 (("Hj|".?e).("al".?w))
316 (("Cj|".?e).("al".?w))
317 (("Hj|".?e).("al".?_))
318 (("Cj|".?e).("al".?_))
320 "Alist that determines inserting space.")
322 (defun mlh-do-spacing ()
323 "Arrange spacing as you like."
326 (let ((s-tab (syntax-table))
331 (set-syntax-table mlh-syntax-table)
332 (setq s-pc (char-syntax (preceding-char))
333 s-fc (char-syntax (following-char))))
334 (set-syntax-table s-tab))
335 (setq c-pc (category-set-mnemonics (char-category-set (preceding-char)))
336 c-fc (category-set-mnemonics (char-category-set (following-char))))
337 (if (member (cons (cons c-pc s-pc) (cons c-fc s-fc)) mlh-space-control)
340 (>= henkan-begin (point))
341 (setq henkan-begin (1+ henkan-begin)))
344 (defvar mlh-select-mode-map (make-keymap))
346 ;;; acutually this map is not necessary now. for future extention
347 (defvar mlh-select-mode-esc-map (make-keymap))
349 (define-key mlh-select-mode-map [t] 'undefined)
350 (define-key mlh-select-mode-esc-map [t] 'undefined)
354 (define-key mlh-select-mode-map (char-to-string ch)
355 'mlh-select-kakutei-and-self-insert)
358 (define-key mlh-select-mode-map "\C-m" 'mlh-select-kakutei-and-self-insert)
359 (define-key mlh-select-mode-map "\C-b" 'mlh-select-prev-candidate)
360 (define-key mlh-select-mode-map "\C-f" 'mlh-select-next-candidate)
361 (define-key mlh-select-mode-map "\177" 'mlh-select-prev-candidate)
362 (define-key mlh-select-mode-map " " 'mlh-select-next-candidate)
363 (define-key mlh-select-mode-map "/" 'mlh-select-kakutei)
365 (if (eq window-system 'x)
367 (define-key mlh-select-mode-map [return] 'mlh-select-kakutei-and-self-insert)
368 (define-key mlh-select-mode-map [delete] 'mlh-select-prev-candidate)
371 (defun mlh-select-insert-candidate (n)
372 (delete-region beg (point))
373 (insert (nth n candidates)))
375 (defun mlh-select-prev-candidate ()
377 (setq current-candidate (1- current-candidate))
378 (if (< current-candidate 0)
379 (setq current-candidate (1- number-of-candidates)))
380 (mlh-select-insert-candidate current-candidate))
382 (defun mlh-select-next-candidate ()
384 (setq current-candidate (1+ current-candidate))
385 (if (>= current-candidate number-of-candidates)
386 (setq current-candidate 0))
387 (mlh-select-insert-candidate current-candidate))
389 (defun mlh-recursive-edit-select (beg end candidates)
390 (mlh-select-insert-candidate 0)
391 (and (boundp 'disable-undo) (setq disable-undo t))
392 (let ((old-local-map (current-local-map))
393 (number-of-candidates (length candidates))
394 (current-candidate 0))
395 (use-local-map mlh-select-mode-map)
397 (use-local-map old-local-map)))
399 (defun mlh-select-kakutei-and-self-insert ()
401 (setq unread-command-events (list last-command-event))
402 (mlh-select-kakutei))
404 (defun mlh-select-kakutei ()
406 (and (boundp 'disable-undo) (setq disable-undo nil))
407 (exit-recursive-edit))
409 (defun mlh-user-defined-conversion ()
411 (skip-chars-backward "-a-zA-Z")
412 (mlh-backward-henkan)
414 (goto-char end-marker)
415 (backward-delete-char 2)
416 (let* ((str (buffer-substring beg (point)))
417 (userdef (mlh-userdef<==string str)))
418 (cond ((stringp userdef)
419 (delete-region beg (point))
422 (delete-region beg (point))
423 ;; (add-userdef) (insert new-userdef)
426 (mlh-recursive-edit-select beg (point) userdef))))
427 (if (null henkan-begin)
428 (setq henkan-begin beg)))
430 (defvar mlh-userdef-table nil
431 "Convertion table of words(string) to another words(string).")
433 (defun mlh-userdef<==string (str)
434 "Convert string to another string with `mlh-userdef-table'"
435 (cdr (assoc str mlh-userdef-table)))
437 (defvar mlh-kanji-function 'mlh-kanji-with-henkan-region-function)
440 (funcall mlh-kanji-function))
442 (defun mlh-kanji-with-henkan-region-function ()
443 (skip-chars-backward "-a-z,.'N[]")
444 (mlh-backward-henkan)
445 (setq inhibit-henkan nil)
447 (goto-char end-marker)
449 (its-translate-region-internal beg (point))
450 (delete-region (point) end-marker)
451 (if (null henkan-begin)
452 (setq henkan-begin beg)))
454 (defun mlh-hiragana ()
456 (skip-chars-backward "-a-z,.'N[]")
457 (mlh-backward-henkan)
459 (goto-char end-marker)
461 (its-translate-region-internal beg (point))
462 (delete-region (point) end-marker)
463 (setq henkan-begin (point)))
465 (defun mlh-hiragana-to-kanji ()
467 (skip-chars-backward "
\e$B$!
\e(B-
\e$B$s!<
\e(B")
468 (mlh-backward-henkan)
470 (setq inhibit-henkan nil)
471 (goto-char end-marker)
472 (backward-delete-char 2)
473 (if (null henkan-begin)
474 (setq henkan-begin beg)))
476 (defun mlh-katakana ()
478 (skip-chars-backward "-a-z,.'N[]")
479 (mlh-backward-henkan)
481 (goto-char end-marker)
483 (its-translate-region-internal beg (point))
484 (insert (mlh-hira-to-kata
486 (buffer-substring beg (point))
487 (delete-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)))
503 (defun mlh-hira-to-kata (str)
504 "Convert hiragana to katakana in STR."
505 (let ((result (copy-sequence str))
507 (while (setq i (string-match "[
\e$B$!
\e(B-
\e$B$s
\e(B]" str i))
508 (aset result (1+ i) ?\245)
514 (skip-chars-backward "a-zEO-RTW,.[]")
515 (mlh-backward-henkan)
517 (setq inhibit-henkan nil)
518 (goto-char end-marker)
520 (let (its-current-map its-current-language)
521 (its-select-hangul t)
522 (its-translate-region-internal beg (point)))
523 (delete-region (point) end-marker)
524 (if (null henkan-begin)
525 (setq henkan-begin beg)))
527 (defun mlh-zhongwen ()
529 (skip-chars-backward "a-z0-4 ,.[]")
530 (mlh-backward-henkan)
532 (setq inhibit-henkan nil)
533 (goto-char end-marker)
535 (let (its-current-map its-current-language)
536 (its-select-pinyin-cn t)
537 (its-translate-region-internal beg (point)))
538 (delete-region (point) end-marker)
539 (if (null henkan-begin)
540 (setq henkan-begin beg)))
542 (defun mlh-zhongwen-tw ()
544 (skip-chars-backward "a-z0-4,.[]")
545 (mlh-backward-henkan)
547 (setq inhibit-henkan nil)
548 (goto-char end-marker)
550 (let (its-current-map its-current-language)
551 (its-select-pinyin-tw t)
552 (its-translate-region-internal beg (point)))
553 (delete-region (point) end-marker)
554 (if (null henkan-begin)
555 (setq henkan-begin beg)))
558 ;;; egg-mlh.el ends here.