1 ;;; ethio-util.el --- utilities for Ethiopic -*- coding: iso-2022-7bit; -*-
3 ;; Copyright (C) 1997, 1998, 2002
4 ;; Free Software Foundation, Inc.
5 ;; Copyright (C) 1997, 1998, 1999, 2001, 2004, 2005
6 ;; National Institute of Advanced Industrial Science and Technology (AIST)
7 ;; Registration Number H14PRO021
9 ;; Keywords: mule, multilingual, Ethiopic
11 ;; This file is part of GNU Emacs.
13 ;; GNU Emacs is free software; you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation; either version 2, or (at your option)
18 ;; GNU Emacs is distributed in the hope that it will be useful,
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ;; GNU General Public License for more details.
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with GNU Emacs; see the file COPYING. If not, write to the
25 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26 ;; Boston, MA 02110-1301, USA.
28 ;; Author: TAKAHASHI Naoto <ntakahas@m17n.org>
34 ;; Information for exiting Ethiopic environment.
35 (defvar exit-ethiopic-environment-data nil)
38 (defun setup-ethiopic-environment-internal ()
39 (let ((key-bindings '((" " . ethio-insert-space)
40 ([?\S- ] . ethio-insert-ethio-space)
41 ([?\C-'] . ethio-gemination)
43 ;; these old bindings conflict
44 ;; with Emacs' binding policy
46 ;; ([f2] . ethio-toggle-space)
47 ;; ([S-f2] . ethio-replace-space) ; as requested
48 ;; ([f3] . ethio-toggle-punctuation)
49 ;; ([f4] . ethio-sera-to-fidel-buffer)
50 ;; ([S-f4] . ethio-sera-to-fidel-region)
51 ;; ([C-f4] . ethio-sera-to-fidel-mail-or-marker)
52 ;; ([f5] . ethio-fidel-to-sera-buffer)
53 ;; ([S-f5] . ethio-fidel-to-sera-region)
54 ;; ([C-f5] . ethio-fidel-to-sera-mail-or-marker)
55 ;; ([f6] . ethio-modify-vowel)
56 ;; ([f7] . ethio-replace-space)
57 ;; ([f8] . ethio-input-special-character)
59 ;; this is the rewritten bindings
61 ([f3] . ethio-fidel-to-sera-buffer)
62 ([S-f3] . ethio-fidel-to-sera-region)
63 ([C-f3] . ethio-fidel-to-sera-mail-or-marker)
64 ([f4] . ethio-sera-to-fidel-buffer)
65 ([S-f4] . ethio-sera-to-fidel-region)
66 ([C-f4] . ethio-sera-to-fidel-mail-or-marker)
67 ([S-f5] . ethio-toggle-punctuation)
68 ([S-f6] . ethio-modify-vowel)
69 ([S-f7] . ethio-replace-space)
70 ([S-f8] . ethio-input-special-character)
71 ([C-f9] . ethio-toggle-space)
72 ([S-f9] . ethio-replace-space) ; as requested
76 (setq kb (car (car key-bindings)))
77 (setq exit-ethiopic-environment-data
78 (cons (cons kb (global-key-binding kb))
79 exit-ethiopic-environment-data))
80 (global-set-key kb (cdr (car key-bindings)))
81 (setq key-bindings (cdr key-bindings))))
83 (add-hook 'quail-activate-hook 'ethio-select-a-translation)
84 (add-hook 'find-file-hook 'ethio-find-file)
85 (add-hook 'write-file-functions 'ethio-write-file)
86 (add-hook 'after-save-hook 'ethio-find-file))
88 (defun exit-ethiopic-environment ()
89 "Exit Ethiopic language environment."
90 (while exit-ethiopic-environment-data
91 (global-set-key (car (car exit-ethiopic-environment-data))
92 (cdr (car exit-ethiopic-environment-data)))
93 (setq exit-ethiopic-environment-data
94 (cdr exit-ethiopic-environment-data)))
96 (remove-hook 'quail-activate-hook 'ethio-select-a-translation)
97 (remove-hook 'find-file-hook 'ethio-find-file)
98 (remove-hook 'write-file-functions 'ethio-write-file)
99 (remove-hook 'after-save-hook 'ethio-find-file))
102 ;; ETHIOPIC UTILITY FUNCTIONS
105 ;; If the filename ends in ".sera", editing is done in fidel
106 ;; but file I/O is done in SERA.
108 ;; If the filename ends in ".java", editing is done in fidel
109 ;; but file I/O is done in the \uXXXX style, where XXXX is
110 ;; the Unicode codepoint for the Ethiopic character.
112 ;; If the filename ends in ".tex", editing is done in fidel
113 ;; but file I/O is done in EthioTeX format.
115 ;; To automatically convert Ethiopic text to SERA format when sending mail,
116 ;; (add-hook 'mail-send-hook 'ethio-fidel-to-sera-mail)
118 ;; To automatically convert SERA format to Ethiopic when receiving mail,
119 ;; (add-hook 'rmail-show-message-hook 'ethio-sera-to-fidel-mail)
121 ;; To automatically convert Ethiopic text to SERA format when posting news,
122 ;; (add-hook 'news-inews-hook 'ethio-fidel-to-sera-mail)
128 (defvar ethio-primary-language 'tigrigna
129 "*Symbol that defines the primary language in SERA --> FIDEL conversion.
130 The value should be one of: `tigrigna', `amharic' or `english'.")
132 (defvar ethio-secondary-language 'english
133 "*Symbol that defines the secondary language in SERA --> FIDEL conversion.
134 The value should be one of: `tigrigna', `amharic' or `english'.")
136 (defvar ethio-use-colon-for-colon nil
137 "*Non-nil means associate ASCII colon with Ethiopic colon.
138 If nil, associate ASCII colon with Ethiopic word separator, i.e., two
139 vertically stacked dots. All SERA <--> FIDEL converters refer this
142 (defvar ethio-use-three-dot-question nil
143 "*Non-nil means associate ASCII question mark with Ethiopic old style question mark (three vertically stacked dots).
144 If nil, associate ASCII question mark with Ethiopic stylized question
145 mark. All SERA <--> FIDEL converters refer this variable.")
147 (defvar ethio-quote-vowel-always nil
148 "*Non-nil means always put an apostrophe before an isolated vowel (except at word initial) in FIDEL --> SERA conversion.
149 If nil, put an apostrophe only between a sixth-form consonant and an
152 (defvar ethio-W-sixth-always nil
153 "*Non-nil means convert the Wu-form of a 12-form consonant to \"W'\" instead of \"Wu\" in FIDEL --> SERA conversion.")
155 (defvar ethio-numeric-reduction 0
156 "*Degree of reduction in converting Ethiopic digits into Arabic digits.
158 For example, ({10}{9}{100}{80}{7}) is converted into:
159 `10`9`100`80`7 if `ethio-numeric-reduction' is 0,
160 `109100807 if `ethio-numeric-reduction' is 1,
161 `10900807 if `ethio-numeric-reduction' is 2.")
163 (defvar ethio-implicit-period-conversion t
164 "*Non-nil means replacing the Ethiopic dot at the end of an Ethiopic sentence
165 with an Ethiopic full stop.")
167 (defvar ethio-java-save-lowercase nil
168 "*Non-nil means save Ethiopic characters in lowercase hex numbers to Java files.
169 If nil, use uppercases.")
175 (defconst ethio-sera-to-fidel-table
177 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
178 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
181 (?: (if ethio-use-colon-for-colon "
\e$(3$l
\e(B" "
\e$(3$h
\e(B")
182 (32 (if ethio-use-colon-for-colon "
\e$(3$l
\e(B " "
\e$(3$h
\e(B"))
185 (?| (if ethio-use-colon-for-colon "
\e$(3$l
\e(B|" "
\e$(3$h
\e(B|")
186 (?: "
\e$(3$o
\e(B"))))
189 nil nil nil nil nil nil ("" (?' "
\e$(3%s
\e(B"))
191 nil nil nil nil ("
\e$(3$j
\e(B") ("-" (?: "
\e$(3$l
\e(B")) ("
\e$(3%u
\e(B")
192 ;;; / 0 1 2 3 4 5 6 7 8 9
193 nil nil nil nil nil nil nil nil nil nil nil
195 ((if ethio-use-colon-for-colon "
\e$(3$l
\e(B" "
\e$(3$h
\e(B")
196 (32 (if ethio-use-colon-for-colon "
\e$(3$l
\e(B " "
\e$(3$h
\e(B"))
199 (?| (if ethio-use-colon-for-colon "
\e$(3$l
\e(B|" "
\e$(3$h
\e(B|")
202 ("
\e$(3$k
\e(B") ("<" (?< "
\e$(3%v
\e(B")) nil (">" (?> "
\e$(3%w
\e(B"))
204 ((if ethio-use-three-dot-question "
\e$(3$n
\e(B" "
\e$(3%x
\e(B"))
208 ("
\e$(3"f
\e(B" (?2 "
\e$(3#8
\e(B"))
210 ("
\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")
211 (?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")))
213 ("
\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")
214 (?W "
\e$(3$6
\e(B" (?a "
\e$(3$6
\e(B")
215 (?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")))
217 ("
\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")
218 (?W "
\e$(3#d
\e(B" (?a "
\e$(3#d
\e(B")
219 (?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")))
221 ("
\e$(3"g
\e(B" (?2 "
\e$(3#9
\e(B"))
223 ("
\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")
224 (?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"))
225 (?Y "
\e$(3$a
\e(B" (?a "
\e$(3$a
\e(B")))
227 ("
\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")
228 (?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")))
230 ("
\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")
231 (?W "
\e$(3!8
\e(B" (?a "
\e$(3!8
\e(B")
232 (?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")))
234 ("
\e$(3"h
\e(B" (?2 "
\e$(3#:
\e(B"))
236 ("
\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")
237 (?W "
\e$(3#l
\e(B" (?a "
\e$(3#l
\e(B")
238 (?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")))
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#*
\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")))
243 ("
\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")
244 (?W "
\e$(3!0
\e(B" (?a "
\e$(3!0
\e(B")
245 (?e "
\e$(3!.%n
\e(B") (?u "
\e$(3!.%r
\e(B") (?i "
\e$(3!.%o
\e(B") (?E "
\e$(3!.%q
\e(B")))
247 ("
\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")
248 (?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"))
249 (?Y "
\e$(3$_
\e(B" (?a "
\e$(3$_
\e(B")))
251 ("
\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")
252 (?W "
\e$(3"b
\e(B" (?a "
\e$(3"b
\e(B")
253 (?e "
\e$(3"`%n
\e(B") (?u "
\e$(3"`%r
\e(B") (?i "
\e$(3"`%o
\e(B") (?E "
\e$(3"`%q
\e(B")))
255 ("
\e$(3"i
\e(B" (?2 "
\e$(3#;
\e(B"))
257 ("
\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")
258 (?W "
\e$(3$>
\e(B" (?a "
\e$(3$>
\e(B")
259 (?e "
\e$(3$<%n
\e(B") (?u "
\e$(3$<%r
\e(B") (?i "
\e$(3$<%o
\e(B") (?E "
\e$(3$<%q
\e(B")))
261 ("
\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")
262 (?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")))
264 ("
\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")
265 (?W "
\e$(3!P
\e(B" (?a "
\e$(3!P
\e(B")
266 (?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"))
267 (?Y "
\e$(3$`
\e(B" (?a "
\e$(3$`
\e(B")))
269 ("
\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")
270 (?W "
\e$(3$F
\e(B" (?a "
\e$(3$F
\e(B")
271 (?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"))
273 (?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")
274 (?W "
\e$(3$F
\e(B" (?a "
\e$(3$F
\e(B")
275 (?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"))))
277 ("
\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")
278 (?W "
\e$(3$.
\e(B" (?a "
\e$(3$.
\e(B")
279 (?e "
\e$(3$,%n
\e(B") (?u "
\e$(3$,%r
\e(B") (?i "
\e$(3$,%o
\e(B") (?E "
\e$(3$,%q
\e(B")))
281 ("
\e$(3"d
\e(B" (?2 "
\e$(3#6
\e(B"))
283 ("
\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")
284 (?W "
\e$(3"2
\e(B" (?a "
\e$(3"2
\e(B")
285 (?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")))
287 ("
\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"))
289 ("
\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"))
291 ("
\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")
292 (?W "
\e$(3#T
\e(B" (?a "
\e$(3#T
\e(B")
293 (?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")))
295 ("
\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")
296 (?W "
\e$(3#L
\e(B" (?a "
\e$(3#L
\e(B")
297 (?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")))
303 (?? (if ethio-use-three-dot-question "
\e$(3%x
\e(B" "
\e$(3$n
\e(B"))
305 (?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")
306 (?E "
\e$(3#9
\e(B") (?I "
\e$(3#:
\e(B") (?o "
\e$(3#;
\e(B") (?O "
\e$(3#;
\e(B")
308 (?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"))
310 (?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")
311 (?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")))
313 (?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"))
315 (?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")
316 (?W "
\e$(3!H
\e(B" (?a "
\e$(3!H
\e(B")
317 (?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")))
319 (?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")
320 (?W "
\e$(3$F
\e(B" (?a "
\e$(3$F
\e(B")
321 (?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")))
322 (?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")))
324 ("
\e$(3"f
\e(B" (?2 "
\e$(3#8
\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")
\e(B")
327 (?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")))
329 ("
\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")
330 (?W "
\e$(3"B
\e(B" (?a "
\e$(3"B
\e(B")
331 (?e "
\e$(3"@%n
\e(B") (?u "
\e$(3"@%r
\e(B") (?i "
\e$(3"@%o
\e(B") (?E "
\e$(3"@%q
\e(B")))
333 ("
\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")
334 (?W "
\e$(3#\
\e(B" (?a "
\e$(3#\
\e(B")
335 (?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")))
337 ("
\e$(3"c
\e(B" (?2 "
\e$(3#5
\e(B") (?a "
\e$(3"j
\e(B"))
339 ("
\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")
340 (?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"))
341 (?Y "
\e$(3$a
\e(B" (?a "
\e$(3$a
\e(B")))
343 ("
\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")
344 (?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"))
345 (?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")))
347 ("
\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")
348 (?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 (?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")
350 (?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"))))
352 ("
\e$(3"e
\e(B" (?2 "
\e$(3#7
\e(B"))
354 ("
\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")
355 (?W "
\e$(3#l
\e(B" (?a "
\e$(3#l
\e(B")
356 (?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")))
358 ("
\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")
359 (?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"))
360 (?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")))
362 ("
\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")
363 (?W "
\e$(3!0
\e(B" (?a "
\e$(3!0
\e(B")
364 (?e "
\e$(3!.%n
\e(B") (?u "
\e$(3!.%r
\e(B") (?i "
\e$(3!.%o
\e(B") (?E "
\e$(3!.%q
\e(B")))
366 ("
\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")
367 (?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"))
368 (?Y "
\e$(3$_
\e(B" (?a "
\e$(3$_
\e(B")))
370 ("
\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")
371 (?W "
\e$(3"Z
\e(B" (?a "
\e$(3"Z
\e(B")
372 (?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")))
374 ("
\e$(3"i
\e(B" (?2 "
\e$(3#;
\e(B"))
376 ("
\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")
377 (?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")))
379 ("
\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")
380 (?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"))
381 (?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")))
383 ("
\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")
384 (?W "
\e$(3!P
\e(B" (?a "
\e$(3!P
\e(B")
385 (?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"))
386 (?Y "
\e$(3$`
\e(B" (?a "
\e$(3$`
\e(B")))
388 ("
\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")
389 (?W "
\e$(3!X
\e(B" (?a "
\e$(3!X
\e(B")
390 (?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"))
391 (?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")
392 (?W "
\e$(3!H
\e(B" (?a "
\e$(3!H
\e(B")
393 (?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"))))
395 ("
\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")
396 (?W "
\e$(3":
\e(B" (?a "
\e$(3":
\e(B")
397 (?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")))
399 ("
\e$(3"d
\e(B" (?2 "
\e$(3#6
\e(B"))
401 ("
\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")
402 (?W "
\e$(3"2
\e(B" (?a "
\e$(3"2
\e(B")
403 (?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")))
405 ("
\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")
406 (?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")))
408 ("
\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")
409 (?W "
\e$(3!`
\e(B" (?a "
\e$(3!`
\e(B")
410 (?e "
\e$(3!^%n
\e(B") (?u "
\e$(3!^%r
\e(B") (?i "
\e$(3!^%o
\e(B") (?E "
\e$(3!^%q
\e(B")))
412 ("
\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")
413 (?W "
\e$(3#T
\e(B" (?a "
\e$(3#T
\e(B")
414 (?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")))
416 ("
\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")
417 (?W "
\e$(3#D
\e(B" (?a "
\e$(3#D
\e(B")
418 (?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")))
423 ;; To avoid byte-compiler warnings. It should never be set globally.
424 (defvar ethio-sera-being-called-by-w3)
425 ;; This variable will be bound by some third-party package.
426 (defvar sera-being-called-by-w3)
429 (defun ethio-sera-to-fidel-region (beg end &optional secondary force)
430 "Convert the characters in region from SERA to FIDEL.
431 The variable `ethio-primary-language' specifies the primary language
432 and `ethio-secondary-language' specifies the secondary.
434 If the 3rd parameter SECONDARY is given and non-nil, assume the region
435 begins begins with the secondary language; otherwise with the primary
438 If the 4th parameter FORCE is given and non-nil, perform conversion
439 even if the buffer is read-only.
441 See also the descriptions of the variables
442 `ethio-use-colon-for-colon' and
443 `ethio-use-three-dot-question'."
447 (narrow-to-region beg end)
448 (ethio-sera-to-fidel-buffer secondary force)))
451 (defun ethio-sera-to-fidel-buffer (&optional secondary force)
452 "Convert the current buffer from SERA to FIDEL.
454 The variable `ethio-primary-language' specifies the primary
455 language and `ethio-secondary-language' specifies the secondary.
457 If the 1st optional parameter SECONDARY is non-nil, assume the buffer
458 begins with the secondary language; otherwise with the primary
461 If the 2nd optional parametr FORCE is non-nil, perform conversion even if the
464 See also the descriptions of the variables
465 `ethio-use-colon-for-colon' and
466 `ethio-use-three-dot-question'."
470 (if (and buffer-read-only
472 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
475 (let ((ethio-primary-language ethio-primary-language)
476 (ethio-secondary-language ethio-secondary-language)
477 (ethio-use-colon-for-colon ethio-use-colon-for-colon)
478 (ethio-use-three-dot-question ethio-use-three-dot-question)
479 ;; The above four variables may be changed temporary
480 ;; by tilde escapes during conversion. So we bind them to other
481 ;; variables but of the same names.
482 (buffer-read-only nil)
483 (case-fold-search nil)
487 (setq current-language
489 ethio-secondary-language
490 ethio-primary-language))
492 (goto-char (point-min))
497 ((eq current-language 'english)
498 (ethio-sera-to-fidel-english))
499 ((eq current-language 'amharic)
500 (ethio-sera-to-fidel-ethio 'amharic))
501 ((eq current-language 'tigrigna)
502 (ethio-sera-to-fidel-ethio 'tigrigna))
503 (t ; we don't know what to do
504 (ethio-sera-to-fidel-english))))
506 (setq current-language
509 ;; when language tag is explicitly specified
510 ((not (eq next-language 'toggle))
513 ;; found a toggle in a primary language section
514 ((eq current-language ethio-primary-language)
515 ethio-secondary-language)
517 ;; found a toggle in a secondary, third, fourth, ...
520 ethio-primary-language))))
522 ;; If ethio-implicit-period-conversion is non-nil, the
523 ;; Ethiopic dot "
\e$(3%u
\e(B" at the end of an Ethiopic sentence is
524 ;; replaced with the Ethiopic full stop "
\e$(3$i
\e(B".
525 (if ethio-implicit-period-conversion
527 (goto-char (point-min))
528 (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]\\)"
530 (replace-match "\\1
\e$(3$i
\e(B\\2"))
531 (goto-char (point-min))
532 (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)
533 (replace-match "\\1
\e$(3$i
\e(B"))))
536 (goto-char (point-min))
537 (while (re-search-forward "\\ce
\e$(3%s
\e(B" nil 0)
539 (save-excursion (backward-char 2) (point))
543 (defun ethio-sera-to-fidel-english nil
544 "Handle English section in SERA to FIDEL conversion.
545 Conversion stops when a language switch is found. Then delete that
546 switch and return the name of the new language as a symbol."
547 (let ((new-language nil))
549 (while (and (not (eobp)) (null new-language))
552 ;; if no more "\", nothing to do.
553 ((not (search-forward "\\" nil 0)))
555 ;; hereafter point is put after a "\".
556 ;; first delete that "\", then check the following chars
558 ;; "\\" : leave the second "\"
560 (delete-backward-char 1)
561 (= (following-char) ?\\ ))
564 ;; "\ " : delete the following " "
565 ((= (following-char) 32)
567 (setq new-language 'toggle))
570 ((setq new-language (ethio-process-language-flag)))
572 ;; just a "\" : not special sequence.
574 (setq new-language 'toggle))))
578 (defun ethio-sera-to-fidel-ethio (lang)
579 "Handle Ethiopic section in SERA to FIDEL conversion.
580 Conversion stops when a language switch is found. Then delete that
581 switch and return the name of the new language as a symbol.
583 The parameter LANG (symbol, either `amharic' or `tigrigna') affects
584 the conversion of \"a\"."
586 (let ((new-language nil)
588 start table table2 ch)
590 (setcar (aref ethio-sera-to-fidel-table ?a)
591 (if (eq lang 'tigrigna) "
\e$(3"f
\e(B" "
\e$(3"c
\e(B"))
593 (while (and (not (eobp)) (null new-language))
594 (setq ch (following-char))
597 ;; skip from "<" to ">" (or from "&" to ";") if in w3-mode
598 ((and (or (= ch ?<) (= ch ?&))
599 (or (and (boundp 'ethio-sera-being-called-by-w3)
600 ethio-sera-being-called-by-w3)
601 (and (boundp 'sera-being-called-by-w3)
602 sera-being-called-by-w3)))
603 (search-forward (if (= ch ?<) ">" ";")
606 ;; leave non-ASCII characters as they are
611 ((looking-at "`[1-9][0-9]*")
613 (ethio-convert-digit))
615 ;; if not seeing a "\", do sera to fidel conversion
619 (setq table (aref ethio-sera-to-fidel-table ch))
620 (while (setq table2 (cdr (assoc (following-char) table)))
623 (if (setq ch (car table))
625 (delete-region start (point))
628 (insert (eval ch))))))
630 ;; if control reaches here, we must be looking at a "\"
634 (if (looking-at "\\\\~! ?")
636 ;; "\~!" or "\~! ". switch to non-verbatim mode
641 ;; "\" but not "\~!" nor "\~! ". skip the current "\".
644 ;; hereafter, non-verbatim mode and looking at a "\"
645 ;; first delete that "\", then check the following chars.
647 ;; "\ " : delete the following " "
650 (setq ch (following-char))
653 (setq new-language 'toggle))
655 ;; "\~!" or "\~! " : switch to verbatim mode
661 ((setq new-language (ethio-process-language-flag)))
663 ;; "\~" but not "\~!" nor a language flag
666 (ethio-tilde-escape))
668 ;; ASCII punctuation escape. skip
669 ((looking-at "\\(,\\|\\.\\|;\\|:\\|'\\|`\\|\?\\|\\\\\\)+")
670 (goto-char (match-end 0)))
672 ;; "\", but not special sequence
674 (setq new-language 'toggle))))
678 (defun ethio-process-language-flag nil
679 "Process a language flag of the form \"~lang\" or \"~lang1~lang2\".
681 If looking at \"~lang1~lang2\", set `ethio-primary-language' and
682 `ethio-une-secondary-language' based on \"lang1\" and \"lang2\".
683 Then delete the language flag \"~lang1~lang2\" from the buffer.
684 Return value is the new primary language.
686 If looking at \"~lang\", delete that language flag \"~lang\" from the
687 buffer and return that language. In this case
688 `ethio-primary-language' and `ethio-uni-secondary-language'
691 If an unsupported language flag is found, just return nil without
699 "~\\([a-z][a-z][a-z]?\\)~\\([a-z][a-z][a-z]?\\)[ \t\n\\]")
701 (ethio-flag-to-language
702 (buffer-substring (match-beginning 1) (match-end 1))))
704 (ethio-flag-to-language
705 (buffer-substring (match-beginning 2) (match-end 2)))))
706 (setq ethio-primary-language lang1
707 ethio-secondary-language lang2)
708 (delete-region (point) (match-end 2))
709 (if (= (following-char) 32)
711 ethio-primary-language)
714 ((and (looking-at "~\\([a-z][a-z][a-z]?\\)[ \t\n\\]")
716 (ethio-flag-to-language
717 (buffer-substring (match-beginning 1) (match-end 1)))))
718 (delete-region (point) (match-end 1))
719 (if (= (following-char) 32)
727 (defun ethio-tilde-escape nil
728 "Handle a SERA tilde escape in Ethiopic section and delete it.
729 Delete the escape even it is not recognized."
731 (let ((p (point)) command)
732 (skip-chars-forward "^ \t\n\\\\")
733 (setq command (buffer-substring p (point)))
734 (delete-region p (point))
735 (if (= (following-char) 32)
741 ((string= command "-:")
742 (setq ethio-use-colon-for-colon t))
745 ((string= command "`:")
746 (setq ethio-use-colon-for-colon nil))
749 ((string= command "?")
750 (setq ethio-use-three-dot-question nil))
753 ((string= command "`|")
754 (setq ethio-use-three-dot-question t))
757 ((string= command "e")
758 (insert "
\e$(3%j
\e(B"))
761 ((string= command "E")
762 (insert "
\e$(3%k
\e(B"))
765 ((string= command "a")
766 (insert "
\e$(3%l
\e(B"))
769 ((string= command "A")
770 (insert "
\e$(3%m
\e(B"))
773 ((string= command "X")
774 (insert "
\e$(3%i
\e(B"))
776 ;; unsupported tilde escape
780 (defun ethio-flag-to-language (flag)
782 ((or (string= flag "en") (string= flag "eng")) 'english)
783 ((or (string= flag "ti") (string= flag "tir")) 'tigrigna)
784 ((or (string= flag "am") (string= flag "amh")) 'amharic)
787 (defun ethio-convert-digit nil
788 "Convert Arabic digits to Ethiopic digits."
790 (while (and (>= (setq ch (following-char)) ?1)
794 ;; count up following zeros
796 (while (= (following-char) ?0)
802 ;; first digit is 10, 20, ..., or 90
804 (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)))
807 ;; first digit is 2, 3, ..., or 9
809 (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))))
813 (insert "
\e$(3$p
\e(B")))
817 (insert "
\e$(3%$
\e(B"))
820 (insert-char ?
\e$(3%%
\e(B (/ z 4)))))
823 (defun ethio-sera-to-fidel-mail-or-marker (&optional arg)
824 "Execute ethio-sera-to-fidel-mail or ethio-sera-to-fidel-marker depending on the current major mode.
825 If in rmail-mode or in mail-mode, execute the former; otherwise latter."
828 (if (or (eq major-mode 'rmail-mode)
829 (eq major-mode 'mail-mode))
830 (ethio-sera-to-fidel-mail (prefix-numeric-value arg))
831 (ethio-sera-to-fidel-marker arg)))
834 (defun ethio-sera-to-fidel-mail (&optional arg)
835 "Convert SERA to FIDEL to read/write mail and news.
837 If the buffer contains the markers \"<sera>\" and \"</sera>\",
838 convert the segments between them into FIDEL.
840 If invoked interactively and there is no marker, convert the subject field
841 and the body into FIDEL using `ethio-sera-to-fidel-region'."
844 (let ((buffer-read-only nil)
848 ;; follow RFC822 rules instead of looking for a fixed separator
851 (setq border (point))
853 ;; note that the point is placed at the border
854 (if (or (re-search-forward "^<sera>$" nil t)
856 (goto-char (point-min))
857 (re-search-forward "^Subject: <sera>" border t)))
861 ;; we start with the body so that the border will not change
862 ;; use "^<sera>\n" instead of "^<sera>$" not to leave a blank line
864 (while (re-search-forward "^<sera>\n" nil t)
866 (ethio-sera-to-fidel-region
869 (if (re-search-forward "^</sera>\n" nil 0)
872 ;; now process the subject
873 (goto-char (point-min))
874 (if (re-search-forward "^Subject: <sera>" border t)
875 (ethio-sera-to-fidel-region
876 (progn (delete-backward-char 6) (point))
878 (if (re-search-forward "</sera>$" (line-end-position) 0)
882 ;; in case there are no marks but invoked interactively
885 (ethio-sera-to-fidel-region border (point-max))
886 (goto-char (point-min))
887 (if (re-search-forward "^Subject: " border t)
888 (ethio-sera-to-fidel-region (point) (line-end-position))))))
890 ;; adjust the rmail marker
891 (if (eq major-mode 'rmail-mode)
893 (aref rmail-message-vector (1+ rmail-current-message))
897 (defun ethio-sera-to-fidel-marker (&optional force)
898 "Convert the regions surrounded by \"<sera>\" and \"</sera>\" from SERA to FIDEL.
899 Assume that each region begins with `ethio-primary-language'.
900 The markers \"<sera>\" and \"</sera>\" themselves are not deleted."
902 (if (and buffer-read-only
904 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
907 (goto-char (point-min))
908 (while (re-search-forward "<sera>" nil t)
909 (ethio-sera-to-fidel-region
911 (if (re-search-forward "</sera>" nil t)
921 (defconst ethio-fidel-to-sera-map
922 [ "he" "hu" "hi" "ha" "hE" "h" "ho" "" ;; 0 - 7
923 "le" "lu" "li" "la" "lE" "l" "lo" "lWa" ;; 8
924 "He" "Hu" "Hi" "Ha" "HE" "H" "Ho" "HWa" ;; 16
925 "me" "mu" "mi" "ma" "mE" "m" "mo" "mWa" ;; 24
926 "`se" "`su" "`si" "`sa" "`sE" "`s" "`so" "`sWa" ;; 32
927 "re" "ru" "ri" "ra" "rE" "r" "ro" "rWa" ;; 40
928 "se" "su" "si" "sa" "sE" "s" "so" "sWa" ;; 48
929 "xe" "xu" "xi" "xa" "xE" "x" "xo" "xWa" ;; 56
930 "qe" "qu" "qi" "qa" "qE" "q" "qo" "" ;; 64
931 "qWe" "" "qWi" "qWa" "qWE" "qW'" "" "" ;; 72
932 "Qe" "Qu" "Qi" "Qa" "QE" "Q" "Qo" "" ;; 80
933 "QWe" "" "QWi" "QWa" "QWE" "QW'" "" "" ;; 88
934 "be" "bu" "bi" "ba" "bE" "b" "bo" "bWa" ;; 96
935 "ve" "vu" "vi" "va" "vE" "v" "vo" "vWa" ;; 104
936 "te" "tu" "ti" "ta" "tE" "t" "to" "tWa" ;; 112
937 "ce" "cu" "ci" "ca" "cE" "c" "co" "cWa" ;; 120
938 "`he" "`hu" "`hi" "`ha" "`hE" "`h" "`ho" "" ;; 128
939 "hWe" "" "hWi" "hWa" "hWE" "hW'" "" "" ;; 136
940 "ne" "nu" "ni" "na" "nE" "n" "no" "nWa" ;; 144
941 "Ne" "Nu" "Ni" "Na" "NE" "N" "No" "NWa" ;; 152
942 "e" "u" "i" "A" "E" "I" "o" "ea" ;; 160
943 "ke" "ku" "ki" "ka" "kE" "k" "ko" "" ;; 168
944 "kWe" "" "kWi" "kWa" "kWE" "kW'" "" "" ;; 176
945 "Ke" "Ku" "Ki" "Ka" "KE" "K" "Ko" "" ;; 184
946 "KWe" "" "KWi" "KWa" "KWE" "KW'" "" "" ;; 192
947 "we" "wu" "wi" "wa" "wE" "w" "wo" "" ;; 200
948 "`e" "`u" "`i" "`a" "`E" "`I" "`o" "" ;; 208
949 "ze" "zu" "zi" "za" "zE" "z" "zo" "zWa" ;; 216
950 "Ze" "Zu" "Zi" "Za" "ZE" "Z" "Zo" "ZWa" ;; 224
951 "ye" "yu" "yi" "ya" "yE" "y" "yo" "yWa" ;; 232
952 "de" "du" "di" "da" "dE" "d" "do" "dWa" ;; 240
953 "De" "Du" "Di" "Da" "DE" "D" "Do" "DWa" ;; 248
954 "je" "ju" "ji" "ja" "jE" "j" "jo" "jWa" ;; 256
955 "ge" "gu" "gi" "ga" "gE" "g" "go" "" ;; 264
956 "gWe" "" "gWi" "gWa" "gWE" "gW'" "" "" ;; 272
957 "Ge" "Gu" "Gi" "Ga" "GE" "G" "Go" "GWa" ;; 280
958 "Te" "Tu" "Ti" "Ta" "TE" "T" "To" "TWa" ;; 288
959 "Ce" "Cu" "Ci" "Ca" "CE" "C" "Co" "CWa" ;; 296
960 "Pe" "Pu" "Pi" "Pa" "PE" "P" "Po" "PWa" ;; 304
961 "Se" "Su" "Si" "Sa" "SE" "S" "So" "SWa" ;; 312
962 "`Se" "`Su" "`Si" "`Sa" "`SE" "`S" "`So" "" ;; 320
963 "fe" "fu" "fi" "fa" "fE" "f" "fo" "fWa" ;; 328
964 "pe" "pu" "pi" "pa" "pE" "p" "po" "pWa" ;; 336
965 "mYa" "rYa" "fYa" "" "" "" "" "" ;; 344
966 " " " : " "::" "," ";" "-:" ":-" "`?" ;; 352
967 ":|:" "1" "2" "3" "4" "5" "6" "7" ;; 360
968 "8" "9" "10" "20" "30" "40" "50" "60" ;; 368
969 "70" "80" "90" "100" "10000" "" "" "" ;; 376
970 "`qe" "`qu" "`qi" "`qa" "`qE" "`q" "`qo" "" ;; 384
971 "mWe" "bWe" "GWe" "fWe" "pWe" "" "" "" ;; 392
972 "`ke" "`ku" "`ki" "`ka" "`kE" "`k" "`ko" "" ;; 400
973 "mWi" "bWi" "GWi" "fWi" "pWi" "" "" "" ;; 408
974 "Xe" "Xu" "Xi" "Xa" "XE" "X" "Xo" "" ;; 416
975 "mWE" "bWE" "GWE" "fWE" "pWE" "" "" "" ;; 424
976 "`ge" "`gu" "`gi" "`ga" "`gE" "`g" "`go" "" ;; 432
977 "mW'" "bW'" "GW'" "fW'" "pW'" "" "" "" ;; 440
978 "\\~X " "\\~e " "\\~E " "\\~a " "\\~A " "wWe" "wWi" "wWa" ;; 448
979 "wWE" "wW'" "''" "`!" "." "<<" ">>" "?" ]) ;; 456
981 (defun ethio-prefer-amharic-p nil
982 (or (eq ethio-primary-language 'amharic)
983 (and (not (eq ethio-primary-language 'tigrigna))
984 (eq ethio-secondary-language 'amharic))))
986 (defun ethio-language-to-flag (lang)
988 ((eq lang 'english) "eng")
989 ((eq lang 'tigrigna) "tir")
990 ((eq lang 'amharic) "amh")
994 (defun ethio-fidel-to-sera-region (begin end &optional secondary force)
995 "Replace all the FIDEL characters in the region to the SERA format.
996 The variable `ethio-primary-language' specifies the primary
997 language and `ethio-secondary-language' specifies the secondary.
999 If the 3dr parameter SECONDARY is given and non-nil, try to convert
1000 the region so that it begins in the secondary language; otherwise with
1001 the primary language.
1003 If the 4th parameter FORCE is given and non-nil, convert even if the
1004 buffer is read-only.
1006 See also the descriptions of the variables
1007 `ethio-use-colon-for-colon', `ethio-use-three-dot-question',
1008 `ethio-quote-vowel-always' and `ethio-numeric-reduction'."
1010 (interactive "r\nP")
1012 (narrow-to-region begin end)
1013 (ethio-fidel-to-sera-buffer secondary force)))
1016 (defun ethio-fidel-to-sera-buffer (&optional secondary force)
1017 "Replace all the FIDEL characters in the current buffer to the SERA format.
1018 The variable `ethio-primary-language' specifies the primary
1019 language and `ethio-secondary-language' specifies the secondary.
1021 If the 1st optional parameter SECONDARY is non-nil, try to convert the
1022 region so that it begins in the secondary language; otherwise with the
1025 If the 2nd optional parameter FORCE is non-nil, convert even if the
1026 buffer is read-only.
1028 See also the descriptions of the variables
1029 `ethio-use-colon-for-colon', `ethio-use-three-dot-question',
1030 `ethio-quote-vowel-always' and `ethio-numeric-reduction'."
1033 (if (and buffer-read-only
1035 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
1038 (let ((buffer-read-only nil)
1039 (case-fold-search nil)
1040 (lonec nil) ;; t means previous char was a lone consonant
1041 (fidel nil) ;; t means previous char was a FIDEL
1042 (digit nil) ;; t means previous char was an Ethiopic digit
1043 (flag (if (ethio-prefer-amharic-p) "\\~amh " "\\~tir "))
1046 ;; user's preference in transcription
1047 (if ethio-use-colon-for-colon
1049 (aset ethio-fidel-to-sera-map 353 "`:")
1050 (aset ethio-fidel-to-sera-map 357 ":"))
1051 (aset ethio-fidel-to-sera-map 353 " : ")
1052 (aset ethio-fidel-to-sera-map 357 "-:"))
1054 (if ethio-use-three-dot-question
1056 (aset ethio-fidel-to-sera-map 359 "?")
1057 (aset ethio-fidel-to-sera-map 463 "`?"))
1058 (aset ethio-fidel-to-sera-map 359 "`?")
1059 (aset ethio-fidel-to-sera-map 463 "?"))
1063 (aset (aref ethio-fidel-to-sera-map x)
1065 (if ethio-W-sixth-always ?' ?u)))
1066 '(77 93 141 181 197 277 440 441 442 443 444 457))
1068 (if (ethio-prefer-amharic-p)
1069 (aset ethio-fidel-to-sera-map 160 "a")
1070 (aset ethio-fidel-to-sera-map 160 "e"))
1071 ;; end of user's preference
1073 ;; first, decompose geminated characters
1074 (decompose-region (point-min) (point-max))
1076 ;; main conversion routine
1077 (goto-char (point-min))
1079 (setq ch (following-char))
1081 (cond ; ethiopic, english, neutral
1083 ;; ethiopic character. must go to ethiopic mode, if not in it.
1084 ((eq (char-charset ch) 'ethiopic)
1085 (setq ch (ethio-char-to-ethiocode ch))
1087 (if (not (eq mode 'ethiopic))
1090 (setq mode 'ethiopic)))
1092 (cond ; fidel, punc, digit
1095 ((or (<= ch 346) ; he - fYa
1096 (and (>= ch 384) (<= ch 444)) ; `qe - pw
1097 (and (>= ch 453) (<= ch 457))) ; wWe - wW
1098 (if (and (memq ch '(160 161 162 163 164 166 167)) ; (e - ea)
1100 (and ethio-quote-vowel-always
1103 (insert (aref ethio-fidel-to-sera-map ch))
1104 (setq lonec (ethio-lone-consonant-p ch)
1108 ;; punctuations or icons
1109 ((or (and (>= ch 353) (<= ch 360)) ; : - :|:
1110 (>= ch 458) ; '' - ?
1111 (and (>= ch 448) (<= ch 452))) ; \~X \~e \~E \~a \~A
1112 (insert (aref ethio-fidel-to-sera-map ch))
1117 ;; now CH must be an ethiopic digit
1119 ;; reduction = 0 or not preceded by Ethiopic number(s)
1120 ((or (= ethio-numeric-reduction 0)
1122 (insert "`" (aref ethio-fidel-to-sera-map ch))
1127 ;; reduction = 2 and following 10s, 100s, 10000s
1128 ((and (= ethio-numeric-reduction 2)
1129 (memq ch '(370 379 380)))
1130 (insert (substring (aref ethio-fidel-to-sera-map ch) 1))
1135 ;; ordinary following digits
1137 (insert (aref ethio-fidel-to-sera-map ch))
1142 ;; english character. must go to english mode, if not in it.
1143 ((or (and (>= ch ?a) (<= ch ?z))
1144 (and (>= ch ?A) (<= ch ?Z)))
1145 (if (not (eq mode 'english))
1153 ;; ch can appear both in ethiopic section and in english section.
1156 ;; we must decide the mode, if not decided yet
1161 ethio-secondary-language
1162 ethio-primary-language))
1163 (if (eq mode 'english)
1166 (setq mode 'ethiopic)))) ; tigrigna & amharic --> ethiopic
1168 (cond ; \ , eng-mode , punc , w3 , other
1170 ;; backslash is always quoted
1175 ;; nothing to do if in english mode
1179 ;; now we must be in ethiopic mode and seeing a non-"\"
1181 ;; ascii punctuations in ethiopic mode
1182 ((looking-at "[,.;:'`?]+")
1184 (goto-char (1+ (match-end 0)))) ; because we inserted one byte (\)
1186 ;; skip from "<" to ">" (or from "&" to ";") if called from w3
1187 ((and (or (= ch ?<) (= ch ?&))
1188 (or (and (boundp 'ethio-sera-being-called-by-w3)
1189 ethio-sera-being-called-by-w3)
1190 (and (boundp 'sera-being-called-by-w3)
1191 sera-being-called-by-w3)))
1192 (search-forward (if (= ch ?<) ">" ";")
1195 ;; neutral character. no need to quote. just skip it.
1202 ;; end of main conversion routine
1205 (defun ethio-lone-consonant-p (ethiocode)
1206 "If ETHIOCODE is an Ethiopic lone consonant, return t."
1207 (or (and (< ethiocode 344) (= (% ethiocode 8) 5))
1209 ;; `q `k X `g mW bW GW fW pW wW
1210 (memq ethiocode '(389 405 421 437 440 441 442 443 444 457))))
1213 (defun ethio-fidel-to-sera-mail-or-marker (&optional arg)
1214 "Execute ethio-fidel-to-sera-mail or ethio-fidel-to-sera-marker depending on the current major mode.
1215 If in rmail-mode or in mail-mode, execute the former; otherwise latter."
1218 (if (or (eq major-mode 'rmail-mode)
1219 (eq major-mode 'mail-mode))
1220 (ethio-fidel-to-sera-mail)
1221 (ethio-fidel-to-sera-marker arg)))
1224 (defun ethio-fidel-to-sera-mail nil
1225 "Convert FIDEL to SERA to read/write mail and news.
1227 If the body contains at least one Ethiopic character,
1228 1) insert the string \"<sera>\" at the beginning of the body,
1229 2) insert \"</sera>\" at the end of the body, and
1230 3) convert the body into SERA.
1232 The very same procedure applies to the subject field, too."
1235 (let ((buffer-read-only nil)
1239 ;; follow RFC822 rules instead of looking for a fixed separator
1242 (setq border (point))
1244 ;; process body first not to change the border
1245 ;; note that the point is already at the border
1246 (if (re-search-forward "\\ce" nil t)
1248 (ethio-fidel-to-sera-region border (point-max))
1251 (goto-char (point-max))
1252 (insert "</sera>")))
1255 (goto-char (point-min))
1256 (if (re-search-forward "^Subject: " border t)
1258 (end (line-end-position)))
1259 (if (re-search-forward "\\ce" end t)
1261 (ethio-fidel-to-sera-region beg end)
1265 (insert "</sera>")))))
1267 ;; adjust the rmail marker
1268 (if (eq major-mode 'rmail-mode)
1270 (aref rmail-message-vector (1+ rmail-current-message))
1274 (defun ethio-fidel-to-sera-marker (&optional force)
1275 "Convert the regions surrounded by \"<sera>\" and \"</sera>\" from FIDEL to SERA.
1276 The markers \"<sera>\" and \"</sera>\" themselves are not deleted."
1279 (if (and buffer-read-only
1281 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
1284 (goto-char (point-min))
1285 (while (re-search-forward "<sera>" nil t)
1286 (ethio-fidel-to-sera-region
1288 (if (re-search-forward "</sera>" nil t)
1295 ;; vowel modification
1299 (defun ethio-modify-vowel nil
1300 "Modify the vowel of the FIDEL that is under the cursor."
1302 (let ((ch (following-char))
1303 (composite nil) ; geminated or not
1304 newch base vowel modulo)
1307 ;; in case of gemination
1308 ((eq (char-charset ch) 'composition)
1309 (setq ch (string-to-char (char-to-string ch))
1311 ;; neither gemination nor fidel
1312 ((not (eq (char-charset ch) 'ethiopic))
1313 (error "Not a valid character")))
1315 ;; set frequently referred character features
1316 (setq ch (ethio-char-to-ethiocode ch)
1320 (if (or (and (>= ch 344) (<= ch 380)) ;; mYa - `10000
1321 (and (>= ch 448) (<= ch 452)) ;; \~X - \~A
1322 (>= ch 458)) ;; private punctuations
1323 (error "Not a valid character"))
1329 ;; first standalone vowels
1331 (if (ethio-prefer-amharic-p)
1332 (message "Modify vowel to: [auiAEIoW\"] ")
1333 (message "Modify vowel to: [euiAEIoW\"] "))
1334 (setq vowel (read-char))
1344 ((= vowel ?a) (if (ethio-prefer-amharic-p) 160 163))
1345 ((= vowel ?\") (setq composite t) ch)
1348 ;; second standalone vowels
1350 (message "Modify vowel to: [euiaEIo\"] ")
1351 (setq vowel (read-char))
1360 ((= vowel ?\") (setq composite t) ch)
1363 ;; 12-form consonants, *W* form
1364 ((memq base '(72 88 136 176 192 272)) ; qW QW hW kW KW gW
1365 (message "Modify vowel to: [euiaE'\"] ")
1366 (setq vowel (read-char))
1369 ((= vowel ?u) (+ base 5))
1370 ((= vowel ?i) (+ base 2))
1371 ((= vowel ?a) (+ base 3))
1372 ((= vowel ?E) (+ base 4))
1373 ((= vowel ?') (+ base 5))
1374 ((= vowel ?\") (setq composite t) ch)
1377 ;; extended 12-form consonants, mWa bWa GWa fWa pWa
1379 (message "Modify vowel to: [euiaE'\"] ")
1380 (setq vowel (read-char))
1388 ((= vowel ?\") (setq composite t) ch)
1391 (message "Modify vowel to: [euiaE'\"] ")
1392 (setq vowel (read-char))
1400 ((= vowel ?\") (setq composite t) ch)
1403 (message "Modify vowel to: [euiaE'\"] ")
1404 (setq vowel (read-char))
1412 ((= vowel ?\") (setq composite t) ch)
1415 (message "Modify vowel to: [euiaE'\"] ")
1416 (setq vowel (read-char))
1424 ((= vowel ?\") (setq composite t) ch)
1427 (message "Modify vowel to: [euiaE'\"] ")
1428 (setq vowel (read-char))
1436 ((= vowel ?\") (setq composite t) ch)
1439 ;; extended 12-form consonatns, mW* bW* GW* fW* pW*
1440 ((memq base '(392 408 424 440)) ; *We *Wi *WE *W
1441 (message "Modify vowel to: [eiEau'\"] ")
1442 (setq vowel (read-char))
1444 ((= vowel ?e) (+ 392 modulo))
1445 ((= vowel ?i) (+ 408 modulo))
1446 ((= vowel ?E) (+ 424 modulo))
1448 ((= modulo 0) 31) ; mWa
1449 ((= modulo 1) 103) ; bWa
1450 ((= modulo 2) 287) ; GWa
1451 ((= modulo 3) 335) ; fWa
1452 ((= modulo 4) 343) ; pWa
1453 (t nil))) ; never reach here
1454 ((= vowel ?') (+ 440 modulo))
1455 ((= vowel ?u) (+ 440 modulo))
1456 ((= vowel ?\") (setq composite t) ch)
1459 ((and (>= ch 453) (<= ch 457)) ; wWe wWi wWa wWE wW
1460 (message "Modify vowel to: [eiaE'u\"] ")
1461 (setq vowel (read-char))
1469 ((= vowel ?\") (setq composite t) ch)
1472 ;; 7-form consonants, or
1473 ;; first 7 of 8-form consonants
1475 (message "Modify vowel to: [euiaE'o\"] ")
1476 (setq vowel (read-char))
1479 ((= vowel ?u) (+ base 1))
1480 ((= vowel ?i) (+ base 2))
1481 ((= vowel ?a) (+ base 3))
1482 ((= vowel ?E) (+ base 4))
1483 ((= vowel ?') (+ base 5))
1484 ((= vowel ?o) (+ base 6))
1485 ((= vowel ?\") (setq composite t) ch)
1494 ;; could not get new character
1496 (error "Invalid vowel"))
1498 ;; vowel changed on a composite Fidel
1503 (concat (char-to-string (ethio-ethiocode-to-char newch)) "
\e$(3%s
\e(B"))))
1505 ;; simple vowel modification
1508 (insert (ethio-ethiocode-to-char newch))))))
1510 (defun ethio-ethiocode-to-char (ethiocode)
1513 (+ (/ ethiocode 94) 33)
1514 (+ (mod ethiocode 94) 33)))
1516 (defun ethio-char-to-ethiocode (ch)
1517 (and (eq (char-charset ch) 'ethiopic)
1518 (let ((char-components (split-char ch)))
1519 (+ (* (- (nth 1 char-components) 33) 94)
1520 (- (nth 2 char-components) 33)))))
1523 ;; space replacement
1527 (defun ethio-replace-space (ch begin end)
1528 "Replace ASCII spaces with Ethiopic word separators in the region.
1530 In the specified region, replace word separators surrounded by two
1531 Ethiopic characters, depending on the first parameter CH, which should
1534 If CH = 1, word separator will be replaced with an ASCII space.
1535 If CH = 2, with two ASCII spaces.
1536 If CH = 3, with the Ethiopic colon-like word separator.
1538 The second and third parameters BEGIN and END specify the region."
1540 (interactive "*cReplace spaces to: 1 (sg col), 2 (dbl col), 3 (Ethiopic)\nr")
1541 (if (not (memq ch '(?1 ?2 ?3)))
1545 (narrow-to-region begin end)
1549 ;; an Ethiopic word separator --> an ASCII space
1550 (goto-char (point-min))
1551 (while (search-forward "
\e$(3$h
\e(B" nil t)
1552 (replace-match " " nil t))
1554 ;; two ASCII spaces between Ethiopic characters --> an ASCII space
1555 (goto-char (point-min))
1556 (while (re-search-forward "\\(\\ce\\) \\(\\ce\\)" nil t)
1557 (replace-match "\\1 \\2")
1558 (goto-char (match-beginning 2))))
1561 ;; An Ethiopic word separator --> two ASCII spaces
1562 (goto-char (point-min))
1563 (while (search-forward "
\e$(3$h
\e(B" nil t)
1564 (replace-match " "))
1566 ;; An ASCII space between Ethiopic characters --> two ASCII spaces
1567 (goto-char (point-min))
1568 (while (re-search-forward "\\(\\ce\\) \\(\\ce\\)" nil t)
1569 (replace-match "\\1 \\2")
1570 (goto-char (match-beginning 2))))
1573 ;; One or two ASCII spaces between Ethiopic characters
1574 ;; --> An Ethiopic word separator
1575 (goto-char (point-min))
1576 (while (re-search-forward "\\(\\ce\\) ?\\(\\ce\\)" nil t)
1577 (replace-match "\\1
\e$(3$h
\e(B\\2")
1578 (goto-char (match-beginning 2)))
1580 ;; Three or more ASCII spaces between Ethiopic characters
1581 ;; --> An Ethiopic word separator + (N - 2) ASCII spaces
1582 (goto-char (point-min))
1583 (while (re-search-forward "\\(\\ce\\) \\( *\\ce\\)" nil t)
1584 (replace-match "\\1
\e$(3$h
\e(B\\2")
1585 (goto-char (match-beginning 2))))))))
1592 (defun ethio-input-special-character (arg)
1593 "Allow the user to input special characters."
1594 (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")
1597 (insert "
\e$(3%j
\e(B"))
1599 (insert "
\e$(3%k
\e(B"))
1601 (insert "
\e$(3%l
\e(B"))
1603 (insert "
\e$(3%m
\e(B"))
1605 (insert "
\e$(3%i
\e(B"))
1613 (defconst ethio-fidel-to-tex-map
1614 [ "heG" "huG" "hiG" "haG" "hEG" "hG" "hoG" "" ;; 0 - 7
1615 "leG" "luG" "liG" "laG" "lEG" "lG" "loG" "lWaG" ;; 8
1616 "HeG" "HuG" "HiG" "HaG" "HEG" "HG" "HoG" "HWaG" ;; 16
1617 "meG" "muG" "miG" "maG" "mEG" "mG" "moG" "mWaG" ;; 24
1618 "sseG" "ssuG" "ssiG" "ssaG" "ssEG" "ssG" "ssoG" "ssWaG" ;; 32
1619 "reG" "ruG" "riG" "raG" "rEG" "rG" "roG" "rWaG" ;; 40
1620 "seG" "suG" "siG" "saG" "sEG" "sG" "soG" "sWaG" ;; 48
1621 "xeG" "xuG" "xiG" "xaG" "xEG" "xG" "xoG" "xWaG" ;; 56
1622 "qeG" "quG" "qiG" "qaG" "qEG" "qG" "qoG" "" ;; 64
1623 "qWeG" "" "qWiG" "qWaG" "qWEG" "qWG" "" "" ;; 72
1624 "QeG" "QuG" "QiG" "QaG" "QEG" "QG" "QoG" "" ;; 80
1625 "QWeG" "" "QWiG" "QWaG" "QWEG" "QWG" "" "" ;; 88
1626 "beG" "buG" "biG" "baG" "bEG" "bG" "boG" "bWaG" ;; 96
1627 "veG" "vuG" "viG" "vaG" "vEG" "vG" "voG" "vWaG" ;; 104
1628 "teG" "tuG" "tiG" "taG" "tEG" "tG" "toG" "tWaG" ;; 112
1629 "ceG" "cuG" "ciG" "caG" "cEG" "cG" "coG" "cWaG" ;; 120
1630 "hheG" "hhuG" "hhiG" "hhaG" "hhEG" "hhG" "hhoG" "" ;; 128
1631 "hWeG" "" "hWiG" "hWaG" "hWEG" "hWG" "" "" ;; 136
1632 "neG" "nuG" "niG" "naG" "nEG" "nG" "noG" "nWaG" ;; 144
1633 "NeG" "NuG" "NiG" "NaG" "NEG" "NG" "NoG" "NWaG" ;; 152
1634 "eG" "uG" "iG" "AG" "EG" "IG" "oG" "eaG" ;; 160
1635 "keG" "kuG" "kiG" "kaG" "kEG" "kG" "koG" "" ;; 168
1636 "kWeG" "" "kWiG" "kWaG" "kWEG" "kWG" "" "" ;; 176
1637 "KeG" "KuG" "KiG" "KaG" "KEG" "KG" "KoG" "" ;; 184
1638 "KWeG" "" "KWiG" "KWaG" "KWEG" "KWG" "" "" ;; 192
1639 "weG" "wuG" "wiG" "waG" "wEG" "wG" "woG" "" ;; 200
1640 "eeG" "uuG" "iiG" "aaG" "EEG" "IIG" "ooG" "" ;; 208
1641 "zeG" "zuG" "ziG" "zaG" "zEG" "zG" "zoG" "zWaG" ;; 216
1642 "ZeG" "ZuG" "ZiG" "ZaG" "ZEG" "ZG" "ZoG" "ZWaG" ;; 224
1643 "yeG" "yuG" "yiG" "yaG" "yEG" "yG" "yoG" "yWaG" ;; 232
1644 "deG" "duG" "diG" "daG" "dEG" "dG" "doG" "dWaG" ;; 240
1645 "DeG" "DuG" "DiG" "DaG" "DEG" "DG" "DoG" "DWaG" ;; 248
1646 "jeG" "juG" "jiG" "jaG" "jEG" "jG" "joG" "jWaG" ;; 256
1647 "geG" "guG" "giG" "gaG" "gEG" "gG" "goG" "" ;; 264
1648 "gWeG" "" "gWiG" "gWaG" "gWEG" "gWG" "" "" ;; 272
1649 "GeG" "GuG" "GiG" "GaG" "GEG" "GG" "GoG" "GWaG" ;; 280
1650 "TeG" "TuG" "TiG" "TaG" "TEG" "TG" "ToG" "TWaG" ;; 288
1651 "CeG" "CuG" "CiG" "CaG" "CEG" "CG" "CoG" "CWaG" ;; 296
1652 "PeG" "PuG" "PiG" "PaG" "PEG" "PG" "PoG" "PWaG" ;; 304
1653 "SeG" "SuG" "SiG" "SaG" "SEG" "SG" "SoG" "SWaG" ;; 312
1654 "SSeG" "SSuG" "SSiG" "SSaG" "SSEG" "SSG" "SSoG" "" ;; 320
1655 "feG" "fuG" "fiG" "faG" "fEG" "fG" "foG" "fWaG" ;; 328
1656 "peG" "puG" "piG" "paG" "pEG" "pG" "poG" "pWaG" ;; 336
1657 "mYaG" "rYaG" "fYaG" "" "" "" "" "" ;; 344
1658 "" "spaceG" "periodG" "commaG" ;; 352
1659 "semicolonG" "colonG" "precolonG" "oldqmarkG" ;; 356
1660 "pbreakG" "andG" "huletG" "sostG" "aratG" "amstG" "sadstG" "sabatG" ;; 360
1661 "smntG" "zeteNG" "asrG" "heyaG" "selasaG" "arbaG" "hemsaG" "slsaG" ;; 368
1662 "sebaG" "semanyaG" "zeTanaG" "metoG" "asrxiG" "" "" "" ;; 376
1663 "qqeG" "qquG" "qqiG" "qqaG" "qqEG" "qqG" "qqoG" "" ;; 384
1664 "mWeG" "bWeG" "GWeG" "fWeG" "pWeG" "" "" "" ;; 392
1665 "kkeG" "kkuG" "kkiG" "kkaG" "kkEG" "kkG" "kkoG" "" ;; 400
1666 "mWiG" "bWiG" "GWiG" "fWiG" "pWiG" "" "" "" ;; 408
1667 "XeG" "XuG" "GXiG" "XaG" "XEG" "XG" "XoG" "" ;; 416
1668 "mWEG" "bWEG" "GWEG" "fWEG" "pWEG" "" "" "" ;; 424
1669 "ggeG" "gguG" "ggiG" "ggaG" "ggEG" "ggG" "ggoG" "" ;; 432
1670 "mWG" "bWG" "GWG" "fWG" "pWG" "" "" "" ;; 440
1671 "ornamentG" "flandG" "iflandG" "africaG" ;; 448
1672 "iafricaG" "wWeG" "wWiG" "wWaG" ;; 452
1673 "wWEG" "wWG" "" "slaqG" "dotG" "lquoteG" "rquoteG" "qmarkG" ]) ;; 456
1676 ;; To make tex-to-fidel mapping.
1677 ;; The following code makes
1678 ;; (get 'ethio-tex-command-he 'ethio-fidel-char) ==> ?
\e$(3!!
\e(B
1683 (while (< i (length ethio-fidel-to-tex-map))
1684 (setq str (aref ethio-fidel-to-tex-map i))
1685 (if (not (string= str ""))
1687 (intern (concat "ethio-tex-command-" (aref ethio-fidel-to-tex-map i)))
1689 (ethio-ethiocode-to-char i)))
1693 (defun ethio-fidel-to-tex-buffer nil
1694 "Convert each fidel characters in the current buffer into a fidel-tex command.
1695 Each command is always surrounded by braces."
1697 (let ((buffer-read-only nil))
1699 ;; Isolated gemination marks need special treatement
1700 (goto-char (point-min))
1701 (while (search-forward "
\e$(3%s
\e(B" nil t)
1702 (replace-match "\\geminateG{}" t t))
1704 ;; First, decompose geminations
1705 ;; Here we assume that each composed character consists of
1706 ;; one Ethiopic character and the Ethiopic gemination mark.
1707 (decompose-region (point-min) (point-max))
1709 ;; Special treatment for geminated characters
1710 ;; The geminated character (la'') will be "\geminateG{\la}".
1711 (goto-char (point-min))
1712 (while (search-forward "
\e$(3%s
\e(B" nil t)
1713 (delete-backward-char 1)
1715 (insert "\\geminateG")
1718 ;; Ethiopic characters to TeX macros
1719 (goto-char (point-min))
1720 (while (re-search-forward "\\ce" nil t)
1723 (aref ethio-fidel-to-tex-map
1724 (prog1 (ethio-char-to-ethiocode (preceding-char))
1725 (backward-delete-char 1)))
1727 (goto-char (point-min))
1728 (set-buffer-modified-p nil)))
1731 (defun ethio-tex-to-fidel-buffer nil
1732 "Convert fidel-tex commands in the current buffer into fidel chars."
1734 (let ((buffer-read-only nil)
1737 ;; Special treatment for gemination
1738 ;; "\geminateG{\la}" or "\geminateG{{\la}}" will be "\la
\e$(3%s
\e(B"
1739 ;; "\geminateG{}" remains unchanged.
1740 (goto-char (point-min))
1741 (while (re-search-forward "\\\\geminateG{\\(\\\\[a-zA-Z]+\\)}" nil t)
1742 (replace-match "\\1
\e$(3%s
\e(B"))
1744 ;; TeX macros to Ethiopic characters
1745 (goto-char (point-min))
1746 (while (search-forward "\\" nil t)
1748 (skip-chars-forward "a-zA-Z")
1750 (get (intern (concat "ethio-tex-command-"
1751 (buffer-substring p (point))))
1755 (delete-region (1- p) (point)) ; don't forget the preceding "\"
1756 (if (and (= (preceding-char) ?{)
1757 (= (following-char) ?}))
1759 (backward-delete-char 1)
1763 ;; compose geminated characters
1764 (goto-char (point-min))
1765 (while (re-search-forward "\\ce
\e$(3%s
\e(B" nil 0)
1767 (save-excursion (backward-char 2) (point))
1770 ;; Now it's time to convert isolated gemination marks.
1771 (goto-char (point-min))
1772 (while (search-forward "\\geminateG{}" nil t)
1773 (replace-match "
\e$(3%s
\e(B"))
1775 (goto-char (point-min))
1776 (set-buffer-modified-p nil)))
1783 (defun ethio-fidel-to-java-buffer nil
1784 "Convert Ethiopic characters into the Java escape sequences.
1786 Each escape sequence is of the form \uXXXX, where XXXX is the
1787 character's codepoint (in hex) in Unicode.
1789 If `ethio-java-save-lowercase' is non-nil, use [0-9a-f].
1790 Otherwise, [0-9A-F]."
1793 ;; first, decompose geminations
1794 (decompose-region (point-min) (point-max))
1796 (goto-char (point-min))
1797 (while (re-search-forward "\\ce" nil t)
1798 (setq ucode (+ ?\x1200 (ethio-char-to-ethiocode (preceding-char))))
1799 (if (> ucode ?\x13bc)
1800 (setq ucode (+ ucode 59952)))
1801 (delete-backward-char 1)
1802 (if ethio-java-save-lowercase
1803 (insert (format "\\u%4x" ucode))
1804 (insert (upcase (format "\\u%4x" ucode)))))))
1807 (defun ethio-java-to-fidel-buffer nil
1808 "Convert the Java escape sequences into corresponding Ethiopic characters."
1810 (goto-char (point-min))
1811 (while (re-search-forward "\\\\u\\([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\\)" nil t)
1816 (buffer-substring (match-beginning 1) (match-end 1)))))
1818 ((and (>= ucode ?\x1200) (<= ucode ?\x13bc))
1820 (insert (ethio-ethiocode-to-char (- ucode ?\x1200))))
1821 ((and (>= ucode ?\xfdf1) (<= ucode ?\xfdff))
1823 (insert (ethio-ethiocode-to-char (- ucode 64560))))
1828 (goto-char (point-min))
1829 (while (re-search-forward "\\ce
\e$(3%s
\e(B" nil 0)
1831 (save-excursion (backward-char 2) (point))
1840 (defun ethio-find-file nil
1841 "Transcribe file content into Ethiopic depending on filename suffix."
1844 ((string-match "\\.sera$" (buffer-file-name))
1846 (ethio-sera-to-fidel-buffer nil 'force)
1847 (set-buffer-modified-p nil)))
1849 ((string-match "\\.html$" (buffer-file-name))
1850 (let ((ethio-sera-being-called-by-w3 t))
1852 (ethio-sera-to-fidel-marker 'force)
1853 (goto-char (point-min))
1854 (while (re-search-forward "&[lr]aquote;" nil t)
1855 (if (= (char-after (1+ (match-beginning 0))) ?l)
1856 (replace-match "
\e$(3%v
\e(B")
1857 (replace-match "
\e$(3%w
\e(B")))
1858 (set-buffer-modified-p nil))))
1860 ((string-match "\\.tex$" (buffer-file-name))
1862 (ethio-tex-to-fidel-buffer)
1863 (set-buffer-modified-p nil)))
1865 ((string-match "\\.java$" (buffer-file-name))
1867 (ethio-java-to-fidel-buffer)
1868 (set-buffer-modified-p nil)))
1874 (defun ethio-write-file nil
1875 "Transcribe Ethiopic characters in ASCII depending on the file extension."
1878 ((string-match "\\.sera$" (buffer-file-name))
1880 (ethio-fidel-to-sera-buffer nil 'force)
1881 (goto-char (point-min))
1882 (ethio-record-user-preference)
1883 (set-buffer-modified-p nil)))
1885 ((string-match "\\.html$" (buffer-file-name))
1887 (let ((ethio-sera-being-called-by-w3 t)
1888 (lq (aref ethio-fidel-to-sera-map 461))
1889 (rq (aref ethio-fidel-to-sera-map 462)))
1890 (aset ethio-fidel-to-sera-map 461 "«te;")
1891 (aset ethio-fidel-to-sera-map 462 "»te;")
1892 (ethio-fidel-to-sera-marker 'force)
1893 (goto-char (point-min))
1894 (if (search-forward "<sera>" nil t)
1895 (ethio-record-user-preference))
1896 (aset ethio-fidel-to-sera-map 461 lq)
1897 (aset ethio-fidel-to-sera-map 462 rq)
1898 (set-buffer-modified-p nil))))
1900 ((string-match "\\.tex$" (buffer-file-name))
1902 (ethio-fidel-to-tex-buffer)
1903 (set-buffer-modified-p nil)))
1905 ((string-match "\\.java$" (buffer-file-name))
1907 (ethio-fidel-to-java-buffer)
1908 (set-buffer-modified-p nil)))
1913 (defun ethio-record-user-preference nil
1914 (if (looking-at "\\\\~\\(tir?\\|amh?\\) ")
1915 (goto-char (match-end 0))
1916 (insert (if (ethio-prefer-amharic-p) "\\~amh " "\\~tir ")))
1917 (insert (if ethio-use-colon-for-colon "\\~-: " "\\~`: ")
1918 (if ethio-use-three-dot-question "\\~`| " "\\~`? ")))
1921 ;; Ethiopic word separator vs. ASCII space
1924 (defvar ethio-prefer-ascii-space t)
1925 (make-variable-buffer-local 'ethio-prefer-ascii-space)
1927 (defun ethio-toggle-space nil
1928 "Toggle ASCII space and Ethiopic separator for keyboard input."
1930 (setq ethio-prefer-ascii-space
1931 (not ethio-prefer-ascii-space))
1932 (if (equal current-input-method "ethiopic")
1933 (setq current-input-method-title (quail-title)))
1934 (force-mode-line-update))
1936 (defun ethio-insert-space (arg)
1937 "Insert ASCII spaces or Ethiopic word separators depending on context.
1939 If the current word separator (indicated in mode-line) is the ASCII space,
1940 insert an ASCII space. With ARG, insert that many ASCII spaces.
1942 If the current word separator is the colon-like Ethiopic word
1943 separator and the point is preceded by `an Ethiopic punctuation mark
1944 followed by zero or more ASCII spaces', then insert also an ASCII
1945 space. With ARG, insert that many ASCII spaces.
1947 Otherwise, insert a colon-like Ethiopic word separator. With ARG, insert that
1948 many Ethiopic word separators."
1952 (ethio-prefer-ascii-space
1953 (insert-char 32 arg))
1955 (skip-chars-backward " ")
1956 (memq (preceding-char)
1957 '(?
\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)))
1958 (insert-char 32 arg))
1960 (insert-char ?
\e$(3$h
\e(B arg))))
1962 (defun ethio-insert-ethio-space (arg)
1963 "Insert the Ethiopic word delimiter (the colon-like character).
1964 With ARG, insert that many delimiters."
1966 (insert-char ?
\e$(3$h
\e(B arg))
1969 ;; Ethiopic punctuation vs. ASCII punctuation
1972 (defvar ethio-prefer-ascii-punctuation nil)
1973 (make-variable-buffer-local 'ethio-prefer-ascii-punctuation)
1975 (defun ethio-toggle-punctuation nil
1976 "Toggle Ethiopic punctuations and ASCII punctuations for keyboard input."
1978 (setq ethio-prefer-ascii-punctuation
1979 (not ethio-prefer-ascii-punctuation))
1980 (let* ((keys '("." ".." "..." "," ",," ";" ";;" ":" "::" ":::" "*" "**"))
1982 (if ethio-prefer-ascii-punctuation
1983 '(?. [".."] ["..."] ?, [",,"] ?\; [";;"] ?: ["::"] [":::"] ?* ["**"])
1984 '(?
\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))))
1986 (quail-defrule (car keys) (car puncs) "ethiopic")
1987 (setq keys (cdr keys)
1989 (if (equal current-input-method "ethiopic")
1990 (setq current-input-method-title (quail-title)))
1991 (force-mode-line-update)))
1997 (defun ethio-gemination nil
1998 "Compose the character before the point with the Ethiopic gemination mark.
1999 If the character is already composed, decompose it and remove the gemination
2003 ((eq (char-charset (preceding-char)) 'ethiopic)
2004 (insert "
\e$(3%s
\e(B")
2006 (save-excursion (backward-char 2) (point))
2009 ((eq (char-charset (preceding-char)) 'leading-code-composition)
2011 (save-excursion (backward-char 1) (point))
2013 (delete-backward-char 1))
2018 (provide 'ethio-util)
2020 ;;; arch-tag: c8feb3d6-39bf-4b0a-b6ef-26f03fbc8140
2021 ;;; ethio-util.el ends here