1 ;;; ethio-util.el --- utilities for Ethiopic -*- coding: iso-2022-7bit; -*-
3 ;; Copyright (C) 1997, 2001 Electrotechnical Laboratory, JAPAN.
4 ;; Licensed to the Free Software Foundation.
6 ;; Keywords: mule, multilingual, Ethiopic
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)
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 ;; Author: TAKAHASHI Naoto <ntakahas@m17n.org>
31 ;; Information for exiting Ethiopic environment.
32 (defvar exit-ethiopic-environment-data nil)
35 (defun setup-ethiopic-environment-internal ()
36 (let ((key-bindings '((" " . ethio-insert-space)
37 ([?\S- ] . ethio-insert-ethio-space)
38 ([?\C-'] . ethio-gemination)
40 ;; these old bindings conflict
41 ;; with Emacs' binding policy
43 ;; ([f2] . ethio-toggle-space)
44 ;; ([S-f2] . ethio-replace-space) ; as requested
45 ;; ([f3] . ethio-toggle-punctuation)
46 ;; ([f4] . ethio-sera-to-fidel-buffer)
47 ;; ([S-f4] . ethio-sera-to-fidel-region)
48 ;; ([C-f4] . ethio-sera-to-fidel-mail-or-marker)
49 ;; ([f5] . ethio-fidel-to-sera-buffer)
50 ;; ([S-f5] . ethio-fidel-to-sera-region)
51 ;; ([C-f5] . ethio-fidel-to-sera-mail-or-marker)
52 ;; ([f6] . ethio-modify-vowel)
53 ;; ([f7] . ethio-replace-space)
54 ;; ([f8] . ethio-input-special-character)
56 ;; this is the rewritten bindings
58 ([f3] . ethio-fidel-to-sera-buffer)
59 ([S-f3] . ethio-fidel-to-sera-region)
60 ([C-f3] . ethio-fidel-to-sera-mail-or-marker)
61 ([f4] . ethio-sera-to-fidel-buffer)
62 ([S-f4] . ethio-sera-to-fidel-region)
63 ([C-f4] . ethio-sera-to-fidel-mail-or-marker)
64 ([S-f5] . ethio-toggle-punctuation)
65 ([S-f6] . ethio-modify-vowel)
66 ([S-f7] . ethio-replace-space)
67 ([S-f8] . ethio-input-special-character)
68 ([C-f9] . ethio-toggle-space)
69 ([S-f9] . ethio-replace-space) ; as requested
73 (setq kb (car (car key-bindings)))
74 (setq exit-ethiopic-environment-data
75 (cons (cons kb (global-key-binding kb))
76 exit-ethiopic-environment-data))
77 (global-set-key kb (cdr (car key-bindings)))
78 (setq key-bindings (cdr key-bindings))))
80 (add-hook 'quail-activate-hook 'ethio-select-a-translation)
81 (add-hook 'find-file-hook 'ethio-find-file)
82 (add-hook 'write-file-functions 'ethio-write-file)
83 (add-hook 'after-save-hook 'ethio-find-file))
85 (defun exit-ethiopic-environment ()
86 "Exit Ethiopic language environment."
87 (while exit-ethiopic-environment-data
88 (global-set-key (car (car exit-ethiopic-environment-data))
89 (cdr (car exit-ethiopic-environment-data)))
90 (setq exit-ethiopic-environment-data
91 (cdr exit-ethiopic-environment-data)))
93 (remove-hook 'quail-activate-hook 'ethio-select-a-translation)
94 (remove-hook 'find-file-hook 'ethio-find-file)
95 (remove-hook 'write-file-functions 'ethio-write-file)
96 (remove-hook 'after-save-hook 'ethio-find-file))
99 ;; ETHIOPIC UTILITY FUNCTIONS
102 ;; If the filename ends in ".sera", editing is done in fidel
103 ;; but file I/O is done in SERA.
105 ;; If the filename ends in ".java", editing is done in fidel
106 ;; but file I/O is done in the \uXXXX style, where XXXX is
107 ;; the Unicode codepoint for the Ethiopic character.
109 ;; If the filename ends in ".tex", editing is done in fidel
110 ;; but file I/O is done in EthioTeX format.
112 ;; To automatically convert Ethiopic text to SERA format when sending mail,
113 ;; (add-hook 'mail-send-hook 'ethio-fidel-to-sera-mail)
115 ;; To automatically convert SERA format to Ethiopic when receiving mail,
116 ;; (add-hook 'rmail-show-message-hook 'ethio-sera-to-fidel-mail)
118 ;; To automatically convert Ethiopic text to SERA format when posting news,
119 ;; (add-hook 'news-inews-hook 'ethio-fidel-to-sera-mail)
125 (defvar ethio-primary-language 'tigrigna
126 "*Symbol that defines the primary language in SERA --> FIDEL conversion.
127 The value should be one of: `tigrigna', `amharic' or `english'.")
129 (defvar ethio-secondary-language 'english
130 "*Symbol that defines the secondary language in SERA --> FIDEL conversion.
131 The value should be one of: `tigrigna', `amharic' or `english'.")
133 (defvar ethio-use-colon-for-colon nil
134 "*Non-nil means associate ASCII colon with Ethiopic colon.
135 If nil, associate ASCII colon with Ethiopic word separator, i.e., two
136 vertically stacked dots. All SERA <--> FIDEL converters refer this
139 (defvar ethio-use-three-dot-question nil
140 "*Non-nil means associate ASCII question mark with Ethiopic old style question mark (three vertically stacked dots).
141 If nil, associate ASCII question mark with Ethiopic stylised question
142 mark. All SERA <--> FIDEL converters refer this variable.")
144 (defvar ethio-quote-vowel-always nil
145 "*Non-nil means always put an apostrophe before an isolated vowel (except at word initial) in FIDEL --> SERA conversion.
146 If nil, put an apostrophe only between a sixth-form consonant and an
149 (defvar ethio-W-sixth-always nil
150 "*Non-nil means convert the Wu-form of a 12-form consonant to \"W'\" instead of \"Wu\" in FIDEL --> SERA conversion.")
152 (defvar ethio-numeric-reduction 0
153 "*Degree of reduction in converting Ethiopic digits into Arabic digits.
155 For example, ({10}{9}{100}{80}{7}) is converted into:
156 `10`9`100`80`7 if `ethio-numeric-reduction' is 0,
157 `109100807 if `ethio-numeric-reduction' is 1,
158 `10900807 if `ethio-numeric-reduction' is 2.")
160 (defvar ethio-implicit-period-conversion t
161 "*Non-nil means replacing the Ethiopic dot at the end of an Ethiopic sentence
162 with an Ethiopic full stop.")
164 (defvar ethio-java-save-lowercase nil
165 "*Non-nil means save Ethiopic characters in lowercase hex numbers to Java files.
166 If nil, use uppercases.")
172 (defconst ethio-sera-to-fidel-table
174 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
175 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
178 (?: (if ethio-use-colon-for-colon "
\e$(3$l
\e(B" "
\e$(3$h
\e(B")
179 (32 (if ethio-use-colon-for-colon "
\e$(3$l
\e(B " "
\e$(3$h
\e(B"))
182 (?| (if ethio-use-colon-for-colon "
\e$(3$l
\e(B|" "
\e$(3$h
\e(B|")
183 (?: "
\e$(3$o
\e(B"))))
186 nil nil nil nil nil nil ("" (?' "
\e$(3%s
\e(B"))
188 nil nil nil nil ("
\e$(3$j
\e(B") ("-" (?: "
\e$(3$l
\e(B")) ("
\e$(3%u
\e(B")
189 ;;; / 0 1 2 3 4 5 6 7 8 9
190 nil nil nil nil nil nil nil nil nil nil nil
192 ((if ethio-use-colon-for-colon "
\e$(3$l
\e(B" "
\e$(3$h
\e(B")
193 (32 (if ethio-use-colon-for-colon "
\e$(3$l
\e(B " "
\e$(3$h
\e(B"))
196 (?| (if ethio-use-colon-for-colon "
\e$(3$l
\e(B|" "
\e$(3$h
\e(B|")
199 ("
\e$(3$k
\e(B") ("<" (?< "
\e$(3%v
\e(B")) nil (">" (?> "
\e$(3%w
\e(B"))
201 ((if ethio-use-three-dot-question "
\e$(3$n
\e(B" "
\e$(3%x
\e(B"))
205 ("
\e$(3"f
\e(B" (?2 "
\e$(3#8
\e(B"))
207 ("
\e$(3"(
\e(B" (?e "
\e$(3"#
\e(B") (?u "
\e$(3"$
\e(B") (?i "
\e$(3"%
\e(B") (?a "
\e$(3"&
\e(B") (?E "
\e$(3"'
\e(B") (?o "
\e$(3")
\e(B")
208 (?W "
\e$(3%b
\e(B" (?e "
\e$(3%2
\e(B") (?u "
\e$(3%b
\e(B") (?i "
\e$(3%B
\e(B") (?a "
\e$(3"*
\e(B") (?E "
\e$(3%R
\e(B")))
210 ("
\e$(3$4
\e(B" (?e "
\e$(3$/
\e(B") (?u "
\e$(3$0
\e(B") (?i "
\e$(3$1
\e(B") (?a "
\e$(3$2
\e(B") (?E "
\e$(3$3
\e(B") (?o "
\e$(3$5
\e(B")
211 (?W "
\e$(3$6
\e(B" (?a "
\e$(3$6
\e(B")
212 (?e "
\e$(3$4%n
\e(B") (?u "
\e$(3$4%r
\e(B") (?i "
\e$(3$4%o
\e(B") (?E "
\e$(3$4%q
\e(B")))
214 ("
\e$(3#b
\e(B" (?e "
\e$(3#]
\e(B") (?u "
\e$(3#^
\e(B") (?i "
\e$(3#_
\e(B") (?a "
\e$(3#`
\e(B") (?E "
\e$(3#a
\e(B") (?o "
\e$(3#c
\e(B")
215 (?W "
\e$(3#d
\e(B" (?a "
\e$(3#d
\e(B")
216 (?e "
\e$(3#b%n
\e(B") (?u "
\e$(3#b%r
\e(B") (?i "
\e$(3#b%o
\e(B") (?E "
\e$(3#b%q
\e(B")))
218 ("
\e$(3"g
\e(B" (?2 "
\e$(3#9
\e(B"))
220 ("
\e$(3$T
\e(B" (?e "
\e$(3$O
\e(B") (?u "
\e$(3$P
\e(B") (?i "
\e$(3$Q
\e(B") (?a "
\e$(3$R
\e(B") (?E "
\e$(3$S
\e(B") (?o "
\e$(3$U
\e(B")
221 (?W "
\e$(3%d
\e(B" (?e "
\e$(3%4
\e(B") (?u "
\e$(3%d
\e(B") (?i "
\e$(3%D
\e(B") (?a "
\e$(3$V
\e(B") (?E "
\e$(3%T
\e(B"))
222 (?Y "
\e$(3$a
\e(B" (?a "
\e$(3$a
\e(B")))
224 ("
\e$(3$$
\e(B" (?e "
\e$(3#}
\e(B") (?u "
\e$(3#~
\e(B") (?i "
\e$(3$!
\e(B") (?a "
\e$(3$"
\e(B") (?E "
\e$(3$#
\e(B") (?o "
\e$(3$%
\e(B")
225 (?W "
\e$(3%c
\e(B" (?e "
\e$(3%3
\e(B") (?u "
\e$(3%c
\e(B") (?i "
\e$(3%C
\e(B") (?a "
\e$(3$&
\e(B") (?E "
\e$(3%S
\e(B")))
227 ("
\e$(3!6
\e(B" (?e "
\e$(3!1
\e(B") (?u "
\e$(3!2
\e(B") (?i "
\e$(3!3
\e(B") (?a "
\e$(3!4
\e(B") (?E "
\e$(3!5
\e(B") (?o "
\e$(3!7
\e(B")
228 (?W "
\e$(3!8
\e(B" (?a "
\e$(3!8
\e(B")
229 (?e "
\e$(3!6%n
\e(B") (?u "
\e$(3!6%r
\e(B") (?i "
\e$(3!6%o
\e(B") (?E "
\e$(3!6%q
\e(B")))
231 ("
\e$(3"h
\e(B" (?2 "
\e$(3#:
\e(B"))
233 ("
\e$(3#j
\e(B" (?e "
\e$(3#e
\e(B") (?u "
\e$(3#f
\e(B") (?i "
\e$(3#g
\e(B") (?a "
\e$(3#h
\e(B") (?E "
\e$(3#i
\e(B") (?o "
\e$(3#k
\e(B")
234 (?W "
\e$(3#l
\e(B" (?a "
\e$(3#l
\e(B")
235 (?e "
\e$(3#j%n
\e(B") (?u "
\e$(3#j%r
\e(B") (?i "
\e$(3#j%o
\e(B") (?E "
\e$(3#j%q
\e(B")))
237 ("
\e$(3#"
\e(B" (?e "
\e$(3"{
\e(B") (?u "
\e$(3"|
\e(B") (?i "
\e$(3"}
\e(B") (?a "
\e$(3"~
\e(B") (?E "
\e$(3#!
\e(B") (?o "
\e$(3##
\e(B")
238 (?W "
\e$(3#*
\e(B" (?e "
\e$(3#%
\e(B") (?u "
\e$(3#*
\e(B") (?i "
\e$(3#'
\e(B") (?a "
\e$(3#(
\e(B") (?E "
\e$(3#)
\e(B")))
240 ("
\e$(3!.
\e(B" (?e "
\e$(3!)
\e(B") (?u "
\e$(3!*
\e(B") (?i "
\e$(3!+
\e(B") (?a "
\e$(3!,
\e(B") (?E "
\e$(3!-
\e(B") (?o "
\e$(3!/
\e(B")
241 (?W "
\e$(3!0
\e(B" (?a "
\e$(3!0
\e(B")
242 (?e "
\e$(3!.%n
\e(B") (?u "
\e$(3!.%r
\e(B") (?i "
\e$(3!.%o
\e(B") (?E "
\e$(3!.%q
\e(B")))
244 ("
\e$(3!>
\e(B" (?e "
\e$(3!9
\e(B") (?u "
\e$(3!:
\e(B") (?i "
\e$(3!;
\e(B") (?a "
\e$(3!<
\e(B") (?E "
\e$(3!=
\e(B") (?o "
\e$(3!?
\e(B")
245 (?W "
\e$(3%a
\e(B" (?e "
\e$(3%1
\e(B") (?u "
\e$(3%a
\e(B") (?i "
\e$(3%A
\e(B") (?a "
\e$(3!@
\e(B") (?E "
\e$(3%Q
\e(B"))
246 (?Y "
\e$(3$_
\e(B" (?a "
\e$(3$_
\e(B")))
248 ("
\e$(3"`
\e(B" (?e "
\e$(3"[
\e(B") (?u "
\e$(3"\
\e(B") (?i "
\e$(3"]
\e(B") (?a "
\e$(3"^
\e(B") (?E "
\e$(3"_
\e(B") (?o "
\e$(3"a
\e(B")
249 (?W "
\e$(3"b
\e(B" (?a "
\e$(3"b
\e(B")
250 (?e "
\e$(3"`%n
\e(B") (?u "
\e$(3"`%r
\e(B") (?i "
\e$(3"`%o
\e(B") (?E "
\e$(3"`%q
\e(B")))
252 ("
\e$(3"i
\e(B" (?2 "
\e$(3#;
\e(B"))
254 ("
\e$(3$<
\e(B" (?e "
\e$(3$7
\e(B") (?u "
\e$(3$8
\e(B") (?i "
\e$(3$9
\e(B") (?a "
\e$(3$:
\e(B") (?E "
\e$(3$;
\e(B") (?o "
\e$(3$=
\e(B")
255 (?W "
\e$(3$>
\e(B" (?a "
\e$(3$>
\e(B")
256 (?e "
\e$(3$<%n
\e(B") (?u "
\e$(3$<%r
\e(B") (?i "
\e$(3$<%o
\e(B") (?E "
\e$(3$<%q
\e(B")))
258 ("
\e$(3!v
\e(B" (?e "
\e$(3!q
\e(B") (?u "
\e$(3!r
\e(B") (?i "
\e$(3!s
\e(B") (?a "
\e$(3!t
\e(B") (?E "
\e$(3!u
\e(B") (?o "
\e$(3!w
\e(B")
259 (?W "
\e$(3!~
\e(B" (?e "
\e$(3!y
\e(B") (?u "
\e$(3!~
\e(B") (?i "
\e$(3!{
\e(B") (?a "
\e$(3!|
\e(B") (?E "
\e$(3!}
\e(B")))
261 ("
\e$(3!N
\e(B" (?e "
\e$(3!I
\e(B") (?u "
\e$(3!J
\e(B") (?i "
\e$(3!K
\e(B") (?a "
\e$(3!L
\e(B") (?E "
\e$(3!M
\e(B") (?o "
\e$(3!O
\e(B")
262 (?W "
\e$(3!P
\e(B" (?a "
\e$(3!P
\e(B")
263 (?e "
\e$(3!N%n
\e(B") (?u "
\e$(3!N%r
\e(B") (?i "
\e$(3!N%o
\e(B") (?E "
\e$(3!N%q
\e(B"))
264 (?Y "
\e$(3$`
\e(B" (?a "
\e$(3$`
\e(B")))
266 ("
\e$(3$D
\e(B" (?e "
\e$(3$?
\e(B") (?u "
\e$(3$@
\e(B") (?i "
\e$(3$A
\e(B") (?a "
\e$(3$B
\e(B") (?E "
\e$(3$C
\e(B") (?o "
\e$(3$E
\e(B")
267 (?W "
\e$(3$F
\e(B" (?a "
\e$(3$F
\e(B")
268 (?e "
\e$(3$D%n
\e(B") (?u "
\e$(3$D%r
\e(B") (?i "
\e$(3$D%o
\e(B") (?E "
\e$(3$D%q
\e(B"))
270 (?e "
\e$(3$G
\e(B") (?u "
\e$(3$H
\e(B") (?i "
\e$(3$I
\e(B") (?a "
\e$(3$J
\e(B") (?E "
\e$(3$K
\e(B") (?o "
\e$(3$M
\e(B")
271 (?W "
\e$(3$F
\e(B" (?a "
\e$(3$F
\e(B")
272 (?e "
\e$(3$L%n
\e(B") (?u "
\e$(3$L%r
\e(B") (?i "
\e$(3$L%o
\e(B") (?E "
\e$(3$L%q
\e(B"))))
274 ("
\e$(3$,
\e(B" (?e "
\e$(3$'
\e(B") (?u "
\e$(3$(
\e(B") (?i "
\e$(3$)
\e(B") (?a "
\e$(3$*
\e(B") (?E "
\e$(3$+
\e(B") (?o "
\e$(3$-
\e(B")
275 (?W "
\e$(3$.
\e(B" (?a "
\e$(3$.
\e(B")
276 (?e "
\e$(3$,%n
\e(B") (?u "
\e$(3$,%r
\e(B") (?i "
\e$(3$,%o
\e(B") (?E "
\e$(3$,%q
\e(B")))
278 ("
\e$(3"d
\e(B" (?2 "
\e$(3#6
\e(B"))
280 ("
\e$(3"0
\e(B" (?e "
\e$(3"+
\e(B") (?u "
\e$(3",
\e(B") (?i "
\e$(3"-
\e(B") (?a "
\e$(3".
\e(B") (?E "
\e$(3"/
\e(B") (?o "
\e$(3"1
\e(B")
281 (?W "
\e$(3"2
\e(B" (?a "
\e$(3"2
\e(B")
282 (?e "
\e$(3"0%n
\e(B") (?u "
\e$(3"0%r
\e(B") (?i "
\e$(3"0%o
\e(B") (?E "
\e$(3"0%q
\e(B")))
284 ("
\e$(3%r
\e(B" (?e "
\e$(3%n
\e(B") (?u "
\e$(3%r
\e(B") (?i "
\e$(3%o
\e(B") (?a "
\e$(3%p
\e(B") (?E "
\e$(3%q
\e(B"))
286 ("
\e$(3%N
\e(B" (?e "
\e$(3%I
\e(B") (?u "
\e$(3%J
\e(B") (?i "
\e$(3%K
\e(B") (?a "
\e$(3%L
\e(B") (?E "
\e$(3%M
\e(B") (?o "
\e$(3%O
\e(B"))
288 ("
\e$(3#R
\e(B" (?e "
\e$(3#M
\e(B") (?u "
\e$(3#N
\e(B") (?i "
\e$(3#O
\e(B") (?a "
\e$(3#P
\e(B") (?E "
\e$(3#Q
\e(B") (?o "
\e$(3#S
\e(B")
289 (?W "
\e$(3#T
\e(B" (?a "
\e$(3#T
\e(B")
290 (?e "
\e$(3#R%n
\e(B") (?u "
\e$(3#R%r
\e(B") (?i "
\e$(3#R%o
\e(B") (?E "
\e$(3#R%q
\e(B")))
292 ("
\e$(3#J
\e(B" (?e "
\e$(3#E
\e(B") (?u "
\e$(3#F
\e(B") (?i "
\e$(3#G
\e(B") (?a "
\e$(3#H
\e(B") (?E "
\e$(3#I
\e(B") (?o "
\e$(3#K
\e(B")
293 (?W "
\e$(3#L
\e(B" (?a "
\e$(3#L
\e(B")
294 (?e "
\e$(3#J%n
\e(B") (?u "
\e$(3#J%r
\e(B") (?i "
\e$(3#J%o
\e(B") (?E "
\e$(3#J%q
\e(B")))
300 (?? (if ethio-use-three-dot-question "
\e$(3%x
\e(B" "
\e$(3$n
\e(B"))
302 (?e "
\e$(3#5
\e(B") (?u "
\e$(3#6
\e(B") (?U "
\e$(3#6
\e(B") (?i "
\e$(3#7
\e(B") (?a "
\e$(3#8
\e(B") (?A "
\e$(3#8
\e(B")
303 (?E "
\e$(3#9
\e(B") (?I "
\e$(3#:
\e(B") (?o "
\e$(3#;
\e(B") (?O "
\e$(3#;
\e(B")
305 (?e "
\e$(3%Y
\e(B") (?u "
\e$(3%Z
\e(B") (?i "
\e$(3%[
\e(B") (?a "
\e$(3%\
\e(B") (?E "
\e$(3%]
\e(B") (?o "
\e$(3%_
\e(B"))
307 (?e "
\e$(3"C
\e(B") (?u "
\e$(3"D
\e(B") (?i "
\e$(3"E
\e(B") (?a "
\e$(3"F
\e(B") (?E "
\e$(3"G
\e(B") (?o "
\e$(3"I
\e(B")
308 (?W "
\e$(3"P
\e(B" (?e "
\e$(3"K
\e(B") (?u "
\e$(3"P
\e(B") (?i "
\e$(3"M
\e(B") (?a "
\e$(3"N
\e(B") (?E "
\e$(3"O
\e(B")))
310 (?e "
\e$(3%9
\e(B") (?u "
\e$(3%:
\e(B") (?i "
\e$(3%;
\e(B") (?a "
\e$(3%<
\e(B") (?E "
\e$(3%=
\e(B") (?o "
\e$(3%?
\e(B"))
312 (?e "
\e$(3!A
\e(B") (?u "
\e$(3!B
\e(B") (?i "
\e$(3!C
\e(B") (?a "
\e$(3!D
\e(B") (?E "
\e$(3!E
\e(B") (?o "
\e$(3!G
\e(B")
313 (?W "
\e$(3!H
\e(B" (?a "
\e$(3!H
\e(B")
314 (?e "
\e$(3!F%n
\e(B") (?u "
\e$(3!F%r
\e(B") (?i "
\e$(3!F%o
\e(B") (?E "
\e$(3!F%q
\e(B")))
316 (?e "
\e$(3$G
\e(B") (?u "
\e$(3$H
\e(B") (?i "
\e$(3$I
\e(B") (?a "
\e$(3$J
\e(B") (?E "
\e$(3$K
\e(B") (?o "
\e$(3$M
\e(B")
317 (?W "
\e$(3$F
\e(B" (?a "
\e$(3$F
\e(B")
318 (?e "
\e$(3$L%n
\e(B") (?u "
\e$(3$L%r
\e(B") (?i "
\e$(3$L%o
\e(B") (?E "
\e$(3$L%q
\e(B")))
319 (?q "
\e$(3%.
\e(B" (?e "
\e$(3%)
\e(B") (?u "
\e$(3%*
\e(B") (?i "
\e$(3%+
\e(B") (?a "
\e$(3%,
\e(B") (?E "
\e$(3%-
\e(B") (?o "
\e$(3%/
\e(B")))
321 ("
\e$(3"f
\e(B" (?2 "
\e$(3#8
\e(B"))
323 ("
\e$(3"(
\e(B" (?e "
\e$(3"#
\e(B") (?u "
\e$(3"$
\e(B") (?i "
\e$(3"%
\e(B") (?a "
\e$(3"&
\e(B") (?E "
\e$(3"'
\e(B") (?o "
\e$(3")
\e(B")
324 (?W "
\e$(3%b
\e(B" (?e "
\e$(3%2
\e(B") (?u "
\e$(3%b
\e(B") (?i "
\e$(3%B
\e(B") (?a "
\e$(3"*
\e(B") (?E "
\e$(3%R
\e(B")))
326 ("
\e$(3"@
\e(B" (?e "
\e$(3";
\e(B") (?u "
\e$(3"<
\e(B") (?i "
\e$(3"=
\e(B") (?a "
\e$(3">
\e(B") (?E "
\e$(3"?
\e(B") (?o "
\e$(3"A
\e(B")
327 (?W "
\e$(3"B
\e(B" (?a "
\e$(3"B
\e(B")
328 (?e "
\e$(3"@%n
\e(B") (?u "
\e$(3"@%r
\e(B") (?i "
\e$(3"@%o
\e(B") (?E "
\e$(3"@%q
\e(B")))
330 ("
\e$(3#Z
\e(B" (?e "
\e$(3#U
\e(B") (?u "
\e$(3#V
\e(B") (?i "
\e$(3#W
\e(B") (?a "
\e$(3#X
\e(B") (?E "
\e$(3#Y
\e(B") (?o "
\e$(3#[
\e(B")
331 (?W "
\e$(3#\
\e(B" (?a "
\e$(3#\
\e(B")
332 (?e "
\e$(3#Z%o
\e(B") (?u "
\e$(3#Z%r
\e(B") (?i "
\e$(3#Z%p
\e(B") (?E "
\e$(3#Z%q
\e(B")))
334 ("
\e$(3"c
\e(B" (?2 "
\e$(3#5
\e(B") (?a "
\e$(3"j
\e(B"))
336 ("
\e$(3$T
\e(B" (?e "
\e$(3$O
\e(B") (?u "
\e$(3$P
\e(B") (?i "
\e$(3$Q
\e(B") (?a "
\e$(3$R
\e(B") (?E "
\e$(3$S
\e(B") (?o "
\e$(3$U
\e(B")
337 (?W "
\e$(3%d
\e(B" (?e "
\e$(3%4
\e(B") (?u "
\e$(3%d
\e(B") (?i "
\e$(3%D
\e(B") (?a "
\e$(3$V
\e(B") (?E "
\e$(3%T
\e(B"))
338 (?Y "
\e$(3$a
\e(B" (?a "
\e$(3$a
\e(B")))
340 ("
\e$(3#r
\e(B" (?e "
\e$(3#m
\e(B") (?u "
\e$(3#n
\e(B") (?i "
\e$(3#o
\e(B") (?a "
\e$(3#p
\e(B") (?E "
\e$(3#q
\e(B") (?o "
\e$(3#s
\e(B")
341 (?W "
\e$(3#z
\e(B" (?e "
\e$(3#u
\e(B") (?u "
\e$(3#z
\e(B") (?i "
\e$(3#w
\e(B") (?a "
\e$(3#x
\e(B") (?E "
\e$(3#y
\e(B"))
342 (?2 "
\e$(3%^
\e(B" (?e "
\e$(3%Y
\e(B") (?u "
\e$(3%Z
\e(B") (?i "
\e$(3%[
\e(B") (?a "
\e$(3%\
\e(B") (?E "
\e$(3%]
\e(B") (?o "
\e$(3%_
\e(B")))
344 ("
\e$(3!&
\e(B" (?e "
\e$(3!!
\e(B") (?u "
\e$(3!"
\e(B") (?i "
\e$(3!#
\e(B") (?a "
\e$(3!$
\e(B") (?E "
\e$(3!%
\e(B") (?o "
\e$(3!'
\e(B")
345 (?W "
\e$(3"P
\e(B" (?e "
\e$(3"K
\e(B") (?u "
\e$(3"P
\e(B") (?i "
\e$(3"M
\e(B") (?a "
\e$(3"N
\e(B") (?E "
\e$(3"O
\e(B"))
346 (?2 "
\e$(3"H
\e(B" (?e "
\e$(3"C
\e(B") (?u "
\e$(3"D
\e(B") (?i "
\e$(3"E
\e(B") (?a "
\e$(3"F
\e(B") (?E "
\e$(3"G
\e(B") (?o "
\e$(3"I
\e(B")
347 (?W "
\e$(3"P
\e(B" (?e "
\e$(3"K
\e(B") (?u "
\e$(3"P
\e(B") (?i "
\e$(3"M
\e(B") (?a "
\e$(3"N
\e(B") (?E "
\e$(3"O
\e(B"))))
349 ("
\e$(3"e
\e(B" (?2 "
\e$(3#7
\e(B"))
351 ("
\e$(3#j
\e(B" (?e "
\e$(3#e
\e(B") (?u "
\e$(3#f
\e(B") (?i "
\e$(3#g
\e(B") (?a "
\e$(3#h
\e(B") (?E "
\e$(3#i
\e(B") (?o "
\e$(3#k
\e(B")
352 (?W "
\e$(3#l
\e(B" (?a "
\e$(3#l
\e(B")
353 (?e "
\e$(3#j%n
\e(B") (?u "
\e$(3#j%r
\e(B") (?i "
\e$(3#j%o
\e(B") (?E "
\e$(3#j%q
\e(B")))
355 ("
\e$(3"p
\e(B" (?e "
\e$(3"k
\e(B") (?u "
\e$(3"l
\e(B") (?i "
\e$(3"m
\e(B") (?a "
\e$(3"n
\e(B") (?E "
\e$(3"o
\e(B") (?o "
\e$(3"q
\e(B")
356 (?W "
\e$(3"x
\e(B" (?e "
\e$(3"s
\e(B") (?u "
\e$(3"x
\e(B") (?i "
\e$(3"u
\e(B") (?a "
\e$(3"v
\e(B") (?E "
\e$(3"w
\e(B"))
357 (?2 "
\e$(3%>
\e(B" (?e "
\e$(3%9
\e(B") (?u "
\e$(3%:
\e(B") (?i "
\e$(3%;
\e(B") (?a "
\e$(3%<
\e(B") (?E "
\e$(3%=
\e(B") (?o "
\e$(3%?
\e(B")))
359 ("
\e$(3!.
\e(B" (?e "
\e$(3!)
\e(B") (?u "
\e$(3!*
\e(B") (?i "
\e$(3!+
\e(B") (?a "
\e$(3!,
\e(B") (?E "
\e$(3!-
\e(B") (?o "
\e$(3!/
\e(B")
360 (?W "
\e$(3!0
\e(B" (?a "
\e$(3!0
\e(B")
361 (?e "
\e$(3!.%n
\e(B") (?u "
\e$(3!.%r
\e(B") (?i "
\e$(3!.%o
\e(B") (?E "
\e$(3!.%q
\e(B")))
363 ("
\e$(3!>
\e(B" (?e "
\e$(3!9
\e(B") (?u "
\e$(3!:
\e(B") (?i "
\e$(3!;
\e(B") (?a "
\e$(3!<
\e(B") (?E "
\e$(3!=
\e(B") (?o "
\e$(3!?
\e(B")
364 (?W "
\e$(3%a
\e(B" (?e "
\e$(3%1
\e(B") (?u "
\e$(3%a
\e(B") (?i "
\e$(3%A
\e(B") (?a "
\e$(3!@
\e(B") (?E "
\e$(3%Q
\e(B"))
365 (?Y "
\e$(3$_
\e(B" (?a "
\e$(3$_
\e(B")))
367 ("
\e$(3"X
\e(B" (?e "
\e$(3"S
\e(B") (?u "
\e$(3"T
\e(B") (?i "
\e$(3"U
\e(B") (?a "
\e$(3"V
\e(B") (?E "
\e$(3"W
\e(B") (?o "
\e$(3"Y
\e(B")
368 (?W "
\e$(3"Z
\e(B" (?a "
\e$(3"Z
\e(B")
369 (?e "
\e$(3"X%n
\e(B") (?u "
\e$(3"X%r
\e(B") (?i "
\e$(3"X%o
\e(B") (?E "
\e$(3"X%q
\e(B")))
371 ("
\e$(3"i
\e(B" (?2 "
\e$(3#;
\e(B"))
373 ("
\e$(3$\
\e(B" (?e "
\e$(3$W
\e(B") (?u "
\e$(3$X
\e(B") (?i "
\e$(3$Y
\e(B") (?a "
\e$(3$Z
\e(B") (?E "
\e$(3$[
\e(B") (?o "
\e$(3$]
\e(B")
374 (?W "
\e$(3%e
\e(B" (?e "
\e$(3%5
\e(B") (?u "
\e$(3%e
\e(B") (?i "
\e$(3%E
\e(B") (?a "
\e$(3$^
\e(B") (?E "
\e$(3%U
\e(B")))
376 ("
\e$(3!f
\e(B" (?e "
\e$(3!a
\e(B") (?u "
\e$(3!b
\e(B") (?i "
\e$(3!c
\e(B") (?a "
\e$(3!d
\e(B") (?E "
\e$(3!e
\e(B") (?o "
\e$(3!g
\e(B")
377 (?W "
\e$(3!n
\e(B" (?e "
\e$(3!i
\e(B") (?u "
\e$(3!n
\e(B") (?i "
\e$(3!k
\e(B") (?a "
\e$(3!l
\e(B") (?E "
\e$(3!m
\e(B"))
378 (?2 "
\e$(3%.
\e(B" (?e "
\e$(3%)
\e(B") (?u "
\e$(3%*
\e(B") (?i "
\e$(3%+
\e(B") (?a "
\e$(3%,
\e(B") (?E "
\e$(3%-
\e(B") (?o "
\e$(3%/
\e(B")))
380 ("
\e$(3!N
\e(B" (?e "
\e$(3!I
\e(B") (?u "
\e$(3!J
\e(B") (?i "
\e$(3!K
\e(B") (?a "
\e$(3!L
\e(B") (?E "
\e$(3!M
\e(B") (?o "
\e$(3!O
\e(B")
381 (?W "
\e$(3!P
\e(B" (?a "
\e$(3!P
\e(B")
382 (?e "
\e$(3!N%n
\e(B") (?u "
\e$(3!N%r
\e(B") (?i "
\e$(3!N%o
\e(B") (?E "
\e$(3!N%q
\e(B"))
383 (?Y "
\e$(3$`
\e(B" (?a "
\e$(3$`
\e(B")))
385 ("
\e$(3!V
\e(B" (?e "
\e$(3!Q
\e(B") (?u "
\e$(3!R
\e(B") (?i "
\e$(3!S
\e(B") (?a "
\e$(3!T
\e(B") (?E "
\e$(3!U
\e(B") (?o "
\e$(3!W
\e(B")
386 (?W "
\e$(3!X
\e(B" (?a "
\e$(3!X
\e(B")
387 (?e "
\e$(3!V%n
\e(B") (?u "
\e$(3!V%r
\e(B") (?i "
\e$(3!V%o
\e(B") (?E "
\e$(3!V%q
\e(B"))
388 (?2 "
\e$(3!F
\e(B" (?e "
\e$(3!A
\e(B") (?u "
\e$(3!B
\e(B") (?i "
\e$(3!C
\e(B") (?a "
\e$(3!D
\e(B") (?E "
\e$(3!E
\e(B") (?o "
\e$(3!G
\e(B")
389 (?W "
\e$(3!H
\e(B" (?a "
\e$(3!H
\e(B")
390 (?e "
\e$(3!F%n
\e(B") (?u "
\e$(3!F%r
\e(B") (?i "
\e$(3!F%o
\e(B") (?E "
\e$(3!F%q
\e(B"))))
392 ("
\e$(3"8
\e(B" (?e "
\e$(3"3
\e(B") (?u "
\e$(3"4
\e(B") (?i "
\e$(3"5
\e(B") (?a "
\e$(3"6
\e(B") (?E "
\e$(3"7
\e(B") (?o "
\e$(3"9
\e(B")
393 (?W "
\e$(3":
\e(B" (?a "
\e$(3":
\e(B")
394 (?e "
\e$(3"8%n
\e(B") (?u "
\e$(3"8%r
\e(B") (?i "
\e$(3"8%o
\e(B") (?E "
\e$(3"8%q
\e(B")))
396 ("
\e$(3"d
\e(B" (?2 "
\e$(3#6
\e(B"))
398 ("
\e$(3"0
\e(B" (?e "
\e$(3"+
\e(B") (?u "
\e$(3",
\e(B") (?i "
\e$(3"-
\e(B") (?a "
\e$(3".
\e(B") (?E "
\e$(3"/
\e(B") (?o "
\e$(3"1
\e(B")
399 (?W "
\e$(3"2
\e(B" (?a "
\e$(3"2
\e(B")
400 (?e "
\e$(3"0%n
\e(B") (?u "
\e$(3"0%r
\e(B") (?i "
\e$(3"0%o
\e(B") (?E "
\e$(3"0%q
\e(B")))
402 ("
\e$(3#2
\e(B" (?e "
\e$(3#-
\e(B") (?u "
\e$(3#.
\e(B") (?i "
\e$(3#/
\e(B") (?a "
\e$(3#0
\e(B") (?E "
\e$(3#1
\e(B") (?o "
\e$(3#3
\e(B")
403 (?W "
\e$(3%p
\e(B" (?e "
\e$(3%n
\e(B") (?u "
\e$(3%r
\e(B") (?i "
\e$(3%o
\e(B") (?a "
\e$(3%p
\e(B") (?E "
\e$(3%q
\e(B")))
405 ("
\e$(3!^
\e(B" (?e "
\e$(3!Y
\e(B") (?u "
\e$(3!Z
\e(B") (?i "
\e$(3![
\e(B") (?a "
\e$(3!\
\e(B") (?E "
\e$(3!]
\e(B") (?o "
\e$(3!_
\e(B")
406 (?W "
\e$(3!`
\e(B" (?a "
\e$(3!`
\e(B")
407 (?e "
\e$(3!^%n
\e(B") (?u "
\e$(3!^%r
\e(B") (?i "
\e$(3!^%o
\e(B") (?E "
\e$(3!^%q
\e(B")))
409 ("
\e$(3#R
\e(B" (?e "
\e$(3#M
\e(B") (?u "
\e$(3#N
\e(B") (?i "
\e$(3#O
\e(B") (?a "
\e$(3#P
\e(B") (?E "
\e$(3#Q
\e(B") (?o "
\e$(3#S
\e(B")
410 (?W "
\e$(3#T
\e(B" (?a "
\e$(3#T
\e(B")
411 (?e "
\e$(3#R%n
\e(B") (?u "
\e$(3#R%r
\e(B") (?i "
\e$(3#R%o
\e(B") (?E "
\e$(3#R%q
\e(B")))
413 ("
\e$(3#B
\e(B" (?e "
\e$(3#=
\e(B") (?u "
\e$(3#>
\e(B") (?i "
\e$(3#?
\e(B") (?a "
\e$(3#@
\e(B") (?E "
\e$(3#A
\e(B") (?o "
\e$(3#C
\e(B")
414 (?W "
\e$(3#D
\e(B" (?a "
\e$(3#D
\e(B")
415 (?e "
\e$(3#B%n
\e(B") (?u "
\e$(3#B%r
\e(B") (?i "
\e$(3#B%o
\e(B") (?E "
\e$(3#B%q
\e(B")))
420 ;; To avoid byte-compiler warnings. It should never be set globally.
421 (defvar ethio-sera-being-called-by-w3)
422 ;; This variable will be bound by some third-party package.
423 (defvar sera-being-called-by-w3)
426 (defun ethio-sera-to-fidel-region (beg end &optional secondary force)
427 "Convert the characters in region from SERA to FIDEL.
428 The variable `ethio-primary-language' specifies the primary language
429 and `ethio-secondary-language' specifies the secondary.
431 If the 3rd parameter SECONDARY is given and non-nil, assume the region
432 begins begins with the secondary language; otherwise with the primary
435 If the 4th parameter FORCE is given and non-nil, perform conversion
436 even if the buffer is read-only.
438 See also the descriptions of the variables
439 `ethio-use-colon-for-colon' and
440 `ethio-use-three-dot-question'."
444 (narrow-to-region beg end)
445 (ethio-sera-to-fidel-buffer secondary force)))
448 (defun ethio-sera-to-fidel-buffer (&optional secondary force)
449 "Convert the current buffer from SERA to FIDEL.
451 The variable `ethio-primary-language' specifies the primary
452 language and `ethio-secondary-language' specifies the secondary.
454 If the 1st optional parameter SECONDARY is non-nil, assume the buffer
455 begins with the secondary language; otherwise with the primary
458 If the 2nd optional parametr FORCE is non-nil, perform conversion even if the
461 See also the descriptions of the variables
462 `ethio-use-colon-for-colon' and
463 `ethio-use-three-dot-question'."
467 (if (and buffer-read-only
469 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
472 (let ((ethio-primary-language ethio-primary-language)
473 (ethio-secondary-language ethio-secondary-language)
474 (ethio-use-colon-for-colon ethio-use-colon-for-colon)
475 (ethio-use-three-dot-question ethio-use-three-dot-question)
476 ;; The above four variables may be changed temporary
477 ;; by tilde escapes during conversion. So we bind them to other
478 ;; variables but of the same names.
479 (buffer-read-only nil)
480 (case-fold-search nil)
484 (setq current-language
486 ethio-secondary-language
487 ethio-primary-language))
489 (goto-char (point-min))
494 ((eq current-language 'english)
495 (ethio-sera-to-fidel-english))
496 ((eq current-language 'amharic)
497 (ethio-sera-to-fidel-ethio 'amharic))
498 ((eq current-language 'tigrigna)
499 (ethio-sera-to-fidel-ethio 'tigrigna))
500 (t ; we don't know what to do
501 (ethio-sera-to-fidel-english))))
503 (setq current-language
506 ;; when language tag is explicitly specified
507 ((not (eq next-language 'toggle))
510 ;; found a toggle in a primary language section
511 ((eq current-language ethio-primary-language)
512 ethio-secondary-language)
514 ;; found a toggle in a secondary, third, fourth, ...
517 ethio-primary-language))))
519 ;; If ethio-implicit-period-conversion is non-nil, the
520 ;; Ethiopic dot "
\e$(3%u
\e(B" at the end of an Ethiopic sentence is
521 ;; replaced with the Ethiopic full stop "
\e$(3$i
\e(B".
522 (if ethio-implicit-period-conversion
524 (goto-char (point-min))
525 (while (re-search-forward "\\([
\e$(3!!
\e(B-
\e$(3$a%)
\e(B-
\e$(3%e%n
\e(B-
\e$(3%r%s
\e(B]\\)
\e$(3%u
\e(B\\([ \t]\\)"
527 (replace-match "\\1
\e$(3$i
\e(B\\2"))
528 (goto-char (point-min))
529 (while (re-search-forward "\\([
\e$(3!!
\e(B-
\e$(3$a%)
\e(B-
\e$(3%e%n
\e(B-
\e$(3%r%s
\e(B]\\)
\e$(3%u
\e(B$" nil t)
530 (replace-match "\\1
\e$(3$i
\e(B"))))
533 (goto-char (point-min))
534 (while (re-search-forward "\\ce
\e$(3%s
\e(B" nil 0)
536 (save-excursion (backward-char 2) (point))
540 (defun ethio-sera-to-fidel-english nil
541 "Handle English section in SERA to FIDEL conversion.
542 Conversion stops when a language switch is found. Then delete that
543 switch and return the name of the new language as a symbol."
544 (let ((new-language nil))
546 (while (and (not (eobp)) (null new-language))
549 ;; if no more "\", nothing to do.
550 ((not (search-forward "\\" nil 0)))
552 ;; hereafter point is put after a "\".
553 ;; first delete that "\", then check the following chars
555 ;; "\\" : leave the second "\"
557 (delete-backward-char 1)
558 (= (following-char) ?\\ ))
561 ;; "\ " : delete the following " "
562 ((= (following-char) 32)
564 (setq new-language 'toggle))
567 ((setq new-language (ethio-process-language-flag)))
569 ;; just a "\" : not special sequence.
571 (setq new-language 'toggle))))
575 (defun ethio-sera-to-fidel-ethio (lang)
576 "Handle Ethiopic section in SERA to FIDEL conversion.
577 Conversion stops when a language switch is found. Then delete that
578 switch and return the name of the new language as a symbol.
580 The parameter LANG (symbol, either `amharic' or `tigrigna') affects
581 the conversion of \"a\"."
583 (let ((new-language nil)
585 start table table2 ch)
587 (setcar (aref ethio-sera-to-fidel-table ?a)
588 (if (eq lang 'tigrigna) "
\e$(3"f
\e(B" "
\e$(3"c
\e(B"))
590 (while (and (not (eobp)) (null new-language))
591 (setq ch (following-char))
594 ;; skip from "<" to ">" (or from "&" to ";") if in w3-mode
595 ((and (or (= ch ?<) (= ch ?&))
596 (or (and (boundp 'ethio-sera-being-called-by-w3)
597 ethio-sera-being-called-by-w3)
598 (and (boundp 'sera-being-called-by-w3)
599 sera-being-called-by-w3)))
600 (search-forward (if (= ch ?<) ">" ";")
603 ;; leave non-ASCII characters as they are
608 ((looking-at "`[1-9][0-9]*")
610 (ethio-convert-digit))
612 ;; if not seeing a "\", do sera to fidel conversion
616 (setq table (aref ethio-sera-to-fidel-table ch))
617 (while (setq table2 (cdr (assoc (following-char) table)))
620 (if (setq ch (car table))
622 (delete-region start (point))
625 (insert (eval ch))))))
627 ;; if control reaches here, we must be looking at a "\"
631 (if (looking-at "\\\\~! ?")
633 ;; "\~!" or "\~! ". switch to non-verbatim mode
638 ;; "\" but not "\~!" nor "\~! ". skip the current "\".
641 ;; hereafter, non-verbatim mode and looking at a "\"
642 ;; first delete that "\", then check the following chars.
644 ;; "\ " : delete the following " "
647 (setq ch (following-char))
650 (setq new-language 'toggle))
652 ;; "\~!" or "\~! " : switch to verbatim mode
658 ((setq new-language (ethio-process-language-flag)))
660 ;; "\~" but not "\~!" nor a language flag
663 (ethio-tilde-escape))
665 ;; ASCII punctuation escape. skip
666 ((looking-at "\\(,\\|\\.\\|;\\|:\\|'\\|`\\|\?\\|\\\\\\)+")
667 (goto-char (match-end 0)))
669 ;; "\", but not special sequence
671 (setq new-language 'toggle))))
675 (defun ethio-process-language-flag nil
676 "Process a language flag of the form \"~lang\" or \"~lang1~lang2\".
678 If looking at \"~lang1~lang2\", set `ethio-primary-language' and
679 `ethio-une-secondary-language' based on \"lang1\" and \"lang2\".
680 Then delete the language flag \"~lang1~lang2\" from the buffer.
681 Return value is the new primary language.
683 If looking at \"~lang\", delete that language flag \"~lang\" from the
684 buffer and return that language. In this case
685 `ethio-primary-language' and `ethio-uni-secondary-language'
688 If an unsupported language flag is found, just return nil without
696 "~\\([a-z][a-z][a-z]?\\)~\\([a-z][a-z][a-z]?\\)[ \t\n\\]")
698 (ethio-flag-to-language
699 (buffer-substring (match-beginning 1) (match-end 1))))
701 (ethio-flag-to-language
702 (buffer-substring (match-beginning 2) (match-end 2)))))
703 (setq ethio-primary-language lang1
704 ethio-secondary-language lang2)
705 (delete-region (point) (match-end 2))
706 (if (= (following-char) 32)
708 ethio-primary-language)
711 ((and (looking-at "~\\([a-z][a-z][a-z]?\\)[ \t\n\\]")
713 (ethio-flag-to-language
714 (buffer-substring (match-beginning 1) (match-end 1)))))
715 (delete-region (point) (match-end 1))
716 (if (= (following-char) 32)
724 (defun ethio-tilde-escape nil
725 "Handle a SERA tilde escape in Ethiopic section and delete it.
726 Delete the escape even it is not recognised."
728 (let ((p (point)) command)
729 (skip-chars-forward "^ \t\n\\\\")
730 (setq command (buffer-substring p (point)))
731 (delete-region p (point))
732 (if (= (following-char) 32)
738 ((string= command "-:")
739 (setq ethio-use-colon-for-colon t))
742 ((string= command "`:")
743 (setq ethio-use-colon-for-colon nil))
746 ((string= command "?")
747 (setq ethio-use-three-dot-question nil))
750 ((string= command "`|")
751 (setq ethio-use-three-dot-question t))
754 ((string= command "e")
755 (insert "
\e$(3%j
\e(B"))
758 ((string= command "E")
759 (insert "
\e$(3%k
\e(B"))
762 ((string= command "a")
763 (insert "
\e$(3%l
\e(B"))
766 ((string= command "A")
767 (insert "
\e$(3%m
\e(B"))
770 ((string= command "X")
771 (insert "
\e$(3%i
\e(B"))
773 ;; unsupported tilde escape
777 (defun ethio-flag-to-language (flag)
779 ((or (string= flag "en") (string= flag "eng")) 'english)
780 ((or (string= flag "ti") (string= flag "tir")) 'tigrigna)
781 ((or (string= flag "am") (string= flag "amh")) 'amharic)
784 (defun ethio-convert-digit nil
785 "Convert Arabic digits to Ethiopic digits."
787 (while (and (>= (setq ch (following-char)) ?1)
791 ;; count up following zeros
793 (while (= (following-char) ?0)
799 ;; first digit is 10, 20, ..., or 90
801 (insert (aref [?
\e$(3$y
\e(B ?
\e$(3$z
\e(B ?
\e$(3${
\e(B ?
\e$(3$|
\e(B ?
\e$(3$}
\e(B ?
\e$(3$~
\e(B ?
\e$(3%!
\e(B ?
\e$(3%"
\e(B ?
\e$(3%#
\e(B] (- ch ?1)))
804 ;; first digit is 2, 3, ..., or 9
806 (insert (aref [?
\e$(3$q
\e(B ?
\e$(3$r
\e(B ?
\e$(3$s
\e(B ?
\e$(3$t
\e(B ?
\e$(3$u
\e(B ?
\e$(3$v
\e(B ?
\e$(3$w
\e(B ?
\e$(3$x
\e(B] (- ch ?2))))
810 (insert "
\e$(3$p
\e(B")))
814 (insert "
\e$(3%$
\e(B"))
817 (insert-char ?
\e$(3%%
\e(B (/ z 4)))))
820 (defun ethio-sera-to-fidel-mail-or-marker (&optional arg)
821 "Execute ethio-sera-to-fidel-mail or ethio-sera-to-fidel-marker depending on the current major mode.
822 If in rmail-mode or in mail-mode, execute the former; otherwise latter."
825 (if (or (eq major-mode 'rmail-mode)
826 (eq major-mode 'mail-mode))
827 (ethio-sera-to-fidel-mail (prefix-numeric-value arg))
828 (ethio-sera-to-fidel-marker arg)))
831 (defun ethio-sera-to-fidel-mail (&optional arg)
832 "Convert SERA to FIDEL to read/write mail and news.
834 If the buffer contains the markers \"<sera>\" and \"</sera>\",
835 convert the segments between them into FIDEL.
837 If invoked interactively and there is no marker, convert the subject field
838 and the body into FIDEL using `ethio-sera-to-fidel-region'."
841 (let ((buffer-read-only nil)
845 ;; follow RFC822 rules instead of looking for a fixed separator
848 (setq border (point))
850 ;; note that the point is placed at the border
851 (if (or (re-search-forward "^<sera>$" nil t)
853 (goto-char (point-min))
854 (re-search-forward "^Subject: <sera>" border t)))
858 ;; we start with the body so that the border will not change
859 ;; use "^<sera>\n" instead of "^<sera>$" not to leave a blank line
861 (while (re-search-forward "^<sera>\n" nil t)
863 (ethio-sera-to-fidel-region
866 (if (re-search-forward "^</sera>\n" nil 0)
869 ;; now process the subject
870 (goto-char (point-min))
871 (if (re-search-forward "^Subject: <sera>" border t)
872 (ethio-sera-to-fidel-region
873 (progn (delete-backward-char 6) (point))
875 (if (re-search-forward "</sera>$" (line-end-position) 0)
879 ;; in case there are no marks but invoked interactively
882 (ethio-sera-to-fidel-region border (point-max))
883 (goto-char (point-min))
884 (if (re-search-forward "^Subject: " border t)
885 (ethio-sera-to-fidel-region (point) (line-end-position))))))
887 ;; adjust the rmail marker
888 (if (eq major-mode 'rmail-mode)
890 (aref rmail-message-vector (1+ rmail-current-message))
894 (defun ethio-sera-to-fidel-marker (&optional force)
895 "Convert the regions surrounded by \"<sera>\" and \"</sera>\" from SERA to FIDEL.
896 Assume that each region begins with `ethio-primary-language'.
897 The markers \"<sera>\" and \"</sera>\" themselves are not deleted."
899 (if (and buffer-read-only
901 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
904 (goto-char (point-min))
905 (while (re-search-forward "<sera>" nil t)
906 (ethio-sera-to-fidel-region
908 (if (re-search-forward "</sera>" nil t)
918 (defconst ethio-fidel-to-sera-map
919 [ "he" "hu" "hi" "ha" "hE" "h" "ho" "" ;; 0 - 7
920 "le" "lu" "li" "la" "lE" "l" "lo" "lWa" ;; 8
921 "He" "Hu" "Hi" "Ha" "HE" "H" "Ho" "HWa" ;; 16
922 "me" "mu" "mi" "ma" "mE" "m" "mo" "mWa" ;; 24
923 "`se" "`su" "`si" "`sa" "`sE" "`s" "`so" "`sWa" ;; 32
924 "re" "ru" "ri" "ra" "rE" "r" "ro" "rWa" ;; 40
925 "se" "su" "si" "sa" "sE" "s" "so" "sWa" ;; 48
926 "xe" "xu" "xi" "xa" "xE" "x" "xo" "xWa" ;; 56
927 "qe" "qu" "qi" "qa" "qE" "q" "qo" "" ;; 64
928 "qWe" "" "qWi" "qWa" "qWE" "qW'" "" "" ;; 72
929 "Qe" "Qu" "Qi" "Qa" "QE" "Q" "Qo" "" ;; 80
930 "QWe" "" "QWi" "QWa" "QWE" "QW'" "" "" ;; 88
931 "be" "bu" "bi" "ba" "bE" "b" "bo" "bWa" ;; 96
932 "ve" "vu" "vi" "va" "vE" "v" "vo" "vWa" ;; 104
933 "te" "tu" "ti" "ta" "tE" "t" "to" "tWa" ;; 112
934 "ce" "cu" "ci" "ca" "cE" "c" "co" "cWa" ;; 120
935 "`he" "`hu" "`hi" "`ha" "`hE" "`h" "`ho" "" ;; 128
936 "hWe" "" "hWi" "hWa" "hWE" "hW'" "" "" ;; 136
937 "ne" "nu" "ni" "na" "nE" "n" "no" "nWa" ;; 144
938 "Ne" "Nu" "Ni" "Na" "NE" "N" "No" "NWa" ;; 152
939 "e" "u" "i" "A" "E" "I" "o" "ea" ;; 160
940 "ke" "ku" "ki" "ka" "kE" "k" "ko" "" ;; 168
941 "kWe" "" "kWi" "kWa" "kWE" "kW'" "" "" ;; 176
942 "Ke" "Ku" "Ki" "Ka" "KE" "K" "Ko" "" ;; 184
943 "KWe" "" "KWi" "KWa" "KWE" "KW'" "" "" ;; 192
944 "we" "wu" "wi" "wa" "wE" "w" "wo" "" ;; 200
945 "`e" "`u" "`i" "`a" "`E" "`I" "`o" "" ;; 208
946 "ze" "zu" "zi" "za" "zE" "z" "zo" "zWa" ;; 216
947 "Ze" "Zu" "Zi" "Za" "ZE" "Z" "Zo" "ZWa" ;; 224
948 "ye" "yu" "yi" "ya" "yE" "y" "yo" "yWa" ;; 232
949 "de" "du" "di" "da" "dE" "d" "do" "dWa" ;; 240
950 "De" "Du" "Di" "Da" "DE" "D" "Do" "DWa" ;; 248
951 "je" "ju" "ji" "ja" "jE" "j" "jo" "jWa" ;; 256
952 "ge" "gu" "gi" "ga" "gE" "g" "go" "" ;; 264
953 "gWe" "" "gWi" "gWa" "gWE" "gW'" "" "" ;; 272
954 "Ge" "Gu" "Gi" "Ga" "GE" "G" "Go" "GWa" ;; 280
955 "Te" "Tu" "Ti" "Ta" "TE" "T" "To" "TWa" ;; 288
956 "Ce" "Cu" "Ci" "Ca" "CE" "C" "Co" "CWa" ;; 296
957 "Pe" "Pu" "Pi" "Pa" "PE" "P" "Po" "PWa" ;; 304
958 "Se" "Su" "Si" "Sa" "SE" "S" "So" "SWa" ;; 312
959 "`Se" "`Su" "`Si" "`Sa" "`SE" "`S" "`So" "" ;; 320
960 "fe" "fu" "fi" "fa" "fE" "f" "fo" "fWa" ;; 328
961 "pe" "pu" "pi" "pa" "pE" "p" "po" "pWa" ;; 336
962 "mYa" "rYa" "fYa" "" "" "" "" "" ;; 344
963 " " " : " "::" "," ";" "-:" ":-" "`?" ;; 352
964 ":|:" "1" "2" "3" "4" "5" "6" "7" ;; 360
965 "8" "9" "10" "20" "30" "40" "50" "60" ;; 368
966 "70" "80" "90" "100" "10000" "" "" "" ;; 376
967 "`qe" "`qu" "`qi" "`qa" "`qE" "`q" "`qo" "" ;; 384
968 "mWe" "bWe" "GWe" "fWe" "pWe" "" "" "" ;; 392
969 "`ke" "`ku" "`ki" "`ka" "`kE" "`k" "`ko" "" ;; 400
970 "mWi" "bWi" "GWi" "fWi" "pWi" "" "" "" ;; 408
971 "Xe" "Xu" "Xi" "Xa" "XE" "X" "Xo" "" ;; 416
972 "mWE" "bWE" "GWE" "fWE" "pWE" "" "" "" ;; 424
973 "`ge" "`gu" "`gi" "`ga" "`gE" "`g" "`go" "" ;; 432
974 "mW'" "bW'" "GW'" "fW'" "pW'" "" "" "" ;; 440
975 "\\~X " "\\~e " "\\~E " "\\~a " "\\~A " "wWe" "wWi" "wWa" ;; 448
976 "wWE" "wW'" "''" "`!" "." "<<" ">>" "?" ]) ;; 456
978 (defun ethio-prefer-amharic-p nil
979 (or (eq ethio-primary-language 'amharic)
980 (and (not (eq ethio-primary-language 'tigrigna))
981 (eq ethio-secondary-language 'amharic))))
983 (defun ethio-language-to-flag (lang)
985 ((eq lang 'english) "eng")
986 ((eq lang 'tigrigna) "tir")
987 ((eq lang 'amharic) "amh")
991 (defun ethio-fidel-to-sera-region (begin end &optional secondary force)
992 "Replace all the FIDEL characters in the region to the SERA format.
993 The variable `ethio-primary-language' specifies the primary
994 language and `ethio-secondary-language' specifies the secondary.
996 If the 3dr parameter SECONDARY is given and non-nil, try to convert
997 the region so that it begins in the secondary language; otherwise with
998 the primary language.
1000 If the 4th parameter FORCE is given and non-nil, convert even if the
1001 buffer is read-only.
1003 See also the descriptions of the variables
1004 `ethio-use-colon-for-colon', `ethio-use-three-dot-question',
1005 `ethio-quote-vowel-always' and `ethio-numeric-reduction'."
1007 (interactive "r\nP")
1009 (narrow-to-region begin end)
1010 (ethio-fidel-to-sera-buffer secondary force)))
1013 (defun ethio-fidel-to-sera-buffer (&optional secondary force)
1014 "Replace all the FIDEL characters in the current buffer to the SERA format.
1015 The variable `ethio-primary-language' specifies the primary
1016 language and `ethio-secondary-language' specifies the secondary.
1018 If the 1st optional parameter SECONDARY is non-nil, try to convert the
1019 region so that it begins in the secondary language; otherwise with the
1022 If the 2nd optional parameter FORCE is non-nil, convert even if the
1023 buffer is read-only.
1025 See also the descriptions of the variables
1026 `ethio-use-colon-for-colon', `ethio-use-three-dot-question',
1027 `ethio-quote-vowel-always' and `ethio-numeric-reduction'."
1030 (if (and buffer-read-only
1032 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
1035 (let ((buffer-read-only nil)
1036 (case-fold-search nil)
1037 (lonec nil) ;; t means previous char was a lone consonant
1038 (fidel nil) ;; t means previous char was a FIDEL
1039 (digit nil) ;; t means previous char was an Ethiopic digit
1040 (flag (if (ethio-prefer-amharic-p) "\\~amh " "\\~tir "))
1043 ;; user's preference in transcription
1044 (if ethio-use-colon-for-colon
1046 (aset ethio-fidel-to-sera-map 353 "`:")
1047 (aset ethio-fidel-to-sera-map 357 ":"))
1048 (aset ethio-fidel-to-sera-map 353 " : ")
1049 (aset ethio-fidel-to-sera-map 357 "-:"))
1051 (if ethio-use-three-dot-question
1053 (aset ethio-fidel-to-sera-map 359 "?")
1054 (aset ethio-fidel-to-sera-map 463 "`?"))
1055 (aset ethio-fidel-to-sera-map 359 "`?")
1056 (aset ethio-fidel-to-sera-map 463 "?"))
1060 (aset (aref ethio-fidel-to-sera-map x)
1062 (if ethio-W-sixth-always ?' ?u)))
1063 '(77 93 141 181 197 277 440 441 442 443 444 457))
1065 (if (ethio-prefer-amharic-p)
1066 (aset ethio-fidel-to-sera-map 160 "a")
1067 (aset ethio-fidel-to-sera-map 160 "e"))
1068 ;; end of user's preference
1070 ;; first, decompose geminated characters
1071 (decompose-region (point-min) (point-max))
1073 ;; main conversion routine
1074 (goto-char (point-min))
1076 (setq ch (following-char))
1078 (cond ; ethiopic, english, neutral
1080 ;; ethiopic character. must go to ethiopic mode, if not in it.
1081 ((eq (char-charset ch) 'ethiopic)
1082 (setq ch (ethio-char-to-ethiocode ch))
1084 (if (not (eq mode 'ethiopic))
1087 (setq mode 'ethiopic)))
1089 (cond ; fidel, punc, digit
1092 ((or (<= ch 346) ; he - fYa
1093 (and (>= ch 384) (<= ch 444)) ; `qe - pw
1094 (and (>= ch 453) (<= ch 457))) ; wWe - wW
1095 (if (and (memq ch '(160 161 162 163 164 166 167)) ; (e - ea)
1097 (and ethio-quote-vowel-always
1100 (insert (aref ethio-fidel-to-sera-map ch))
1101 (setq lonec (ethio-lone-consonant-p ch)
1105 ;; punctuations or icons
1106 ((or (and (>= ch 353) (<= ch 360)) ; : - :|:
1107 (>= ch 458) ; '' - ?
1108 (and (>= ch 448) (<= ch 452))) ; \~X \~e \~E \~a \~A
1109 (insert (aref ethio-fidel-to-sera-map ch))
1114 ;; now CH must be an ethiopic digit
1116 ;; reduction = 0 or not preceded by Ethiopic number(s)
1117 ((or (= ethio-numeric-reduction 0)
1119 (insert "`" (aref ethio-fidel-to-sera-map ch))
1124 ;; reduction = 2 and following 10s, 100s, 10000s
1125 ((and (= ethio-numeric-reduction 2)
1126 (memq ch '(370 379 380)))
1127 (insert (substring (aref ethio-fidel-to-sera-map ch) 1))
1132 ;; ordinary following digits
1134 (insert (aref ethio-fidel-to-sera-map ch))
1139 ;; english character. must go to english mode, if not in it.
1140 ((or (and (>= ch ?a) (<= ch ?z))
1141 (and (>= ch ?A) (<= ch ?Z)))
1142 (if (not (eq mode 'english))
1150 ;; ch can appear both in ethiopic section and in english section.
1153 ;; we must decide the mode, if not decided yet
1158 ethio-secondary-language
1159 ethio-primary-language))
1160 (if (eq mode 'english)
1163 (setq mode 'ethiopic)))) ; tigrigna & amharic --> ethiopic
1165 (cond ; \ , eng-mode , punc , w3 , other
1167 ;; backslash is always quoted
1172 ;; nothing to do if in english mode
1176 ;; now we must be in ethiopic mode and seeing a non-"\"
1178 ;; ascii punctuations in ethiopic mode
1179 ((looking-at "[,.;:'`?]+")
1181 (goto-char (1+ (match-end 0)))) ; because we inserted one byte (\)
1183 ;; skip from "<" to ">" (or from "&" to ";") if called from w3
1184 ((and (or (= ch ?<) (= ch ?&))
1185 (or (and (boundp 'ethio-sera-being-called-by-w3)
1186 ethio-sera-being-called-by-w3)
1187 (and (boundp 'sera-being-called-by-w3)
1188 sera-being-called-by-w3)))
1189 (search-forward (if (= ch ?<) ">" ";")
1192 ;; neutral character. no need to quote. just skip it.
1199 ;; end of main conversion routine
1202 (defun ethio-lone-consonant-p (ethiocode)
1203 "If ETHIOCODE is an Ethiopic lone consonant, return t."
1204 (or (and (< ethiocode 344) (= (% ethiocode 8) 5))
1206 ;; `q `k X `g mW bW GW fW pW wW
1207 (memq ethiocode '(389 405 421 437 440 441 442 443 444 457))))
1210 (defun ethio-fidel-to-sera-mail-or-marker (&optional arg)
1211 "Execute ethio-fidel-to-sera-mail or ethio-fidel-to-sera-marker depending on the current major mode.
1212 If in rmail-mode or in mail-mode, execute the former; otherwise latter."
1215 (if (or (eq major-mode 'rmail-mode)
1216 (eq major-mode 'mail-mode))
1217 (ethio-fidel-to-sera-mail)
1218 (ethio-fidel-to-sera-marker arg)))
1221 (defun ethio-fidel-to-sera-mail nil
1222 "Convert FIDEL to SERA to read/write mail and news.
1224 If the body contains at least one Ethiopic character,
1225 1) insert the string \"<sera>\" at the beginning of the body,
1226 2) insert \"</sera>\" at the end of the body, and
1227 3) convert the body into SERA.
1229 The very same procedure applies to the subject field, too."
1232 (let ((buffer-read-only nil)
1236 ;; follow RFC822 rules instead of looking for a fixed separator
1239 (setq border (point))
1241 ;; process body first not to change the border
1242 ;; note that the point is already at the border
1243 (if (re-search-forward "\\ce" nil t)
1245 (ethio-fidel-to-sera-region border (point-max))
1248 (goto-char (point-max))
1249 (insert "</sera>")))
1252 (goto-char (point-min))
1253 (if (re-search-forward "^Subject: " border t)
1255 (end (line-end-position)))
1256 (if (re-search-forward "\\ce" end t)
1258 (ethio-fidel-to-sera-region beg end)
1262 (insert "</sera>")))))
1264 ;; adjust the rmail marker
1265 (if (eq major-mode 'rmail-mode)
1267 (aref rmail-message-vector (1+ rmail-current-message))
1271 (defun ethio-fidel-to-sera-marker (&optional force)
1272 "Convert the regions surrounded by \"<sera>\" and \"</sera>\" from FIDEL to SERA.
1273 The markers \"<sera>\" and \"</sera>\" themselves are not deleted."
1276 (if (and buffer-read-only
1278 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
1281 (goto-char (point-min))
1282 (while (re-search-forward "<sera>" nil t)
1283 (ethio-fidel-to-sera-region
1285 (if (re-search-forward "</sera>" nil t)
1292 ;; vowel modification
1296 (defun ethio-modify-vowel nil
1297 "Modify the vowel of the FIDEL that is under the cursor."
1299 (let ((ch (following-char))
1300 (composite nil) ; geminated or not
1301 newch base vowel modulo)
1304 ;; in case of gemination
1305 ((eq (char-charset ch) 'composition)
1306 (setq ch (string-to-char (char-to-string ch))
1308 ;; neither gemination nor fidel
1309 ((not (eq (char-charset ch) 'ethiopic))
1310 (error "Not a valid character")))
1312 ;; set frequently referred character features
1313 (setq ch (ethio-char-to-ethiocode ch)
1317 (if (or (and (>= ch 344) (<= ch 380)) ;; mYa - `10000
1318 (and (>= ch 448) (<= ch 452)) ;; \~X - \~A
1319 (>= ch 458)) ;; private punctuations
1320 (error "Not a valid character"))
1326 ;; first standalone vowels
1328 (if (ethio-prefer-amharic-p)
1329 (message "Modify vowel to: [auiAEIoW\"] ")
1330 (message "Modify vowel to: [euiAEIoW\"] "))
1331 (setq vowel (read-char))
1341 ((= vowel ?a) (if (ethio-prefer-amharic-p) 160 163))
1342 ((= vowel ?\") (setq composite t) ch)
1345 ;; second standalone vowels
1347 (message "Modify vowel to: [euiaEIo\"] ")
1348 (setq vowel (read-char))
1357 ((= vowel ?\") (setq composite t) ch)
1360 ;; 12-form consonants, *W* form
1361 ((memq base '(72 88 136 176 192 272)) ; qW QW hW kW KW gW
1362 (message "Modify vowel to: [euiaE'\"] ")
1363 (setq vowel (read-char))
1366 ((= vowel ?u) (+ base 5))
1367 ((= vowel ?i) (+ base 2))
1368 ((= vowel ?a) (+ base 3))
1369 ((= vowel ?E) (+ base 4))
1370 ((= vowel ?') (+ base 5))
1371 ((= vowel ?\") (setq composite t) ch)
1374 ;; extended 12-form consonants, mWa bWa GWa fWa pWa
1376 (message "Modify vowel to: [euiaE'\"] ")
1377 (setq vowel (read-char))
1385 ((= vowel ?\") (setq composite t) ch)
1388 (message "Modify vowel to: [euiaE'\"] ")
1389 (setq vowel (read-char))
1397 ((= vowel ?\") (setq composite t) ch)
1400 (message "Modify vowel to: [euiaE'\"] ")
1401 (setq vowel (read-char))
1409 ((= vowel ?\") (setq composite t) ch)
1412 (message "Modify vowel to: [euiaE'\"] ")
1413 (setq vowel (read-char))
1421 ((= vowel ?\") (setq composite t) ch)
1424 (message "Modify vowel to: [euiaE'\"] ")
1425 (setq vowel (read-char))
1433 ((= vowel ?\") (setq composite t) ch)
1436 ;; extended 12-form consonatns, mW* bW* GW* fW* pW*
1437 ((memq base '(392 408 424 440)) ; *We *Wi *WE *W
1438 (message "Modify vowel to: [eiEau'\"] ")
1439 (setq vowel (read-char))
1441 ((= vowel ?e) (+ 392 modulo))
1442 ((= vowel ?i) (+ 408 modulo))
1443 ((= vowel ?E) (+ 424 modulo))
1445 ((= modulo 0) 31) ; mWa
1446 ((= modulo 1) 103) ; bWa
1447 ((= modulo 2) 287) ; GWa
1448 ((= modulo 3) 335) ; fWa
1449 ((= modulo 4) 343) ; pWa
1450 (t nil))) ; never reach here
1451 ((= vowel ?') (+ 440 modulo))
1452 ((= vowel ?u) (+ 440 modulo))
1453 ((= vowel ?\") (setq composite t) ch)
1456 ((and (>= ch 453) (<= ch 457)) ; wWe wWi wWa wWE wW
1457 (message "Modify vowel to: [eiaE'u\"] ")
1458 (setq vowel (read-char))
1466 ((= vowel ?\") (setq composite t) ch)
1469 ;; 7-form consonants, or
1470 ;; first 7 of 8-form consonants
1472 (message "Modify vowel to: [euiaE'o\"] ")
1473 (setq vowel (read-char))
1476 ((= vowel ?u) (+ base 1))
1477 ((= vowel ?i) (+ base 2))
1478 ((= vowel ?a) (+ base 3))
1479 ((= vowel ?E) (+ base 4))
1480 ((= vowel ?') (+ base 5))
1481 ((= vowel ?o) (+ base 6))
1482 ((= vowel ?\") (setq composite t) ch)
1491 ;; could not get new character
1493 (error "Invalid vowel"))
1495 ;; vowel changed on a composite Fidel
1500 (concat (char-to-string (ethio-ethiocode-to-char newch)) "
\e$(3%s
\e(B"))))
1502 ;; simple vowel modification
1505 (insert (ethio-ethiocode-to-char newch))))))
1507 (defun ethio-ethiocode-to-char (ethiocode)
1510 (+ (/ ethiocode 94) 33)
1511 (+ (mod ethiocode 94) 33)))
1513 (defun ethio-char-to-ethiocode (ch)
1514 (and (eq (char-charset ch) 'ethiopic)
1515 (let ((char-components (split-char ch)))
1516 (+ (* (- (nth 1 char-components) 33) 94)
1517 (- (nth 2 char-components) 33)))))
1520 ;; space replacement
1524 (defun ethio-replace-space (ch begin end)
1525 "Replace ASCII spaces with Ethiopic word separators in the region.
1527 In the specified region, replace word separators surrounded by two
1528 Ethiopic characters, depending on the first parameter CH, which should
1531 If CH = 1, word separator will be replaced with an ASCII space.
1532 If CH = 2, with two ASCII spaces.
1533 If CH = 3, with the Ethiopic colon-like word separator.
1535 The second and third parameters BEGIN and END specify the region."
1537 (interactive "*cReplace spaces to: 1 (sg col), 2 (dbl col), 3 (Ethiopic)\nr")
1538 (if (not (memq ch '(?1 ?2 ?3)))
1542 (narrow-to-region begin end)
1546 ;; an Ethiopic word separator --> an ASCII space
1547 (goto-char (point-min))
1548 (while (search-forward "
\e$(3$h
\e(B" nil t)
1549 (replace-match " " nil t))
1551 ;; two ASCII spaces between Ethiopic characters --> an ASCII space
1552 (goto-char (point-min))
1553 (while (re-search-forward "\\(\\ce\\) \\(\\ce\\)" nil t)
1554 (replace-match "\\1 \\2")
1555 (goto-char (match-beginning 2))))
1558 ;; An Ethiopic word separator --> two ASCII spaces
1559 (goto-char (point-min))
1560 (while (search-forward "
\e$(3$h
\e(B" nil t)
1561 (replace-match " "))
1563 ;; An ASCII space between Ethiopic characters --> two ASCII spaces
1564 (goto-char (point-min))
1565 (while (re-search-forward "\\(\\ce\\) \\(\\ce\\)" nil t)
1566 (replace-match "\\1 \\2")
1567 (goto-char (match-beginning 2))))
1570 ;; One or two ASCII spaces between Ethiopic characters
1571 ;; --> An Ethiopic word separator
1572 (goto-char (point-min))
1573 (while (re-search-forward "\\(\\ce\\) ?\\(\\ce\\)" nil t)
1574 (replace-match "\\1
\e$(3$h
\e(B\\2")
1575 (goto-char (match-beginning 2)))
1577 ;; Three or more ASCII spaces between Ethiopic characters
1578 ;; --> An Ethiopic word separator + (N - 2) ASCII spaces
1579 (goto-char (point-min))
1580 (while (re-search-forward "\\(\\ce\\) \\( *\\ce\\)" nil t)
1581 (replace-match "\\1
\e$(3$h
\e(B\\2")
1582 (goto-char (match-beginning 2))))))))
1589 (defun ethio-input-special-character (arg)
1590 "Allow the user to input special characters."
1591 (interactive "*cInput number: 1.
\e$(3%j
\e(B 2.
\e$(3%k
\e(B 3.
\e$(3%l
\e(B 4.
\e$(3%m
\e(B 5.
\e$(3%i
\e(B")
1594 (insert "
\e$(3%j
\e(B"))
1596 (insert "
\e$(3%k
\e(B"))
1598 (insert "
\e$(3%l
\e(B"))
1600 (insert "
\e$(3%m
\e(B"))
1602 (insert "
\e$(3%i
\e(B"))
1610 (defconst ethio-fidel-to-tex-map
1611 [ "heG" "huG" "hiG" "haG" "hEG" "hG" "hoG" "" ;; 0 - 7
1612 "leG" "luG" "liG" "laG" "lEG" "lG" "loG" "lWaG" ;; 8
1613 "HeG" "HuG" "HiG" "HaG" "HEG" "HG" "HoG" "HWaG" ;; 16
1614 "meG" "muG" "miG" "maG" "mEG" "mG" "moG" "mWaG" ;; 24
1615 "sseG" "ssuG" "ssiG" "ssaG" "ssEG" "ssG" "ssoG" "ssWaG" ;; 32
1616 "reG" "ruG" "riG" "raG" "rEG" "rG" "roG" "rWaG" ;; 40
1617 "seG" "suG" "siG" "saG" "sEG" "sG" "soG" "sWaG" ;; 48
1618 "xeG" "xuG" "xiG" "xaG" "xEG" "xG" "xoG" "xWaG" ;; 56
1619 "qeG" "quG" "qiG" "qaG" "qEG" "qG" "qoG" "" ;; 64
1620 "qWeG" "" "qWiG" "qWaG" "qWEG" "qWG" "" "" ;; 72
1621 "QeG" "QuG" "QiG" "QaG" "QEG" "QG" "QoG" "" ;; 80
1622 "QWeG" "" "QWiG" "QWaG" "QWEG" "QWG" "" "" ;; 88
1623 "beG" "buG" "biG" "baG" "bEG" "bG" "boG" "bWaG" ;; 96
1624 "veG" "vuG" "viG" "vaG" "vEG" "vG" "voG" "vWaG" ;; 104
1625 "teG" "tuG" "tiG" "taG" "tEG" "tG" "toG" "tWaG" ;; 112
1626 "ceG" "cuG" "ciG" "caG" "cEG" "cG" "coG" "cWaG" ;; 120
1627 "hheG" "hhuG" "hhiG" "hhaG" "hhEG" "hhG" "hhoG" "" ;; 128
1628 "hWeG" "" "hWiG" "hWaG" "hWEG" "hWG" "" "" ;; 136
1629 "neG" "nuG" "niG" "naG" "nEG" "nG" "noG" "nWaG" ;; 144
1630 "NeG" "NuG" "NiG" "NaG" "NEG" "NG" "NoG" "NWaG" ;; 152
1631 "eG" "uG" "iG" "AG" "EG" "IG" "oG" "eaG" ;; 160
1632 "keG" "kuG" "kiG" "kaG" "kEG" "kG" "koG" "" ;; 168
1633 "kWeG" "" "kWiG" "kWaG" "kWEG" "kWG" "" "" ;; 176
1634 "KeG" "KuG" "KiG" "KaG" "KEG" "KG" "KoG" "" ;; 184
1635 "KWeG" "" "KWiG" "KWaG" "KWEG" "KWG" "" "" ;; 192
1636 "weG" "wuG" "wiG" "waG" "wEG" "wG" "woG" "" ;; 200
1637 "eeG" "uuG" "iiG" "aaG" "EEG" "IIG" "ooG" "" ;; 208
1638 "zeG" "zuG" "ziG" "zaG" "zEG" "zG" "zoG" "zWaG" ;; 216
1639 "ZeG" "ZuG" "ZiG" "ZaG" "ZEG" "ZG" "ZoG" "ZWaG" ;; 224
1640 "yeG" "yuG" "yiG" "yaG" "yEG" "yG" "yoG" "yWaG" ;; 232
1641 "deG" "duG" "diG" "daG" "dEG" "dG" "doG" "dWaG" ;; 240
1642 "DeG" "DuG" "DiG" "DaG" "DEG" "DG" "DoG" "DWaG" ;; 248
1643 "jeG" "juG" "jiG" "jaG" "jEG" "jG" "joG" "jWaG" ;; 256
1644 "geG" "guG" "giG" "gaG" "gEG" "gG" "goG" "" ;; 264
1645 "gWeG" "" "gWiG" "gWaG" "gWEG" "gWG" "" "" ;; 272
1646 "GeG" "GuG" "GiG" "GaG" "GEG" "GG" "GoG" "GWaG" ;; 280
1647 "TeG" "TuG" "TiG" "TaG" "TEG" "TG" "ToG" "TWaG" ;; 288
1648 "CeG" "CuG" "CiG" "CaG" "CEG" "CG" "CoG" "CWaG" ;; 296
1649 "PeG" "PuG" "PiG" "PaG" "PEG" "PG" "PoG" "PWaG" ;; 304
1650 "SeG" "SuG" "SiG" "SaG" "SEG" "SG" "SoG" "SWaG" ;; 312
1651 "SSeG" "SSuG" "SSiG" "SSaG" "SSEG" "SSG" "SSoG" "" ;; 320
1652 "feG" "fuG" "fiG" "faG" "fEG" "fG" "foG" "fWaG" ;; 328
1653 "peG" "puG" "piG" "paG" "pEG" "pG" "poG" "pWaG" ;; 336
1654 "mYaG" "rYaG" "fYaG" "" "" "" "" "" ;; 344
1655 "" "spaceG" "periodG" "commaG" ;; 352
1656 "semicolonG" "colonG" "precolonG" "oldqmarkG" ;; 356
1657 "pbreakG" "andG" "huletG" "sostG" "aratG" "amstG" "sadstG" "sabatG" ;; 360
1658 "smntG" "zeteNG" "asrG" "heyaG" "selasaG" "arbaG" "hemsaG" "slsaG" ;; 368
1659 "sebaG" "semanyaG" "zeTanaG" "metoG" "asrxiG" "" "" "" ;; 376
1660 "qqeG" "qquG" "qqiG" "qqaG" "qqEG" "qqG" "qqoG" "" ;; 384
1661 "mWeG" "bWeG" "GWeG" "fWeG" "pWeG" "" "" "" ;; 392
1662 "kkeG" "kkuG" "kkiG" "kkaG" "kkEG" "kkG" "kkoG" "" ;; 400
1663 "mWiG" "bWiG" "GWiG" "fWiG" "pWiG" "" "" "" ;; 408
1664 "XeG" "XuG" "GXiG" "XaG" "XEG" "XG" "XoG" "" ;; 416
1665 "mWEG" "bWEG" "GWEG" "fWEG" "pWEG" "" "" "" ;; 424
1666 "ggeG" "gguG" "ggiG" "ggaG" "ggEG" "ggG" "ggoG" "" ;; 432
1667 "mWG" "bWG" "GWG" "fWG" "pWG" "" "" "" ;; 440
1668 "ornamentG" "flandG" "iflandG" "africaG" ;; 448
1669 "iafricaG" "wWeG" "wWiG" "wWaG" ;; 452
1670 "wWEG" "wWG" "" "slaqG" "dotG" "lquoteG" "rquoteG" "qmarkG" ]) ;; 456
1673 ;; To make tex-to-fidel mapping.
1674 ;; The following code makes
1675 ;; (get 'ethio-tex-command-he 'ethio-fidel-char) ==> ?
\e$(3!!
\e(B
1680 (while (< i (length ethio-fidel-to-tex-map))
1681 (setq str (aref ethio-fidel-to-tex-map i))
1682 (if (not (string= str ""))
1684 (intern (concat "ethio-tex-command-" (aref ethio-fidel-to-tex-map i)))
1686 (ethio-ethiocode-to-char i)))
1690 (defun ethio-fidel-to-tex-buffer nil
1691 "Convert each fidel characters in the current buffer into a fidel-tex command.
1692 Each command is always surrounded by braces."
1694 (let ((buffer-read-only nil))
1696 ;; Isolated gemination marks need special treatement
1697 (goto-char (point-min))
1698 (while (search-forward "
\e$(3%s
\e(B" nil t)
1699 (replace-match "\\geminateG{}" t t))
1701 ;; First, decompose geminations
1702 ;; Here we assume that each composed character consists of
1703 ;; one Ethiopic character and the Ethiopic gemination mark.
1704 (decompose-region (point-min) (point-max))
1706 ;; Special treatment for geminated characters
1707 ;; The geminated character (la'') will be "\geminateG{\la}".
1708 (goto-char (point-min))
1709 (while (search-forward "
\e$(3%s
\e(B" nil t)
1710 (delete-backward-char 1)
1712 (insert "\\geminateG")
1715 ;; Ethiopic characters to TeX macros
1716 (goto-char (point-min))
1717 (while (re-search-forward "\\ce" nil t)
1720 (aref ethio-fidel-to-tex-map
1721 (prog1 (ethio-char-to-ethiocode (preceding-char))
1722 (backward-delete-char 1)))
1724 (goto-char (point-min))
1725 (set-buffer-modified-p nil)))
1728 (defun ethio-tex-to-fidel-buffer nil
1729 "Convert fidel-tex commands in the current buffer into fidel chars."
1731 (let ((buffer-read-only nil)
1734 ;; Special treatment for gemination
1735 ;; "\geminateG{\la}" or "\geminateG{{\la}}" will be "\la
\e$(3%s
\e(B"
1736 ;; "\geminateG{}" remains unchanged.
1737 (goto-char (point-min))
1738 (while (re-search-forward "\\\\geminateG{\\(\\\\[a-zA-Z]+\\)}" nil t)
1739 (replace-match "\\1
\e$(3%s
\e(B"))
1741 ;; TeX macros to Ethiopic characters
1742 (goto-char (point-min))
1743 (while (search-forward "\\" nil t)
1745 (skip-chars-forward "a-zA-Z")
1747 (get (intern (concat "ethio-tex-command-"
1748 (buffer-substring p (point))))
1752 (delete-region (1- p) (point)) ; don't forget the preceding "\"
1753 (if (and (= (preceding-char) ?{)
1754 (= (following-char) ?}))
1756 (backward-delete-char 1)
1760 ;; compose geminated characters
1761 (goto-char (point-min))
1762 (while (re-search-forward "\\ce
\e$(3%s
\e(B" nil 0)
1764 (save-excursion (backward-char 2) (point))
1767 ;; Now it's time to convert isolated gemination marks.
1768 (goto-char (point-min))
1769 (while (search-forward "\\geminateG{}" nil t)
1770 (replace-match "
\e$(3%s
\e(B"))
1772 (goto-char (point-min))
1773 (set-buffer-modified-p nil)))
1780 (defun ethio-fidel-to-java-buffer nil
1781 "Convert Ethiopic characters into the Java escape sequences.
1783 Each escape sequence is of the form \uXXXX, where XXXX is the
1784 character's codepoint (in hex) in Unicode.
1786 If `ethio-java-save-lowercase' is non-nil, use [0-9a-f].
1787 Otherwise, [0-9A-F]."
1790 ;; first, decompose geminations
1791 (decompose-region (point-min) (point-max))
1793 (goto-char (point-min))
1794 (while (re-search-forward "\\ce" nil t)
1795 (setq ucode (+ ?\x1200 (ethio-char-to-ethiocode (preceding-char))))
1796 (if (> ucode ?\x13bc)
1797 (setq ucode (+ ucode 59952)))
1798 (delete-backward-char 1)
1799 (if ethio-java-save-lowercase
1800 (insert (format "\\u%4x" ucode))
1801 (insert (upcase (format "\\u%4x" ucode)))))))
1804 (defun ethio-java-to-fidel-buffer nil
1805 "Convert the Java escape sequences into corresponding Ethiopic characters."
1807 (goto-char (point-min))
1808 (while (re-search-forward "\\\\u\\([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\\)" nil t)
1813 (buffer-substring (match-beginning 1) (match-end 1)))))
1815 ((and (>= ucode ?\x1200) (<= ucode ?\x13bc))
1817 (insert (ethio-ethiocode-to-char (- ucode ?\x1200))))
1818 ((and (>= ucode ?\xfdf1) (<= ucode ?\xfdff))
1820 (insert (ethio-ethiocode-to-char (- ucode 64560))))
1825 (goto-char (point-min))
1826 (while (re-search-forward "\\ce
\e$(3%s
\e(B" nil 0)
1828 (save-excursion (backward-char 2) (point))
1837 (defun ethio-find-file nil
1838 "Transcribe file content into Ethiopic depending on filename suffix."
1841 ((string-match "\\.sera$" (buffer-file-name))
1843 (ethio-sera-to-fidel-buffer nil 'force)
1844 (set-buffer-modified-p nil)))
1846 ((string-match "\\.html$" (buffer-file-name))
1847 (let ((ethio-sera-being-called-by-w3 t))
1849 (ethio-sera-to-fidel-marker 'force)
1850 (goto-char (point-min))
1851 (while (re-search-forward "&[lr]aquote;" nil t)
1852 (if (= (char-after (1+ (match-beginning 0))) ?l)
1853 (replace-match "
\e$(3%v
\e(B")
1854 (replace-match "
\e$(3%w
\e(B")))
1855 (set-buffer-modified-p nil))))
1857 ((string-match "\\.tex$" (buffer-file-name))
1859 (ethio-tex-to-fidel-buffer)
1860 (set-buffer-modified-p nil)))
1862 ((string-match "\\.java$" (buffer-file-name))
1864 (ethio-java-to-fidel-buffer)
1865 (set-buffer-modified-p nil)))
1871 (defun ethio-write-file nil
1872 "Transcribe Ethiopic characters in ASCII depending on the file extension."
1875 ((string-match "\\.sera$" (buffer-file-name))
1877 (ethio-fidel-to-sera-buffer nil 'force)
1878 (goto-char (point-min))
1879 (ethio-record-user-preference)
1880 (set-buffer-modified-p nil)))
1882 ((string-match "\\.html$" (buffer-file-name))
1884 (let ((ethio-sera-being-called-by-w3 t)
1885 (lq (aref ethio-fidel-to-sera-map 461))
1886 (rq (aref ethio-fidel-to-sera-map 462)))
1887 (aset ethio-fidel-to-sera-map 461 "«te;")
1888 (aset ethio-fidel-to-sera-map 462 "»te;")
1889 (ethio-fidel-to-sera-marker 'force)
1890 (goto-char (point-min))
1891 (if (search-forward "<sera>" nil t)
1892 (ethio-record-user-preference))
1893 (aset ethio-fidel-to-sera-map 461 lq)
1894 (aset ethio-fidel-to-sera-map 462 rq)
1895 (set-buffer-modified-p nil))))
1897 ((string-match "\\.tex$" (buffer-file-name))
1899 (ethio-fidel-to-tex-buffer)
1900 (set-buffer-modified-p nil)))
1902 ((string-match "\\.java$" (buffer-file-name))
1904 (ethio-fidel-to-java-buffer)
1905 (set-buffer-modified-p nil)))
1910 (defun ethio-record-user-preference nil
1911 (if (looking-at "\\\\~\\(tir?\\|amh?\\) ")
1912 (goto-char (match-end 0))
1913 (insert (if (ethio-prefer-amharic-p) "\\~amh " "\\~tir ")))
1914 (insert (if ethio-use-colon-for-colon "\\~-: " "\\~`: ")
1915 (if ethio-use-three-dot-question "\\~`| " "\\~`? ")))
1918 ;; Ethiopic word separator vs. ASCII space
1921 (defvar ethio-prefer-ascii-space t)
1922 (make-variable-buffer-local 'ethio-prefer-ascii-space)
1924 (defun ethio-toggle-space nil
1925 "Toggle ASCII space and Ethiopic separator for keyboard input."
1927 (setq ethio-prefer-ascii-space
1928 (not ethio-prefer-ascii-space))
1929 (if (equal current-input-method "ethiopic")
1930 (setq current-input-method-title (quail-title)))
1931 (force-mode-line-update))
1933 (defun ethio-insert-space (arg)
1934 "Insert ASCII spaces or Ethiopic word separators depending on context.
1936 If the current word separator (indicated in mode-line) is the ASCII space,
1937 insert an ASCII space. With ARG, insert that many ASCII spaces.
1939 If the current word separator is the colon-like Ethiopic word
1940 separator and the point is preceded by `an Ethiopic punctuation mark
1941 followed by zero or more ASCII spaces', then insert also an ASCII
1942 space. With ARG, insert that many ASCII spaces.
1944 Otherwise, insert a colon-like Ethiopic word separator. With ARG, insert that
1945 many Ethiopic word separators."
1949 (ethio-prefer-ascii-space
1950 (insert-char 32 arg))
1952 (skip-chars-backward " ")
1953 (memq (preceding-char)
1954 '(?
\e$(3$h
\e(B ?
\e$(3$i
\e(B ?
\e$(3$j
\e(B ?
\e$(3$k
\e(B ?
\e$(3$l
\e(B ?
\e$(3$m
\e(B ?
\e$(3$n
\e(B ?
\e$(3$o
\e(B ?
\e$(3%t
\e(B ?
\e$(3%u
\e(B ?
\e$(3%v
\e(B ?
\e$(3%w
\e(B ?
\e$(3%x
\e(B)))
1955 (insert-char 32 arg))
1957 (insert-char ?
\e$(3$h
\e(B arg))))
1959 (defun ethio-insert-ethio-space (arg)
1960 "Insert the Ethiopic word delimiter (the colon-like character).
1961 With ARG, insert that many delimiters."
1963 (insert-char ?
\e$(3$h
\e(B arg))
1966 ;; Ethiopic punctuation vs. ASCII punctuation
1969 (defvar ethio-prefer-ascii-punctuation nil)
1970 (make-variable-buffer-local 'ethio-prefer-ascii-punctuation)
1972 (defun ethio-toggle-punctuation nil
1973 "Toggle Ethiopic punctuations and ASCII punctuations for keyboard input."
1975 (setq ethio-prefer-ascii-punctuation
1976 (not ethio-prefer-ascii-punctuation))
1977 (let* ((keys '("." ".." "..." "," ",," ";" ";;" ":" "::" ":::" "*" "**"))
1979 (if ethio-prefer-ascii-punctuation
1980 '(?. [".."] ["..."] ?, [",,"] ?\; [";;"] ?: ["::"] [":::"] ?* ["**"])
1981 '(?
\e$(3$i
\e(B ?
\e$(3%u
\e(B ?. ?
\e$(3$j
\e(B ?, ?
\e$(3$k
\e(B ?\; ?
\e$(3$h
\e(B ?
\e$(3$i
\e(B ?: ?* ?
\e$(3$o
\e(B))))
1983 (quail-defrule (car keys) (car puncs) "ethiopic")
1984 (setq keys (cdr keys)
1986 (if (equal current-input-method "ethiopic")
1987 (setq current-input-method-title (quail-title)))
1988 (force-mode-line-update)))
1994 (defun ethio-gemination nil
1995 "Compose the character before the point with the Ethiopic gemination mark.
1996 If the character is already composed, decompose it and remove the gemination
2000 ((eq (char-charset (preceding-char)) 'ethiopic)
2001 (insert "
\e$(3%s
\e(B")
2003 (save-excursion (backward-char 2) (point))
2006 ((eq (char-charset (preceding-char)) 'leading-code-composition)
2008 (save-excursion (backward-char 1) (point))
2010 (delete-backward-char 1))
2015 (provide 'ethio-util)
2017 ;;; arch-tag: c8feb3d6-39bf-4b0a-b6ef-26f03fbc8140
2018 ;;; ethio-util.el ends here