1 ;;; ethio-util.el --- utilities for Ethiopic
3 ;; Copyright (C) 1997 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@etl.go.jp>
29 ;; Information for exiting Ethiopic environment.
30 (defvar exit-ethiopic-environment-data nil
)
33 (defun setup-ethiopic-environment-internal ()
34 (let ((key-bindings '((" " . ethio-insert-space
)
35 ([?\S-
] . ethio-insert-ethio-space
)
36 ([?\C-
'] . ethio-gemination
)
37 ([f2] . ethio-toggle-space)
38 ([S-f2] . ethio-replace-space) ; as requested
39 ([f3] . ethio-toggle-punctuation)
40 ([f4] . ethio-sera-to-fidel-buffer)
41 ([S-f4] . ethio-sera-to-fidel-region)
42 ([C-f4] . ethio-sera-to-fidel-mail-or-marker)
43 ([f5] . ethio-fidel-to-sera-buffer)
44 ([S-f5] . ethio-fidel-to-sera-region)
45 ([C-f5] . ethio-fidel-to-sera-mail-or-marker)
46 ([f6] . ethio-modify-vowel)
47 ([f7] . ethio-replace-space)
48 ([f8] . ethio-input-special-character)))
51 (setq kb (car (car key-bindings)))
52 (setq exit-ethiopic-environment-data
53 (cons (cons kb (global-key-binding kb))
54 exit-ethiopic-environment-data))
55 (global-set-key kb (cdr (car key-bindings)))
56 (setq key-bindings (cdr key-bindings))))
58 (add-hook 'quail-activate-hook 'ethio-select-a-translation)
59 (add-hook 'find-file-hooks 'ethio-find-file)
60 (add-hook 'write-file-hooks 'ethio-write-file)
61 (add-hook 'after-save-hook 'ethio-find-file))
63 (defun exit-ethiopic-environment ()
64 "Exit Ethiopic language environment"
65 (while exit-ethiopic-environment-data
66 (global-set-key (car (car exit-ethiopic-environment-data))
67 (cdr (car exit-ethiopic-environment-data)))
68 (setq exit-ethiopic-environment-data
69 (cdr exit-ethiopic-environment-data)))
71 (remove-hook 'quail-activate-hook 'ethio-select-a-translation)
72 (remove-hook 'find-file-hooks 'ethio-find-file)
73 (remove-hook 'write-file-hooks 'ethio-write-file)
74 (remove-hook 'after-save-hook 'ethio-find-file))
77 ;; ETHIOPIC UTILITY FUNCTIONS
80 ;; If the filename ends in ".sera", editing is done in fidel
81 ;; but file I/O is done in SERA.
83 ;; If the filename ends in ".java", editing is done in fidel
84 ;; but file I/O is done in the \uXXXX style, where XXXX is
85 ;; the Unicode codepoint for the Ethiopic character.
87 ;; If the filename ends in ".tex", editing is done in fidel
88 ;; but file I/O is done in EthioTeX format.
90 ;; To automatically convert Ethiopic text to SERA format when sending mail,
91 ;; (add-hook 'mail-send-hook 'ethio-fidel-to-sera-mail)
93 ;; To automatically convert SERA format to Ethiopic when receiving mail,
94 ;; (add-hook 'rmail-show-message-hook 'ethio-sera-to-fidel-mail)
96 ;; To automatically convert Ethiopic text to SERA format when posting news,
97 ;; (add-hook 'news-inews-hook 'ethio-fidel-to-sera-mail)
103 (defvar ethio-primary-language 'tigrigna
104 "*Symbol that defines the primary language in SERA --> FIDEL conversion.
105 The value should be one of: `tigrigna', `amharic' or `english'.")
107 (defvar ethio-secondary-language 'english
108 "*Symbol that defines the secondary language in SERA --> FIDEL conversion.
109 The value should be one of: `tigrigna', `amharic' or `english'.")
111 (defvar ethio-use-colon-for-colon nil
112 "*Non-nil means associate ASCII colon with Ethiopic colon.
113 If nil, associate ASCII colon with Ethiopic word separator, i.e., two
114 vertically stacked dots. All SERA <--> FIDEL converters refer this
117 (defvar ethio-use-three-dot-question nil
118 "*Non-nil means associate ASCII question mark with Ethiopic old style question mark (three vertically stacked dots).
119 If nil, associate ASCII question mark with Ethiopic stylised question
120 mark. All SERA <--> FIDEL converters refer this variable.")
122 (defvar ethio-quote-vowel-always nil
123 "*Non-nil means always put an apostrophe before an isolated vowel (except at word initial) in FIDEL --> SERA conversion.
124 If nil, put an apostrophe only between a sixth-form consonant and an
127 (defvar ethio-W-sixth-always nil
128 "*Non-nil means convert the Wu-form of a 12-form consonant to \"W'\" instead of \"Wu\" in FIDEL --> SERA conversion.")
130 (defvar ethio-numeric-reduction 0
131 "*Degree of reduction in converting Ethiopic digits into Arabic digits.
133 For example, ({10}{9}{100}{80}{7}) is converted into:
134 `10`9`100`80`7 if `ethio-numeric-reduction' is 0,
135 `109100807 if `ethio-numeric-reduction' is 1,
136 `10900807 if `ethio-numeric-reduction' is 2.")
138 (defvar ethio-implicit-period-conversion t
139 "*Non-nil means replacing the Ethiopic dot at the end of an Ethiopic sentence
140 with an Ethiopic full stop.")
142 (defvar ethio-java-save-lowercase nil
143 "*Non-nil means save Ethiopic characters in lowercase hex numbers to Java files.
144 If nil, use uppercases.")
150 (defconst ethio-sera-to-fidel-table
152 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
153 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
156 (?: (if ethio-use-colon-for-colon " \e$(3$l\e(B" "\e$(3$h\e(B")
157 (32 (if ethio-use-colon-for-colon " \e$(3$l\e(B " "\e$(3$h\e(B"))
160 (?| (if ethio-use-colon-for-colon " \e$(3$l\e(B|" " \e$(3$h\e(B|")
161 (?: " \e$(3$o\e(B"))))
164 nil nil nil nil nil nil ("" (?' "\e$(3%s\e(B"))
166 nil nil nil nil ("\e$(3$j\e(B") ("-" (?: "\e$(3$l\e(B")) ("\e$(3%u\e(B")
167 ;;; / 0 1 2 3 4 5 6 7 8 9
168 nil nil nil nil nil nil nil nil nil nil nil
170 ((if ethio-use-colon-for-colon "\e$(3$l\e(B" "\e$(3$h\e(B")
171 (32 (if ethio-use-colon-for-colon "\e$(3$l\e(B " "\e$(3$h\e(B"))
174 (?| (if ethio-use-colon-for-colon "\e$(3$l\e(B|" "\e$(3$h\e(B|")
177 ("\e$(3$k\e(B") ("<" (?< "\e$(3%v\e(B")) nil (">" (?> "\e$(3%w\e(B"))
179 ((if ethio-use-three-dot-question "\e$(3$n\e(B" "\e$(3%x\e(B"))
183 ("\e$(3"f\e(B" (?2 "\e$(3#8\e(B"))
185 ("\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")
186 (?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")))
188 ("\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")
189 (?W "\e$(3$6\e(B" (?a "\e$(3$6\e(B")
190 (?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")))
192 ("\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")
193 (?W "\e$(3#d\e(B" (?a "\e$(3#d\e(B")
194 (?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")))
196 ("\e$(3"g\e(B" (?2 "\e$(3#9\e(B"))
198 ("\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")
199 (?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"))
200 (?Y "\e$(3$a\e(B" (?a "\e$(3$a\e(B")))
202 ("\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")
203 (?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")))
205 ("\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")
206 (?W "\e$(3!8\e(B" (?a "\e$(3!8\e(B")
207 (?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")))
209 ("\e$(3"h\e(B" (?2 "\e$(3#:\e(B"))
211 ("\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")
212 (?W "\e$(3#l\e(B" (?a "\e$(3#l\e(B")
213 (?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")))
215 ("\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")
216 (?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")))
218 ("\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")
219 (?W "\e$(3!0\e(B" (?a "\e$(3!0\e(B")
220 (?e "\e$(3!.%n\e(B") (?u "\e$(3!.%r\e(B") (?i "\e$(3!.%o\e(B") (?E "\e$(3!.%q\e(B")))
222 ("\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")
223 (?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"))
224 (?Y "\e$(3$_\e(B" (?a "\e$(3$_\e(B")))
226 ("\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")
227 (?W "\e$(3"b\e(B" (?a "\e$(3"b\e(B")
228 (?e "\e$(3"`%n\e(B") (?u "\e$(3"`%r\e(B") (?i "\e$(3"`%o\e(B") (?E "\e$(3"`%q\e(B")))
230 ("\e$(3"i\e(B" (?2 "\e$(3#;\e(B"))
232 ("\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")
233 (?W "\e$(3$>\e(B" (?a "\e$(3$>\e(B")
234 (?e "\e$(3$<%n\e(B") (?u "\e$(3$<%r\e(B") (?i "\e$(3$<%o\e(B") (?E "\e$(3$<%q\e(B")))
236 ("\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")
237 (?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")))
239 ("\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")
240 (?W "\e$(3!P\e(B" (?a "\e$(3!P\e(B")
241 (?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"))
242 (?Y "\e$(3$`\e(B" (?a "\e$(3$`\e(B")))
244 ("\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")
245 (?W "\e$(3$F\e(B" (?a "\e$(3$F\e(B")
246 (?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"))
248 (?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")
249 (?W "\e$(3$F\e(B" (?a "\e$(3$F\e(B")
250 (?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"))))
252 ("\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")
253 (?W "\e$(3$.\e(B" (?a "\e$(3$.\e(B")
254 (?e "\e$(3$,%n\e(B") (?u "\e$(3$,%r\e(B") (?i "\e$(3$,%o\e(B") (?E "\e$(3$,%q\e(B")))
256 ("\e$(3"d\e(B" (?2 "\e$(3#6\e(B"))
258 ("\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")
259 (?W "\e$(3"2\e(B" (?a "\e$(3"2\e(B")
260 (?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")))
262 ("\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"))
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"))
266 ("\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")
267 (?W "\e$(3#T\e(B" (?a "\e$(3#T\e(B")
268 (?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")))
270 ("\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")
271 (?W "\e$(3#L\e(B" (?a "\e$(3#L\e(B")
272 (?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")))
278 (?? (if ethio-use-three-dot-question "\e$(3%x\e(B" "\e$(3$n\e(B"))
280 (?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")
281 (?E "\e$(3#9\e(B") (?I "\e$(3#:\e(B") (?o "\e$(3#;\e(B") (?O "\e$(3#;\e(B")
283 (?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"))
285 (?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")
286 (?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")))
288 (?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"))
290 (?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")
291 (?W "\e$(3!H\e(B" (?a "\e$(3!H\e(B")
292 (?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")))
294 (?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")
295 (?W "\e$(3$F\e(B" (?a "\e$(3$F\e(B")
296 (?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")))
297 (?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")))
299 ("\e$(3"f\e(B" (?2 "\e$(3#8\e(B"))
301 ("\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")
302 (?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")))
304 ("\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")
305 (?W "\e$(3"B\e(B" (?a "\e$(3"B\e(B")
306 (?e "\e$(3"@%n\e(B") (?u "\e$(3"@%r\e(B") (?i "\e$(3"@%o\e(B") (?E "\e$(3"@%q\e(B")))
308 ("\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")
309 (?W "\e$(3#\\e(B" (?a "\e$(3#\\e(B")
310 (?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")))
312 ("\e$(3"c\e(B" (?2 "\e$(3#5\e(B") (?a "\e$(3"j\e(B"))
314 ("\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")
315 (?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"))
316 (?Y "\e$(3$a\e(B" (?a "\e$(3$a\e(B")))
318 ("\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")
319 (?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"))
320 (?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")))
322 ("\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")
323 (?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"))
324 (?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")
325 (?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"))))
327 ("\e$(3"e\e(B" (?2 "\e$(3#7\e(B"))
329 ("\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")
330 (?W "\e$(3#l\e(B" (?a "\e$(3#l\e(B")
331 (?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")))
333 ("\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")
334 (?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"))
335 (?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")))
337 ("\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")
338 (?W "\e$(3!0\e(B" (?a "\e$(3!0\e(B")
339 (?e "\e$(3!.%n\e(B") (?u "\e$(3!.%r\e(B") (?i "\e$(3!.%o\e(B") (?E "\e$(3!.%q\e(B")))
341 ("\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")
342 (?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"))
343 (?Y "\e$(3$_\e(B" (?a "\e$(3$_\e(B")))
345 ("\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")
346 (?W "\e$(3"Z\e(B" (?a "\e$(3"Z\e(B")
347 (?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")))
349 ("\e$(3"i\e(B" (?2 "\e$(3#;\e(B"))
351 ("\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")
352 (?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")))
354 ("\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")
355 (?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"))
356 (?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")))
358 ("\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")
359 (?W "\e$(3!P\e(B" (?a "\e$(3!P\e(B")
360 (?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"))
361 (?Y "\e$(3$`\e(B" (?a "\e$(3$`\e(B")))
363 ("\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")
364 (?W "\e$(3!X\e(B" (?a "\e$(3!X\e(B")
365 (?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"))
366 (?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")
367 (?W "\e$(3!H\e(B" (?a "\e$(3!H\e(B")
368 (?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"))))
370 ("\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")
371 (?W "\e$(3":\e(B" (?a "\e$(3":\e(B")
372 (?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")))
374 ("\e$(3"d\e(B" (?2 "\e$(3#6\e(B"))
376 ("\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")
377 (?W "\e$(3"2\e(B" (?a "\e$(3"2\e(B")
378 (?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")))
380 ("\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")
381 (?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")))
383 ("\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")
384 (?W "\e$(3!`\e(B" (?a "\e$(3!`\e(B")
385 (?e "\e$(3!^%n\e(B") (?u "\e$(3!^%r\e(B") (?i "\e$(3!^%o\e(B") (?E "\e$(3!^%q\e(B")))
387 ("\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")
388 (?W "\e$(3#T\e(B" (?a "\e$(3#T\e(B")
389 (?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")))
391 ("\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")
392 (?W "\e$(3#D\e(B" (?a "\e$(3#D\e(B")
393 (?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")))
399 (defun ethio-sera-to-fidel-region (beg end &optional secondary force)
400 "Convert the characters in region from SERA to FIDEL.
401 The variable `ethio-primary-language' specifies the primary language
402 and `ethio-secondary-language' specifies the secondary.
404 If the 3rd parameter SECONDARY is given and non-nil, assume the region
405 begins begins with the secondary language; otherwise with the primary
408 If the 4th parameter FORCE is given and non-nil, perform conversion
409 even if the buffer is read-only.
411 See also the descriptions of the variables
412 `ethio-use-colon-for-colon' and
413 `ethio-use-three-dot-question'."
417 (narrow-to-region beg end)
418 (ethio-sera-to-fidel-buffer secondary force)))
421 (defun ethio-sera-to-fidel-buffer (&optional secondary force)
422 "Convert the current buffer from SERA to FIDEL.
424 The variable `ethio-primary-language' specifies the primary
425 language and `ethio-secondary-language' specifies the secondary.
427 If the 1st optional parameter SECONDARY is non-nil, assume the buffer
428 begins with the secondary language; otherwise with the primary
431 If the 2nd optional parametr FORCE is non-nil, perform conversion even if the
434 See also the descriptions of the variables
435 `ethio-use-colon-for-colon' and
436 `ethio-use-three-dot-question'."
440 (if (and buffer-read-only
442 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
445 (let ((ethio-primary-language ethio-primary-language)
446 (ethio-secondary-language ethio-secondary-language)
447 (ethio-use-colon-for-colon ethio-use-colon-for-colon)
448 (ethio-use-three-dot-question ethio-use-three-dot-question)
449 ;; The above four variables may be changed temporary
450 ;; by tilde escapes during conversion. So we bind them to other
451 ;; variables but of the same names.
452 (buffer-read-only nil)
453 (case-fold-search nil)
457 (setq current-language
459 ethio-secondary-language
460 ethio-primary-language))
462 (goto-char (point-min))
467 ((eq current-language 'english)
468 (ethio-sera-to-fidel-english))
469 ((eq current-language 'amharic)
470 (ethio-sera-to-fidel-ethio 'amharic))
471 ((eq current-language 'tigrigna)
472 (ethio-sera-to-fidel-ethio 'tigrigna))
473 (t ; we don't know what to do
474 (ethio-sera-to-fidel-english))))
476 (setq current-language
479 ;; when language tag is explicitly specified
480 ((not (eq next-language 'toggle))
483 ;; found a toggle in a primary language section
484 ((eq current-language ethio-primary-language)
485 ethio-secondary-language)
487 ;; found a toggle in a secondary, third, fourth, ...
490 ethio-primary-language))))
492 ;; If ethio-implicit-period-conversion is non-nil, the
493 ;; Ethiopic dot "\e$(3%u\e(B" at the end of an Ethiopic sentence is
494 ;; replaced with the Ethiopic full stop "\e$(3$i\e(B".
495 (if ethio-implicit-period-conversion
497 (goto-char (point-min))
498 (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]\\)"
500 (replace-match "\\1\e$(3$i\e(B\\2"))
501 (goto-char (point-min))
502 (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)
503 (replace-match "\\1\e$(3$i\e(B"))))
506 (goto-char (point-min))
507 (while (re-search-forward "\\ce\e$(3%s\e(B" nil 0)
509 (save-excursion (backward-char 2) (point))
513 (defun ethio-sera-to-fidel-english nil
514 "Handle English section in SERA to FIDEL conversion.
515 Conversion stops when a language switch is found. Then delete that
516 switch and return the name of the new language as a symbol."
517 (let ((new-language nil))
519 (while (and (not (eobp)) (null new-language))
522 ;; if no more "\", nothing to do.
523 ((not (search-forward "\\" nil 0)))
525 ;; hereafter point is put after a "\".
526 ;; first delete that "\", then check the following chars
528 ;; "\\" : leave the second "\"
530 (delete-backward-char 1)
531 (= (following-char) ?\\ ))
534 ;; "\ " : delete the following " "
535 ((= (following-char) 32)
537 (setq new-language 'toggle))
540 ((setq new-language (ethio-process-language-flag)))
542 ;; just a "\" : not special sequence.
544 (setq new-language 'toggle))))
548 (defun ethio-sera-to-fidel-ethio (lang)
549 "Handle Ethiopic section in SERA to FIDEL conversion.
550 Conversion stops when a language switch is found. Then delete that
551 switch and return the name of the new language as a symbol.
553 The parameter LANG (symbol, either `amharic' or `tigrigna') affects
554 the conversion of \"a\"."
556 (let ((new-language nil)
558 start table table2 ch)
560 (setcar (aref ethio-sera-to-fidel-table ?a)
561 (if (eq lang 'tigrigna) "\e$(3"f\e(B" "\e$(3"c\e(B"))
563 (while (and (not (eobp)) (null new-language))
564 (setq ch (following-char))
567 ;; skip from "<" to ">" (or from "&" to ";") if in w3-mode
568 ((and (boundp 'sera-being-called-by-w3)
569 sera-being-called-by-w3
570 (or (= ch ?<) (= ch ?&)))
571 (search-forward (if (= ch ?<) ">" ";")
574 ;; leave non-ASCII characters as they are
579 ((looking-at "`[1-9][0-9]*")
581 (ethio-convert-digit))
583 ;; if not seeing a "\", do sera to fidel conversion
587 (setq table (aref ethio-sera-to-fidel-table ch))
588 (while (setq table2 (cdr (assoc (following-char) table)))
591 (if (setq ch (car table))
593 (delete-region start (point))
596 (insert (eval ch))))))
598 ;; if control reaches here, we must be looking at a "\"
602 (if (looking-at "\\\\~! ?")
604 ;; "\~!" or "\~! ". switch to non-verbatim mode
609 ;; "\" but not "\~!" nor "\~! ". skip the current "\".
612 ;; hereafter, non-verbatim mode and looking at a "\"
613 ;; first delete that "\", then check the following chars.
615 ;; "\ " : delete the following " "
618 (setq ch (following-char))
621 (setq new-language 'toggle))
623 ;; "\~!" or "\~! " : switch to verbatim mode
629 ((setq new-language (ethio-process-language-flag)))
631 ;; "\~" but not "\~!" nor a language flag
634 (ethio-tilde-escape))
636 ;; ASCII punctuation escape. skip
637 ((looking-at "\\(,\\|\\.\\|;\\|:\\|'\\|`\\|\?\\|\\\\\\)+")
638 (goto-char (match-end 0)))
640 ;; "\", but not special sequence
642 (setq new-language 'toggle))))
646 (defun ethio-process-language-flag nil
647 "Process a language flag of the form \"~lang\" or \"~lang1~lang2\".
649 If looking at \"~lang1~lang2\", set `ethio-primary-language' and
650 `ethio-une-secondary-language' based on \"lang1\" and \"lang2\".
651 Then delete the language flag \"~lang1~lang2\" from the buffer.
652 Return value is the new primary language.
654 If looking at \"~lang\", delete that language flag \"~lang\" from the
655 buffer and return that language. In this case
656 `ethio-primary-language' and `ethio-uni-secondary-language'
659 If an unsupported language flag is found, just return nil without
667 "~\\([a-z][a-z][a-z]?\\)~\\([a-z][a-z][a-z]?\\)[ \t\n\\]")
669 (ethio-flag-to-language
670 (buffer-substring (match-beginning 1) (match-end 1))))
672 (ethio-flag-to-language
673 (buffer-substring (match-beginning 2) (match-end 2)))))
674 (setq ethio-primary-language lang1
675 ethio-secondary-language lang2)
676 (delete-region (point) (match-end 2))
677 (if (= (following-char) 32)
679 ethio-primary-language)
682 ((and (looking-at "~\\([a-z][a-z][a-z]?\\)[ \t\n\\]")
684 (ethio-flag-to-language
685 (buffer-substring (match-beginning 1) (match-end 1)))))
686 (delete-region (point) (match-end 1))
687 (if (= (following-char) 32)
695 (defun ethio-tilde-escape nil
696 "Handle a SERA tilde escape in Ethiopic section and delete it.
697 Delete the escape even it is not recognised."
699 (let ((p (point)) command)
700 (skip-chars-forward "^ \t\n\\\\")
701 (setq command (buffer-substring p (point)))
702 (delete-region p (point))
703 (if (= (following-char) 32)
709 ((string= command "-:")
710 (setq ethio-use-colon-for-colon t))
713 ((string= command "`:")
714 (setq ethio-use-colon-for-colon nil))
717 ((string= command "?")
718 (setq ethio-use-three-dot-question nil))
721 ((string= command "`|")
722 (setq ethio-use-three-dot-question t))
725 ((string= command "e")
726 (insert "\e$(3%j\e(B"))
729 ((string= command "E")
730 (insert "\e$(3%k\e(B"))
733 ((string= command "a")
734 (insert "\e$(3%l\e(B"))
737 ((string= command "A")
738 (insert "\e$(3%m\e(B"))
741 ((string= command "X")
742 (insert "\e$(3%i\e(B"))
744 ;; unsupported tilde escape
748 (defun ethio-flag-to-language (flag)
750 ((or (string= flag "en") (string= flag "eng")) 'english)
751 ((or (string= flag "ti") (string= flag "tir")) 'tigrigna)
752 ((or (string= flag "am") (string= flag "amh")) 'amharic)
755 (defun ethio-convert-digit nil
756 "Convert Arabic digits to Ethiopic digits."
758 (while (and (>= (setq ch (following-char)) ?1)
762 ;; count up following zeros
764 (while (= (following-char) ?0)
770 ;; first digit is 10, 20, ..., or 90
772 (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)))
775 ;; first digit is 2, 3, ..., or 9
777 (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))))
781 (insert "\e$(3$p\e(B")))
785 (insert "\e$(3%$\e(B"))
788 (insert-char ?\e$(3%%\e(B (/ z 4)))))
791 (defun ethio-sera-to-fidel-mail-or-marker (&optional arg)
792 "Execute ethio-sera-to-fidel-mail or ethio-sera-to-fidel-marker depending on the current major mode.
793 If in rmail-mode or in mail-mode, execute the former; otherwise latter."
796 (if (or (eq major-mode 'rmail-mode)
797 (eq major-mode 'mail-mode))
798 (ethio-sera-to-fidel-mail (prefix-numeric-value arg))
799 (ethio-sera-to-fidel-marker arg)))
802 (defun ethio-sera-to-fidel-mail (&optional arg)
803 "Convert SERA to FIDEL to read/write mail and news.
805 If the buffer contains the markers \"<sera>\" and \"</sera>\",
806 convert the segments between them into FIDEL.
808 If invoked interactively and there is no marker, convert the subject field
809 and the body into FIDEL using `ethio-sera-to-fidel-region'."
812 (let ((buffer-read-only nil)
816 ;; follow RFC822 rules instead of looking for a fixed separator
819 (setq border (point))
821 ;; note that the point is placed at the border
822 (if (or (re-search-forward "^<sera>$" nil t)
824 (goto-char (point-min))
825 (re-search-forward "^Subject: <sera>" border t)))
829 ;; we start with the body so that the border will not change
830 ;; use "^<sera>\n" instead of "^<sera>$" not to leave a blank line
832 (while (re-search-forward "^<sera>\n" nil t)
834 (ethio-sera-to-fidel-region
837 (if (re-search-forward "^</sera>\n" nil 0)
840 ;; now process the subject
841 (goto-char (point-min))
842 (if (re-search-forward "^Subject: <sera>" border t)
843 (ethio-sera-to-fidel-region
844 (progn (delete-backward-char 6) (point))
846 (if (re-search-forward "</sera>$" (line-end-position) 0)
850 ;; in case there are no marks but invoked interactively
853 (ethio-sera-to-fidel-region border (point-max))
854 (goto-char (point-min))
855 (if (re-search-forward "^Subject: " border t)
856 (ethio-sera-to-fidel-region (point) (line-end-position))))))
858 ;; adjust the rmail marker
859 (if (eq major-mode 'rmail-mode)
861 (aref rmail-message-vector (1+ rmail-current-message))
865 (defun ethio-sera-to-fidel-marker (&optional force)
866 "Convert the regions surrounded by \"<sera>\" and \"</sera>\" from SERA to FIDEL.
867 Assume that each region begins with `ethio-primary-language'.
868 The markers \"<sera>\" and \"</sera>\" themselves are not deleted."
870 (if (and buffer-read-only
872 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
875 (goto-char (point-min))
876 (while (re-search-forward "<sera>" nil t)
877 (ethio-sera-to-fidel-region
879 (if (re-search-forward "</sera>" nil t)
889 (defconst ethio-fidel-to-sera-map
890 [ "he" "hu" "hi" "ha" "hE" "h" "ho" "" ;; 0 - 7
891 "le" "lu" "li" "la" "lE" "l" "lo" "lWa" ;; 8
892 "He" "Hu" "Hi" "Ha" "HE" "H" "Ho" "HWa" ;; 16
893 "me" "mu" "mi" "ma" "mE" "m" "mo" "mWa" ;; 24
894 "`se" "`su" "`si" "`sa" "`sE" "`s" "`so" "`sWa" ;; 32
895 "re" "ru" "ri" "ra" "rE" "r" "ro" "rWa" ;; 40
896 "se" "su" "si" "sa" "sE" "s" "so" "sWa" ;; 48
897 "xe" "xu" "xi" "xa" "xE" "x" "xo" "xWa" ;; 56
898 "qe" "qu" "qi" "qa" "qE" "q" "qo" "" ;; 64
899 "qWe" "" "qWi" "qWa" "qWE" "qW'" "" "" ;; 72
900 "Qe" "Qu" "Qi" "Qa" "QE" "Q" "Qo" "" ;; 80
901 "QWe" "" "QWi" "QWa" "QWE" "QW'" "" "" ;; 88
902 "be" "bu" "bi" "ba" "bE" "b" "bo" "bWa" ;; 96
903 "ve" "vu" "vi" "va" "vE" "v" "vo" "vWa" ;; 104
904 "te" "tu" "ti" "ta" "tE" "t" "to" "tWa" ;; 112
905 "ce" "cu" "ci" "ca" "cE" "c" "co" "cWa" ;; 120
906 "`he" "`hu" "`hi" "`ha" "`hE" "`h" "`ho" "" ;; 128
907 "hWe" "" "hWi" "hWa" "hWE" "hW'" "" "" ;; 136
908 "ne" "nu" "ni" "na" "nE" "n" "no" "nWa" ;; 144
909 "Ne" "Nu" "Ni" "Na" "NE" "N" "No" "NWa" ;; 152
910 "e" "u" "i" "A" "E" "I" "o" "ea" ;; 160
911 "ke" "ku" "ki" "ka" "kE" "k" "ko" "" ;; 168
912 "kWe" "" "kWi" "kWa" "kWE" "kW'" "" "" ;; 176
913 "Ke" "Ku" "Ki" "Ka" "KE" "K" "Ko" "" ;; 184
914 "KWe" "" "KWi" "KWa" "KWE" "KW'" "" "" ;; 192
915 "we" "wu" "wi" "wa" "wE" "w" "wo" "" ;; 200
916 "`e" "`u" "`i" "`a" "`E" "`I" "`o" "" ;; 208
917 "ze" "zu" "zi" "za" "zE" "z" "zo" "zWa" ;; 216
918 "Ze" "Zu" "Zi" "Za" "ZE" "Z" "Zo" "ZWa" ;; 224
919 "ye" "yu" "yi" "ya" "yE" "y" "yo" "yWa" ;; 232
920 "de" "du" "di" "da" "dE" "d" "do" "dWa" ;; 240
921 "De" "Du" "Di" "Da" "DE" "D" "Do" "DWa" ;; 248
922 "je" "ju" "ji" "ja" "jE" "j" "jo" "jWa" ;; 256
923 "ge" "gu" "gi" "ga" "gE" "g" "go" "" ;; 264
924 "gWe" "" "gWi" "gWa" "gWE" "gW'" "" "" ;; 272
925 "Ge" "Gu" "Gi" "Ga" "GE" "G" "Go" "GWa" ;; 280
926 "Te" "Tu" "Ti" "Ta" "TE" "T" "To" "TWa" ;; 288
927 "Ce" "Cu" "Ci" "Ca" "CE" "C" "Co" "CWa" ;; 296
928 "Pe" "Pu" "Pi" "Pa" "PE" "P" "Po" "PWa" ;; 304
929 "Se" "Su" "Si" "Sa" "SE" "S" "So" "SWa" ;; 312
930 "`Se" "`Su" "`Si" "`Sa" "`SE" "`S" "`So" "" ;; 320
931 "fe" "fu" "fi" "fa" "fE" "f" "fo" "fWa" ;; 328
932 "pe" "pu" "pi" "pa" "pE" "p" "po" "pWa" ;; 336
933 "mYa" "rYa" "fYa" "" "" "" "" "" ;; 344
934 " " " : " "::" "," ";" "-:" ":-" "`?" ;; 352
935 ":|:" "1" "2" "3" "4" "5" "6" "7" ;; 360
936 "8" "9" "10" "20" "30" "40" "50" "60" ;; 368
937 "70" "80" "90" "100" "10000" "" "" "" ;; 376
938 "`qe" "`qu" "`qi" "`qa" "`qE" "`q" "`qo" "" ;; 384
939 "mWe" "bWe" "GWe" "fWe" "pWe" "" "" "" ;; 392
940 "`ke" "`ku" "`ki" "`ka" "`kE" "`k" "`ko" "" ;; 400
941 "mWi" "bWi" "GWi" "fWi" "pWi" "" "" "" ;; 408
942 "Xe" "Xu" "Xi" "Xa" "XE" "X" "Xo" "" ;; 416
943 "mWE" "bWE" "GWE" "fWE" "pWE" "" "" "" ;; 424
944 "`ge" "`gu" "`gi" "`ga" "`gE" "`g" "`go" "" ;; 432
945 "mW'" "bW'" "GW'" "fW'" "pW'" "" "" "" ;; 440
946 "\\~X " "\\~e " "\\~E " "\\~a " "\\~A " "wWe" "wWi" "wWa" ;; 448
947 "wWE" "wW'" "''" "`!" "." "<<" ">>" "?" ]) ;; 456
949 (defun ethio-prefer-amharic-p nil
950 (or (eq ethio-primary-language 'amharic)
951 (and (not (eq ethio-primary-language 'tigrigna))
952 (eq ethio-secondary-language 'amharic))))
954 (defun ethio-language-to-flag (lang)
956 ((eq lang 'english) "eng")
957 ((eq lang 'tigrigna) "tir")
958 ((eq lang 'amharic) "amh")
962 (defun ethio-fidel-to-sera-region (begin end &optional secondary force)
963 "Replace all the FIDEL characters in the region to the SERA format.
964 The variable `ethio-primary-language' specifies the primary
965 language and `ethio-secondary-language' specifies the secondary.
967 If the 3dr parameter SECONDARY is given and non-nil, try to convert
968 the region so that it begins in the secondary language; otherwise with
969 the primary language.
971 If the 4th parameter FORCE is given and non-nil, convert even if the
974 See also the descriptions of the variables
975 `ethio-use-colon-for-colon', `ethio-use-three-dot-question',
976 `ethio-quote-vowel-always' and `ethio-numeric-reduction'."
980 (narrow-to-region begin end)
981 (ethio-fidel-to-sera-buffer secondary force)))
984 (defun ethio-fidel-to-sera-buffer (&optional secondary force)
985 "Replace all the FIDEL characters in the current buffer to the SERA format.
986 The variable `ethio-primary-language' specifies the primary
987 language and `ethio-secondary-language' specifies the secondary.
989 If the 1st optional parameter SECONDARY is non-nil, try to convert the
990 region so that it begins in the secondary language; otherwise with the
993 If the 2nd optional parameter FORCE is non-nil, convert even if the
996 See also the descriptions of the variables
997 `ethio-use-colon-for-colon', `ethio-use-three-dot-question',
998 `ethio-quote-vowel-always' and `ethio-numeric-reduction'."
1001 (if (and buffer-read-only
1003 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
1006 (let ((buffer-read-only nil)
1007 (case-fold-search nil)
1008 (lonec nil) ;; t means previous char was a lone consonant
1009 (fidel nil) ;; t means previous char was a FIDEL
1010 (digit nil) ;; t means previous char was an Ethiopic digit
1011 (flag (if (ethio-prefer-amharic-p) "\\~amh " "\\~tir "))
1014 ;; user's preference in transcription
1015 (if ethio-use-colon-for-colon
1017 (aset ethio-fidel-to-sera-map 353 "`:")
1018 (aset ethio-fidel-to-sera-map 357 ":"))
1019 (aset ethio-fidel-to-sera-map 353 " : ")
1020 (aset ethio-fidel-to-sera-map 357 "-:"))
1022 (if ethio-use-three-dot-question
1024 (aset ethio-fidel-to-sera-map 359 "?")
1025 (aset ethio-fidel-to-sera-map 463 "`?"))
1026 (aset ethio-fidel-to-sera-map 359 "`?")
1027 (aset ethio-fidel-to-sera-map 463 "?"))
1031 (aset (aref ethio-fidel-to-sera-map x)
1033 (if ethio-W-sixth-always ?' ?u)))
1034 '(77 93 141 181 197 277 440 441 442 443 444 457))
1036 (if (ethio-prefer-amharic-p)
1037 (aset ethio-fidel-to-sera-map 160 "a")
1038 (aset ethio-fidel-to-sera-map 160 "e"))
1039 ;; end of user's preference
1041 ;; first, decompose geminated characters
1042 (decompose-region (point-min) (point-max))
1044 ;; main conversion routine
1045 (goto-char (point-min))
1047 (setq ch (following-char))
1049 (cond ; ethiopic, english, neutral
1051 ;; ethiopic character. must go to ethiopic mode, if not in it.
1052 ((eq (char-charset ch) 'ethiopic)
1053 (setq ch (ethio-char-to-ethiocode ch))
1055 (if (not (eq mode 'ethiopic))
1058 (setq mode 'ethiopic)))
1060 (cond ; fidel, punc, digit
1063 ((or (<= ch 346) ; he - fYa
1064 (and (>= ch 384) (<= ch 444)) ; `qe - pw
1065 (and (>= ch 453) (<= ch 457))) ; wWe - wW
1066 (if (and (memq ch '(160 161 162 163 164 166 167)) ; (e - ea)
1068 (and ethio-quote-vowel-always
1071 (insert (aref ethio-fidel-to-sera-map ch))
1072 (setq lonec (ethio-lone-consonant-p ch)
1076 ;; punctuations or icons
1077 ((or (and (>= ch 353) (<= ch 360)) ; : - :|:
1078 (>= ch 458) ; '' - ?
1079 (and (>= ch 448) (<= ch 452))) ; \~X \~e \~E \~a \~A
1080 (insert (aref ethio-fidel-to-sera-map ch))
1085 ;; now CH must be an ethiopic digit
1087 ;; reduction = 0 or not preceded by Ethiopic number(s)
1088 ((or (= ethio-numeric-reduction 0)
1090 (insert "`" (aref ethio-fidel-to-sera-map ch))
1095 ;; reduction = 2 and following 10s, 100s, 10000s
1096 ((and (= ethio-numeric-reduction 2)
1097 (memq ch '(370 379 380)))
1098 (insert (substring (aref ethio-fidel-to-sera-map ch) 1))
1103 ;; ordinary following digits
1105 (insert (aref ethio-fidel-to-sera-map ch))
1110 ;; english character. must go to english mode, if not in it.
1111 ((or (and (>= ch ?a) (<= ch ?z))
1112 (and (>= ch ?A) (<= ch ?Z)))
1113 (if (not (eq mode 'english))
1121 ;; ch can appear both in ethiopic section and in english section.
1124 ;; we must decide the mode, if not decided yet
1129 ethio-secondary-language
1130 ethio-primary-language))
1131 (if (eq mode 'english)
1134 (setq mode 'ethiopic)))) ; tigrigna & amharic --> ethiopic
1136 (cond ; \ , eng-mode , punc , w3 , other
1138 ;; backslash is always quoted
1143 ;; nothing to do if in english mode
1147 ;; now we must be in ethiopic mode and seeing a non-"\"
1149 ;; ascii punctuations in ethiopic mode
1150 ((looking-at "[,.;:'`?]+")
1152 (goto-char (1+ (match-end 0)))) ; because we inserted one byte (\)
1154 ;; skip from "<" to ">" (or from "&" to ";") if called from w3
1155 ((and (boundp 'sera-being-called-by-w3)
1156 sera-being-called-by-w3
1157 (or (= ch ?<) (= ch ?&)))
1158 (search-forward (if (= ch ?<) ">" ";")
1161 ;; neutral character. no need to quote. just skip it.
1168 ;; end of main conversion routine
1171 (defun ethio-lone-consonant-p (ethiocode)
1172 "If ETHIOCODE is an Ethiopic lone consonant, return t."
1173 (or (and (< ethiocode 344) (= (% ethiocode 8) 5))
1175 ;; `q `k X `g mW bW GW fW pW wW
1176 (memq ethiocode '(389 405 421 437 440 441 442 443 444 457))))
1179 (defun ethio-fidel-to-sera-mail-or-marker (&optional arg)
1180 "Execute ethio-fidel-to-sera-mail or ethio-fidel-to-sera-marker depending on the current major mode.
1181 If in rmail-mode or in mail-mode, execute the former; otherwise latter."
1184 (if (or (eq major-mode 'rmail-mode)
1185 (eq major-mode 'mail-mode))
1186 (ethio-fidel-to-sera-mail)
1187 (ethio-fidel-to-sera-marker arg)))
1190 (defun ethio-fidel-to-sera-mail nil
1191 "Convert FIDEL to SERA to read/write mail and news.
1193 If the body contains at least one Ethiopic character,
1194 1) insert the string \"<sera>\" at the beginning of the body,
1195 2) insert \"</sera>\" at the end of the body, and
1196 3) convert the body into SERA.
1198 The very same procedure applies to the subject field, too."
1201 (let ((buffer-read-only nil)
1205 ;; follow RFC822 rules instead of looking for a fixed separator
1208 (setq border (point))
1210 ;; process body first not to change the border
1211 ;; note that the point is already at the border
1212 (if (re-search-forward "\\ce" nil t)
1214 (ethio-fidel-to-sera-region border (point-max))
1217 (goto-char (point-max))
1218 (insert "</sera>")))
1221 (goto-char (point-min))
1222 (if (re-search-forward "^Subject: " border t)
1224 (end (line-end-position)))
1225 (if (re-search-forward "\\ce" end t)
1227 (ethio-fidel-to-sera-region beg end)
1231 (insert "</sera>")))))
1233 ;; adjust the rmail marker
1234 (if (eq major-mode 'rmail-mode)
1236 (aref rmail-message-vector (1+ rmail-current-message))
1240 (defun ethio-fidel-to-sera-marker (&optional force)
1241 "Convert the regions surrounded by \"<sera>\" and \"</sera>\" from FIDEL to SERA.
1242 The markers \"<sera>\" and \"</sera>\" themselves are not deleted."
1245 (if (and buffer-read-only
1247 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
1250 (goto-char (point-min))
1251 (while (re-search-forward "<sera>" nil t)
1252 (ethio-fidel-to-sera-region
1254 (if (re-search-forward "</sera>" nil t)
1261 ;; vowel modification
1265 (defun ethio-modify-vowel nil
1266 "Modify the vowel of the FIDEL that is under the cursor."
1268 (let ((ch (following-char))
1269 (composite nil) ; geminated or not
1270 newch base vowel modulo)
1273 ;; in case of gemination
1274 ((eq (char-charset ch) 'composition)
1275 (setq ch (string-to-char (decompose-composite-char ch))
1277 ;; neither gemination nor fidel
1278 ((not (eq (char-charset ch) 'ethiopic))
1279 (error "Not a valid character.")))
1281 ;; set frequently referred character features
1282 (setq ch (ethio-char-to-ethiocode ch)
1286 (if (or (and (>= ch 344) (<= ch 380)) ;; mYa - `10000
1287 (and (>= ch 448) (<= ch 452)) ;; \~X - \~A
1288 (>= ch 458)) ;; private punctuations
1289 (error "Not a valid character."))
1295 ;; first standalone vowels
1297 (if (ethio-prefer-amharic-p)
1298 (message "Modify vowel to: [auiAEIoW\"] ")
1299 (message "Modify vowel to: [euiAEIoW\"] "))
1300 (setq vowel (read-char))
1310 ((= vowel ?a) (if (ethio-prefer-amharic-p) 160 163))
1311 ((= vowel ?\") (setq composite t) ch)
1314 ;; second standalone vowels
1316 (message "Modify vowel to: [euiaEIo\"] ")
1317 (setq vowel (read-char))
1326 ((= vowel ?\") (setq composite t) ch)
1329 ;; 12-form consonants, *W* form
1330 ((memq base '(72 88 136 176 192 272)) ; qW QW hW kW KW gW
1331 (message "Modify vowel to: [euiaE'\"] ")
1332 (setq vowel (read-char))
1335 ((= vowel ?u) (+ base 5))
1336 ((= vowel ?i) (+ base 2))
1337 ((= vowel ?a) (+ base 3))
1338 ((= vowel ?E) (+ base 4))
1339 ((= vowel ?') (+ base 5))
1340 ((= vowel ?\") (setq composite t) ch)
1343 ;; extended 12-form consonants, mWa bWa GWa fWa pWa
1345 (message "Modify vowel to: [euiaE'\"] ")
1346 (setq vowel (read-char))
1354 ((= vowel ?\") (setq composite t) ch)
1357 (message "Modify vowel to: [euiaE'\"] ")
1358 (setq vowel (read-char))
1366 ((= vowel ?\") (setq composite t) ch)
1369 (message "Modify vowel to: [euiaE'\"] ")
1370 (setq vowel (read-char))
1378 ((= vowel ?\") (setq composite t) ch)
1381 (message "Modify vowel to: [euiaE'\"] ")
1382 (setq vowel (read-char))
1390 ((= vowel ?\") (setq composite t) ch)
1393 (message "Modify vowel to: [euiaE'\"] ")
1394 (setq vowel (read-char))
1402 ((= vowel ?\") (setq composite t) ch)
1405 ;; extended 12-form consonatns, mW* bW* GW* fW* pW*
1406 ((memq base '(392 408 424 440)) ; *We *Wi *WE *W
1407 (message "Modify vowel to: [eiEau'\"] ")
1408 (setq vowel (read-char))
1410 ((= vowel ?e) (+ 392 modulo))
1411 ((= vowel ?i) (+ 408 modulo))
1412 ((= vowel ?E) (+ 424 modulo))
1414 ((= modulo 0) 31) ; mWa
1415 ((= modulo 1) 103) ; bWa
1416 ((= modulo 2) 287) ; GWa
1417 ((= modulo 3) 335) ; fWa
1418 ((= modulo 4) 343) ; pWa
1419 (t nil))) ; never reach here
1420 ((= vowel ?') (+ 440 modulo))
1421 ((= vowel ?u) (+ 440 modulo))
1422 ((= vowel ?\") (setq composite t) ch)
1425 ((and (>= ch 453) (<= ch 457)) ; wWe wWi wWa wWE wW
1426 (message "Modify vowel to: [eiaE'u\"] ")
1427 (setq vowel (read-char))
1435 ((= vowel ?\") (setq composite t) ch)
1438 ;; 7-form consonants, or
1439 ;; first 7 of 8-form consonants
1441 (message "Modify vowel to: [euiaE'o\"] ")
1442 (setq vowel (read-char))
1445 ((= vowel ?u) (+ base 1))
1446 ((= vowel ?i) (+ base 2))
1447 ((= vowel ?a) (+ base 3))
1448 ((= vowel ?E) (+ base 4))
1449 ((= vowel ?') (+ base 5))
1450 ((= vowel ?o) (+ base 6))
1451 ((= vowel ?\") (setq composite t) ch)
1460 ;; could not get new character
1462 (error "Invalid vowel"))
1464 ;; vowel changed on a composite Fidel
1469 (concat (char-to-string (ethio-ethiocode-to-char newch)) "\e$(3%s\e(B"))))
1471 ;; simple vowel modification
1474 (insert (ethio-ethiocode-to-char newch))))))
1476 (defun ethio-ethiocode-to-char (ethiocode)
1479 (+ (/ ethiocode 94) 33)
1480 (+ (mod ethiocode 94) 33)))
1482 (defun ethio-char-to-ethiocode (ch)
1483 (and (eq (char-charset ch) 'ethiopic)
1484 (let ((char-components (split-char ch)))
1485 (+ (* (- (nth 1 char-components) 33) 94)
1486 (- (nth 2 char-components) 33)))))
1489 ;; space replacement
1493 (defun ethio-replace-space (ch begin end)
1494 "Replace ASCII spaces with Ethiopic word separators in the region.
1496 In the specified region, replace word separators surrounded by two
1497 Ethiopic characters, depending on the first parameter CH, which should
1500 If CH = 1, word separator will be replaced with an ASCII space.
1501 If CH = 2, with two ASCII spaces.
1502 If CH = 3, with the Ethiopic colon-like word separator.
1504 The second and third parameters BEGIN and END specify the region."
1506 (interactive "*cReplace spaces to: 1 (sg col), 2 (dbl col), 3 (Ethiopic)\nr")
1507 (if (not (memq ch '(?1 ?2 ?3)))
1511 (narrow-to-region begin end)
1515 ;; an Ethiopic word separator --> an ASCII space
1516 (goto-char (point-min))
1517 (while (search-forward "\e$(3$h\e(B" nil t)
1518 (replace-match " " nil t))
1520 ;; two ASCII spaces between Ethiopic characters --> an ASCII space
1521 (goto-char (point-min))
1522 (while (re-search-forward "\\(\\ce\\) \\(\\ce\\)" nil t)
1523 (replace-match "\\1 \\2")
1524 (goto-char (match-beginning 2))))
1527 ;; An Ethiopic word separator --> two ASCII spaces
1528 (goto-char (point-min))
1529 (while (search-forward "\e$(3$h\e(B" nil t)
1530 (replace-match " "))
1532 ;; An ASCII space between Ethiopic characters --> two ASCII spaces
1533 (goto-char (point-min))
1534 (while (re-search-forward "\\(\\ce\\) \\(\\ce\\)" nil t)
1535 (replace-match "\\1 \\2")
1536 (goto-char (match-beginning 2))))
1539 ;; One or two ASCII spaces between Ethiopic characters
1540 ;; --> An Ethiopic word separator
1541 (goto-char (point-min))
1542 (while (re-search-forward "\\(\\ce\\) ?\\(\\ce\\)" nil t)
1543 (replace-match "\\1\e$(3$h\e(B\\2")
1544 (goto-char (match-beginning 2)))
1546 ;; Three or more ASCII spaces between Ethiopic characters
1547 ;; --> An Ethiopic word separator + (N - 2) ASCII spaces
1548 (goto-char (point-min))
1549 (while (re-search-forward "\\(\\ce\\) \\( *\\ce\\)" nil t)
1550 (replace-match "\\1\e$(3$h\e(B\\2")
1551 (goto-char (match-beginning 2))))))))
1558 (defun ethio-input-special-character (arg)
1559 "Allow the user to input special characters."
1560 (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")
1563 (insert "\e$(3%j\e(B"))
1565 (insert "\e$(3%k\e(B"))
1567 (insert "\e$(3%l\e(B"))
1569 (insert "\e$(3%m\e(B"))
1571 (insert "\e$(3%i\e(B"))
1579 (defconst ethio-fidel-to-tex-map
1580 [ "heG" "huG" "hiG" "haG" "hEG" "hG" "hoG" "" ;; 0 - 7
1581 "leG" "luG" "liG" "laG" "lEG" "lG" "loG" "lWaG" ;; 8
1582 "HeG" "HuG" "HiG" "HaG" "HEG" "HG" "HoG" "HWaG" ;; 16
1583 "meG" "muG" "miG" "maG" "mEG" "mG" "moG" "mWaG" ;; 24
1584 "sseG" "ssuG" "ssiG" "ssaG" "ssEG" "ssG" "ssoG" "ssWaG" ;; 32
1585 "reG" "ruG" "riG" "raG" "rEG" "rG" "roG" "rWaG" ;; 40
1586 "seG" "suG" "siG" "saG" "sEG" "sG" "soG" "sWaG" ;; 48
1587 "xeG" "xuG" "xiG" "xaG" "xEG" "xG" "xoG" "xWaG" ;; 56
1588 "qeG" "quG" "qiG" "qaG" "qEG" "qG" "qoG" "" ;; 64
1589 "qWeG" "" "qWiG" "qWaG" "qWEG" "qWG" "" "" ;; 72
1590 "QeG" "QuG" "QiG" "QaG" "QEG" "QG" "QoG" "" ;; 80
1591 "QWeG" "" "QWiG" "QWaG" "QWEG" "QWG" "" "" ;; 88
1592 "beG" "buG" "biG" "baG" "bEG" "bG" "boG" "bWaG" ;; 96
1593 "veG" "vuG" "viG" "vaG" "vEG" "vG" "voG" "vWaG" ;; 104
1594 "teG" "tuG" "tiG" "taG" "tEG" "tG" "toG" "tWaG" ;; 112
1595 "ceG" "cuG" "ciG" "caG" "cEG" "cG" "coG" "cWaG" ;; 120
1596 "hheG" "hhuG" "hhiG" "hhaG" "hhEG" "hhG" "hhoG" "" ;; 128
1597 "hWeG" "" "hWiG" "hWaG" "hWEG" "hWG" "" "" ;; 136
1598 "neG" "nuG" "niG" "naG" "nEG" "nG" "noG" "nWaG" ;; 144
1599 "NeG" "NuG" "NiG" "NaG" "NEG" "NG" "NoG" "NWaG" ;; 152
1600 "eG" "uG" "iG" "AG" "EG" "IG" "oG" "eaG" ;; 160
1601 "keG" "kuG" "kiG" "kaG" "kEG" "kG" "koG" "" ;; 168
1602 "kWeG" "" "kWiG" "kWaG" "kWEG" "kWG" "" "" ;; 176
1603 "KeG" "KuG" "KiG" "KaG" "KEG" "KG" "KoG" "" ;; 184
1604 "KWeG" "" "KWiG" "KWaG" "KWEG" "KWG" "" "" ;; 192
1605 "weG" "wuG" "wiG" "waG" "wEG" "wG" "woG" "" ;; 200
1606 "eeG" "uuG" "iiG" "aaG" "EEG" "IIG" "ooG" "" ;; 208
1607 "zeG" "zuG" "ziG" "zaG" "zEG" "zG" "zoG" "zWaG" ;; 216
1608 "ZeG" "ZuG" "ZiG" "ZaG" "ZEG" "ZG" "ZoG" "ZWaG" ;; 224
1609 "yeG" "yuG" "yiG" "yaG" "yEG" "yG" "yoG" "yWaG" ;; 232
1610 "deG" "duG" "diG" "daG" "dEG" "dG" "doG" "dWaG" ;; 240
1611 "DeG" "DuG" "DiG" "DaG" "DEG" "DG" "DoG" "DWaG" ;; 248
1612 "jeG" "juG" "jiG" "jaG" "jEG" "jG" "joG" "jWaG" ;; 256
1613 "geG" "guG" "giG" "gaG" "gEG" "gG" "goG" "" ;; 264
1614 "gWeG" "" "gWiG" "gWaG" "gWEG" "gWG" "" "" ;; 272
1615 "GeG" "GuG" "GiG" "GaG" "GEG" "GG" "GoG" "GWaG" ;; 280
1616 "TeG" "TuG" "TiG" "TaG" "TEG" "TG" "ToG" "TWaG" ;; 288
1617 "CeG" "CuG" "CiG" "CaG" "CEG" "CG" "CoG" "CWaG" ;; 296
1618 "PeG" "PuG" "PiG" "PaG" "PEG" "PG" "PoG" "PWaG" ;; 304
1619 "SeG" "SuG" "SiG" "SaG" "SEG" "SG" "SoG" "SWaG" ;; 312
1620 "SSeG" "SSuG" "SSiG" "SSaG" "SSEG" "SSG" "SSoG" "" ;; 320
1621 "feG" "fuG" "fiG" "faG" "fEG" "fG" "foG" "fWaG" ;; 328
1622 "peG" "puG" "piG" "paG" "pEG" "pG" "poG" "pWaG" ;; 336
1623 "mYaG" "rYaG" "fYaG" "" "" "" "" "" ;; 344
1624 "" "spaceG" "periodG" "commaG" ;; 352
1625 "semicolonG" "colonG" "precolonG" "oldqmarkG" ;; 356
1626 "pbreakG" "andG" "huletG" "sostG" "aratG" "amstG" "sadstG" "sabatG" ;; 360
1627 "smntG" "zeteNG" "asrG" "heyaG" "selasaG" "arbaG" "hemsaG" "slsaG" ;; 368
1628 "sebaG" "semanyaG" "zeTanaG" "metoG" "asrxiG" "" "" "" ;; 376
1629 "qqeG" "qquG" "qqiG" "qqaG" "qqEG" "qqG" "qqoG" "" ;; 384
1630 "mWeG" "bWeG" "GWeG" "fWeG" "pWeG" "" "" "" ;; 392
1631 "kkeG" "kkuG" "kkiG" "kkaG" "kkEG" "kkG" "kkoG" "" ;; 400
1632 "mWiG" "bWiG" "GWiG" "fWiG" "pWiG" "" "" "" ;; 408
1633 "XeG" "XuG" "GXiG" "XaG" "XEG" "XG" "XoG" "" ;; 416
1634 "mWEG" "bWEG" "GWEG" "fWEG" "pWEG" "" "" "" ;; 424
1635 "ggeG" "gguG" "ggiG" "ggaG" "ggEG" "ggG" "ggoG" "" ;; 432
1636 "mWG" "bWG" "GWG" "fWG" "pWG" "" "" "" ;; 440
1637 "ornamentG" "flandG" "iflandG" "africaG" ;; 448
1638 "iafricaG" "wWeG" "wWiG" "wWaG" ;; 452
1639 "wWEG" "wWG" "" "slaqG" "dotG" "lquoteG" "rquoteG" "qmarkG" ]) ;; 456
1642 ;; To make tex-to-fidel mapping.
1643 ;; The following code makes
1644 ;; (get 'ethio-tex-command-he 'ethio-fidel-char) ==> ?\e$(3!!\e(B
1649 (while (< i (length ethio-fidel-to-tex-map))
1650 (setq str (aref ethio-fidel-to-tex-map i))
1651 (if (not (string= str ""))
1653 (intern (concat "ethio-tex-command-" (aref ethio-fidel-to-tex-map i)))
1655 (ethio-ethiocode-to-char i)))
1659 (defun ethio-fidel-to-tex-buffer nil
1660 "Convert each fidel characters in the current buffer into a fidel-tex command.
1661 Each command is always surrounded by braces."
1663 (let ((buffer-read-only nil))
1665 ;; Isolated gemination marks need special treatement
1666 (goto-char (point-min))
1667 (while (search-forward "\e$(3%s\e(B" nil t)
1668 (replace-match "\\geminateG{}" t t))
1670 ;; First, decompose geminations
1671 ;; Here we assume that each composed character consists of
1672 ;; one Ethiopic character and the Ethiopic gemination mark.
1673 (decompose-region (point-min) (point-max))
1675 ;; Special treatment for geminated characters
1676 ;; The geminated character (la'') will be "\geminateG{\la}".
1677 (goto-char (point-min))
1678 (while (search-forward "\e$(3%s\e(B" nil t)
1679 (delete-backward-char 1)
1681 (insert "\\geminateG")
1684 ;; Ethiopic characters to TeX macros
1685 (goto-char (point-min))
1686 (while (re-search-forward "\\ce" nil t)
1689 (aref ethio-fidel-to-tex-map
1690 (prog1 (ethio-char-to-ethiocode (preceding-char))
1691 (backward-delete-char 1)))
1693 (goto-char (point-min))
1694 (set-buffer-modified-p nil)))
1697 (defun ethio-tex-to-fidel-buffer nil
1698 "Convert fidel-tex commands in the current buffer into fidel chars."
1700 (let ((buffer-read-only nil)
1703 ;; Special treatment for gemination
1704 ;; "\geminateG{\la}" or "\geminateG{{\la}}" will be "\la\e$(3%s\e(B"
1705 ;; "\geminateG{}" remains unchanged.
1706 (goto-char (point-min))
1707 (while (re-search-forward "\\\\geminateG{\\(\\\\[a-zA-Z]+\\)}" nil t)
1708 (replace-match "\\1\e$(3%s\e(B"))
1710 ;; TeX macros to Ethiopic characters
1711 (goto-char (point-min))
1712 (while (search-forward "\\" nil t)
1714 (skip-chars-forward "a-zA-Z")
1716 (get (intern (concat "ethio-tex-command-"
1717 (buffer-substring p (point))))
1721 (delete-region (1- p) (point)) ; don't forget the preceding "\"
1722 (if (and (= (preceding-char) ?{)
1723 (= (following-char) ?}))
1725 (backward-delete-char 1)
1729 ;; compose geminated characters
1730 (goto-char (point-min))
1731 (while (re-search-forward "\\ce\e$(3%s\e(B" nil 0)
1733 (save-excursion (backward-char 2) (point))
1736 ;; Now it's time to convert isolated gemination marks.
1737 (goto-char (point-min))
1738 (while (search-forward "\\geminateG{}" nil t)
1739 (replace-match "\e$(3%s\e(B"))
1741 (goto-char (point-min))
1742 (set-buffer-modified-p nil)))
1749 (defun ethio-fidel-to-java-buffer nil
1750 "Convert Ethiopic characters into the Java escape sequences.
1752 Each escape sequence is of the form \uXXXX, where XXXX is the
1753 character's codepoint (in hex) in Unicode.
1755 If `ethio-java-save-lowercase' is non-nil, use [0-9a-f].
1756 Otherwise, [0-9A-F]."
1759 ;; first, decompose geminations
1760 (decompose-region (point-min) (point-max))
1762 (goto-char (point-min))
1763 (while (re-search-forward "\\ce" nil t)
1764 (setq ucode (+ ?\x1200 (ethio-char-to-ethiocode (preceding-char))))
1765 (if (> ucode ?\x13bc)
1766 (setq ucode (+ ucode 59952)))
1767 (delete-backward-char 1)
1768 (if ethio-java-save-lowercase
1769 (insert (format "\\u%4x" ucode))
1770 (insert (upcase (format "\\u%4x" ucode)))))))
1773 (defun ethio-java-to-fidel-buffer nil
1774 "Convert the Java escape sequences into corresponding Ethiopic characters."
1776 (goto-char (point-min))
1777 (while (re-search-forward "\\\\u\\([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\\)" nil t)
1782 (buffer-substring (match-beginning 1) (match-end 1)))))
1784 ((and (>= ucode ?\x1200) (<= ucode ?\x13bc))
1786 (insert (ethio-ethiocode-to-char (- ucode ?\x1200))))
1787 ((and (>= ucode ?\xfdf1) (<= ucode ?\xfdff))
1789 (insert (ethio-ethiocode-to-char (- ucode 64560))))
1794 (goto-char (point-min))
1795 (while (re-search-forward "\\ce\e$(3%s\e(B" nil 0)
1797 (save-excursion (backward-char 2) (point))
1806 (defun ethio-find-file nil
1807 "Transcribe file content into Ethiopic dependig on filename suffix."
1810 ((string-match "\\.sera$" (buffer-file-name))
1812 (ethio-sera-to-fidel-buffer nil 'force)
1813 (set-buffer-modified-p nil)))
1815 ((string-match "\\.html$" (buffer-file-name))
1816 (let ((sera-being-called-by-w3 t))
1818 (ethio-sera-to-fidel-marker 'force)
1819 (goto-char (point-min))
1820 (while (re-search-forward "&[lr]aquote;" nil t)
1821 (if (= (char-after (1+ (match-beginning 0))) ?l)
1822 (replace-match "\e$(3%v\e(B")
1823 (replace-match "\e$(3%w\e(B")))
1824 (set-buffer-modified-p nil))))
1826 ((string-match "\\.tex$" (buffer-file-name))
1828 (ethio-tex-to-fidel-buffer)
1829 (set-buffer-modified-p nil)))
1831 ((string-match "\\.java$" (buffer-file-name))
1833 (ethio-java-to-fidel-buffer)
1834 (set-buffer-modified-p nil)))
1840 (defun ethio-write-file nil
1841 "Transcribe Ethiopic characters in ASCII depending on the file extension."
1844 ((string-match "\\.sera$" (buffer-file-name))
1846 (ethio-fidel-to-sera-buffer nil 'force)
1847 (goto-char (point-min))
1848 (ethio-record-user-preference)
1849 (set-buffer-modified-p nil)))
1851 ((string-match "\\.html$" (buffer-file-name))
1853 (let ((sera-being-called-by-w3 t)
1854 (lq (aref ethio-fidel-to-sera-map 461))
1855 (rq (aref ethio-fidel-to-sera-map 462)))
1856 (aset ethio-fidel-to-sera-map 461 "«te;")
1857 (aset ethio-fidel-to-sera-map 462 "»te;")
1858 (ethio-fidel-to-sera-marker 'force)
1859 (goto-char (point-min))
1860 (if (search-forward "<sera>" nil t)
1861 (ethio-record-user-preference))
1862 (aset ethio-fidel-to-sera-map 461 lq)
1863 (aset ethio-fidel-to-sera-map 462 rq)
1864 (set-buffer-modified-p nil))))
1866 ((string-match "\\.tex$" (buffer-file-name))
1868 (ethio-fidel-to-tex-buffer)
1869 (set-buffer-modified-p nil)))
1871 ((string-match "\\.java$" (buffer-file-name))
1873 (ethio-fidel-to-java-buffer)
1874 (set-buffer-modified-p nil)))
1879 (defun ethio-record-user-preference nil
1880 (if (looking-at "\\\\~\\(tir?\\|amh?\\) ")
1881 (goto-char (match-end 0))
1882 (insert (if (ethio-prefer-amharic-p) "\\~amh " "\\~tir ")))
1883 (insert (if ethio-use-colon-for-colon "\\~-: " "\\~`: ")
1884 (if ethio-use-three-dot-question "\\~`| " "\\~`? ")))
1887 ;; Ethiopic word separator vs. ASCII space
1890 (defvar ethio-prefer-ascii-space t)
1891 (make-variable-buffer-local 'ethio-prefer-ascii-space)
1893 (defun ethio-toggle-space nil
1894 "Toggle ASCII space and Ethiopic separator for keyboard input."
1896 (setq ethio-prefer-ascii-space
1897 (not ethio-prefer-ascii-space))
1898 (force-mode-line-update))
1900 (defun ethio-insert-space (arg)
1901 "Insert ASCII spaces or Ethiopic word separators depending on context.
1903 If the current word separator (indicated in mode-line) is the ASCII space,
1904 insert an ASCII space. With ARG, insert that many ASCII spaces.
1906 If the current word separator is the colon-like Ethiopic word
1907 separator and the point is preceded by `an Ethiopic punctuation mark
1908 followed by zero or more ASCII spaces', then insert also an ASCII
1909 space. With ARG, insert that many ASCII spaces.
1911 Otherwise, insert a colon-like Ethiopic word separator. With ARG, insert that
1912 many Ethiopic word separators."
1916 (ethio-prefer-ascii-space
1917 (insert-char 32 arg))
1919 (skip-chars-backward " ")
1920 (memq (preceding-char)
1921 '(?\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)))
1922 (insert-char 32 arg))
1924 (insert-char ?\e$(3$h\e(B arg))))
1926 (defun ethio-insert-ethio-space (arg)
1927 "Insert the Ethiopic word delimiter (the colon-like character).
1928 With ARG, insert that many delimiters."
1930 (insert-char ?\e$(3$h\e(B arg))
1933 ;; Ethiopic punctuation vs. ASCII punctuation
1936 (defvar ethio-prefer-ascii-punctuation nil)
1937 (make-variable-buffer-local 'ethio-prefer-ascii-punctuation)
1939 (defun ethio-toggle-punctuation nil
1940 "Toggle Ethiopic punctuations and ASCII punctuations for keyboard input."
1942 (setq ethio-prefer-ascii-punctuation
1943 (not ethio-prefer-ascii-punctuation))
1944 (let* ((keys '("." ".." "..." "," ",," ";" ";;" ":" "::" ":::" "*" "**"))
1946 (if ethio-prefer-ascii-punctuation
1947 '(?. [".."] ["..."] ?, [",,"] ?\; [";;"] ?: ["::"] [":::"] ?* ["**"])
1948 '(?\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))))
1950 (quail-defrule (car keys) (car puncs) "ethiopic")
1951 (setq keys (cdr keys)
1953 (force-mode-line-update)))
1959 (defun ethio-gemination nil
1960 "Compose the character before the point with the Ethiopic gemination mark.
1961 If the characater is already composed, decompose it and remove the gemination
1965 ((eq (char-charset (preceding-char)) 'ethiopic)
1966 (insert "\e$(3%s\e(B")
1968 (save-excursion (backward-char 2) (point))
1971 ((eq (char-charset (preceding-char)) 'leading-code-composition)
1973 (save-excursion (backward-char 1) (point))
1975 (delete-backward-char 1))
1980 (provide 'ethio-util)
1982 ;;; ethio-util.el ends here