1 ;;; ethio-util.el --- utilities for Ethiopic -*- coding: iso-2022-7bit; -*-
3 ;; Copyright (C) 1997, 2001 Electrotechnical Laboratory, JAPAN.
4 ;; Licensed to the Free Software Foundation.
6 ;; Keywords: mule, multilingual, Ethiopic
8 ;; This file is part of GNU Emacs.
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;; Author: TAKAHASHI Naoto <ntakahas@m17n.org>
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
)
38 ;; these old bindings conflict
39 ;; with Emacs' binding policy
41 ;; ([f2] . ethio-toggle-space)
42 ;; ([S-f2] . ethio-replace-space) ; as requested
43 ;; ([f3] . ethio-toggle-punctuation)
44 ;; ([f4] . ethio-sera-to-fidel-buffer)
45 ;; ([S-f4] . ethio-sera-to-fidel-region)
46 ;; ([C-f4] . ethio-sera-to-fidel-mail-or-marker)
47 ;; ([f5] . ethio-fidel-to-sera-buffer)
48 ;; ([S-f5] . ethio-fidel-to-sera-region)
49 ;; ([C-f5] . ethio-fidel-to-sera-mail-or-marker)
50 ;; ([f6] . ethio-modify-vowel)
51 ;; ([f7] . ethio-replace-space)
52 ;; ([f8] . ethio-input-special-character)
54 ;; this is the rewritten bindings
56 ([f3] . ethio-fidel-to-sera-buffer)
57 ([S-f3] . ethio-fidel-to-sera-region)
58 ([C-f3] . ethio-fidel-to-sera-mail-or-marker)
59 ([f4] . ethio-sera-to-fidel-buffer)
60 ([S-f4] . ethio-sera-to-fidel-region)
61 ([C-f4] . ethio-sera-to-fidel-mail-or-marker)
62 ([S-f5] . ethio-toggle-punctuation)
63 ([S-f6] . ethio-modify-vowel)
64 ([S-f7] . ethio-replace-space)
65 ([S-f8] . ethio-input-special-character)
66 ([C-f9] . ethio-toggle-space)
67 ([S-f9] . ethio-replace-space) ; as requested
71 (setq kb (car (car key-bindings)))
72 (setq exit-ethiopic-environment-data
73 (cons (cons kb (global-key-binding kb))
74 exit-ethiopic-environment-data))
75 (global-set-key kb (cdr (car key-bindings)))
76 (setq key-bindings (cdr key-bindings))))
78 (add-hook 'quail-activate-hook 'ethio-select-a-translation)
79 (add-hook 'find-file-hooks 'ethio-find-file)
80 (add-hook 'write-file-hooks 'ethio-write-file)
81 (add-hook 'after-save-hook 'ethio-find-file))
83 (defun exit-ethiopic-environment ()
84 "Exit Ethiopic language environment"
85 (while exit-ethiopic-environment-data
86 (global-set-key (car (car exit-ethiopic-environment-data))
87 (cdr (car exit-ethiopic-environment-data)))
88 (setq exit-ethiopic-environment-data
89 (cdr exit-ethiopic-environment-data)))
91 (remove-hook 'quail-activate-hook 'ethio-select-a-translation)
92 (remove-hook 'find-file-hooks 'ethio-find-file)
93 (remove-hook 'write-file-hooks 'ethio-write-file)
94 (remove-hook 'after-save-hook 'ethio-find-file))
97 ;; ETHIOPIC UTILITY FUNCTIONS
100 ;; If the filename ends in ".sera", editing is done in fidel
101 ;; but file I/O is done in SERA.
103 ;; If the filename ends in ".java", editing is done in fidel
104 ;; but file I/O is done in the \uXXXX style, where XXXX is
105 ;; the Unicode codepoint for the Ethiopic character.
107 ;; If the filename ends in ".tex", editing is done in fidel
108 ;; but file I/O is done in EthioTeX format.
110 ;; To automatically convert Ethiopic text to SERA format when sending mail,
111 ;; (add-hook 'mail-send-hook 'ethio-fidel-to-sera-mail)
113 ;; To automatically convert SERA format to Ethiopic when receiving mail,
114 ;; (add-hook 'rmail-show-message-hook 'ethio-sera-to-fidel-mail)
116 ;; To automatically convert Ethiopic text to SERA format when posting news,
117 ;; (add-hook 'news-inews-hook 'ethio-fidel-to-sera-mail)
123 (defvar ethio-primary-language 'tigrigna
124 "*Symbol that defines the primary language in SERA --> FIDEL conversion.
125 The value should be one of: `tigrigna', `amharic' or `english'.")
127 (defvar ethio-secondary-language 'english
128 "*Symbol that defines the secondary language in SERA --> FIDEL conversion.
129 The value should be one of: `tigrigna', `amharic' or `english'.")
131 (defvar ethio-use-colon-for-colon nil
132 "*Non-nil means associate ASCII colon with Ethiopic colon.
133 If nil, associate ASCII colon with Ethiopic word separator, i.e., two
134 vertically stacked dots. All SERA <--> FIDEL converters refer this
137 (defvar ethio-use-three-dot-question nil
138 "*Non-nil means associate ASCII question mark with Ethiopic old style question mark (three vertically stacked dots).
139 If nil, associate ASCII question mark with Ethiopic stylised question
140 mark. All SERA <--> FIDEL converters refer this variable.")
142 (defvar ethio-quote-vowel-always nil
143 "*Non-nil means always put an apostrophe before an isolated vowel (except at word initial) in FIDEL --> SERA conversion.
144 If nil, put an apostrophe only between a sixth-form consonant and an
147 (defvar ethio-W-sixth-always nil
148 "*Non-nil means convert the Wu-form of a 12-form consonant to \"W'\" instead of \"Wu\" in FIDEL --> SERA conversion.")
150 (defvar ethio-numeric-reduction 0
151 "*Degree of reduction in converting Ethiopic digits into Arabic digits.
153 For example, ({10}{9}{100}{80}{7}) is converted into:
154 `10`9`100`80`7 if `ethio-numeric-reduction' is 0,
155 `109100807 if `ethio-numeric-reduction' is 1,
156 `10900807 if `ethio-numeric-reduction' is 2.")
158 (defvar ethio-implicit-period-conversion t
159 "*Non-nil means replacing the Ethiopic dot at the end of an Ethiopic sentence
160 with an Ethiopic full stop.")
162 (defvar ethio-java-save-lowercase nil
163 "*Non-nil means save Ethiopic characters in lowercase hex numbers to Java files.
164 If nil, use uppercases.")
170 (defconst ethio-sera-to-fidel-table
172 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
173 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
176 (?: (if ethio-use-colon-for-colon " \e$(3$l\e(B" "\e$(3$h\e(B")
177 (32 (if ethio-use-colon-for-colon " \e$(3$l\e(B " "\e$(3$h\e(B"))
180 (?| (if ethio-use-colon-for-colon " \e$(3$l\e(B|" " \e$(3$h\e(B|")
181 (?: " \e$(3$o\e(B"))))
184 nil nil nil nil nil nil ("" (?' "\e$(3%s\e(B"))
186 nil nil nil nil ("\e$(3$j\e(B") ("-" (?: "\e$(3$l\e(B")) ("\e$(3%u\e(B")
187 ;;; / 0 1 2 3 4 5 6 7 8 9
188 nil nil nil nil nil nil nil nil nil nil nil
190 ((if ethio-use-colon-for-colon "\e$(3$l\e(B" "\e$(3$h\e(B")
191 (32 (if ethio-use-colon-for-colon "\e$(3$l\e(B " "\e$(3$h\e(B"))
194 (?| (if ethio-use-colon-for-colon "\e$(3$l\e(B|" "\e$(3$h\e(B|")
197 ("\e$(3$k\e(B") ("<" (?< "\e$(3%v\e(B")) nil (">" (?> "\e$(3%w\e(B"))
199 ((if ethio-use-three-dot-question "\e$(3$n\e(B" "\e$(3%x\e(B"))
203 ("\e$(3"f\e(B" (?2 "\e$(3#8\e(B"))
205 ("\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")
206 (?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")))
208 ("\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")
209 (?W "\e$(3$6\e(B" (?a "\e$(3$6\e(B")
210 (?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")))
212 ("\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")
213 (?W "\e$(3#d\e(B" (?a "\e$(3#d\e(B")
214 (?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")))
216 ("\e$(3"g\e(B" (?2 "\e$(3#9\e(B"))
218 ("\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")
219 (?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"))
220 (?Y "\e$(3$a\e(B" (?a "\e$(3$a\e(B")))
222 ("\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")
223 (?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")))
225 ("\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")
226 (?W "\e$(3!8\e(B" (?a "\e$(3!8\e(B")
227 (?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")))
229 ("\e$(3"h\e(B" (?2 "\e$(3#:\e(B"))
231 ("\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")
232 (?W "\e$(3#l\e(B" (?a "\e$(3#l\e(B")
233 (?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")))
235 ("\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")
236 (?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")))
238 ("\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")
239 (?W "\e$(3!0\e(B" (?a "\e$(3!0\e(B")
240 (?e "\e$(3!.%n\e(B") (?u "\e$(3!.%r\e(B") (?i "\e$(3!.%o\e(B") (?E "\e$(3!.%q\e(B")))
242 ("\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")
243 (?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"))
244 (?Y "\e$(3$_\e(B" (?a "\e$(3$_\e(B")))
246 ("\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")
247 (?W "\e$(3"b\e(B" (?a "\e$(3"b\e(B")
248 (?e "\e$(3"`%n\e(B") (?u "\e$(3"`%r\e(B") (?i "\e$(3"`%o\e(B") (?E "\e$(3"`%q\e(B")))
250 ("\e$(3"i\e(B" (?2 "\e$(3#;\e(B"))
252 ("\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")
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!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")
257 (?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")))
259 ("\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")
260 (?W "\e$(3!P\e(B" (?a "\e$(3!P\e(B")
261 (?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"))
262 (?Y "\e$(3$`\e(B" (?a "\e$(3$`\e(B")))
264 ("\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")
265 (?W "\e$(3$F\e(B" (?a "\e$(3$F\e(B")
266 (?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"))
268 (?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")
269 (?W "\e$(3$F\e(B" (?a "\e$(3$F\e(B")
270 (?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"))))
272 ("\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")
273 (?W "\e$(3$.\e(B" (?a "\e$(3$.\e(B")
274 (?e "\e$(3$,%n\e(B") (?u "\e$(3$,%r\e(B") (?i "\e$(3$,%o\e(B") (?E "\e$(3$,%q\e(B")))
276 ("\e$(3"d\e(B" (?2 "\e$(3#6\e(B"))
278 ("\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")
279 (?W "\e$(3"2\e(B" (?a "\e$(3"2\e(B")
280 (?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")))
282 ("\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"))
284 ("\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"))
286 ("\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")
287 (?W "\e$(3#T\e(B" (?a "\e$(3#T\e(B")
288 (?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")))
290 ("\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")
291 (?W "\e$(3#L\e(B" (?a "\e$(3#L\e(B")
292 (?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")))
298 (?? (if ethio-use-three-dot-question "\e$(3%x\e(B" "\e$(3$n\e(B"))
300 (?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")
301 (?E "\e$(3#9\e(B") (?I "\e$(3#:\e(B") (?o "\e$(3#;\e(B") (?O "\e$(3#;\e(B")
303 (?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"))
305 (?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")
306 (?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")))
308 (?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"))
310 (?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")
311 (?W "\e$(3!H\e(B" (?a "\e$(3!H\e(B")
312 (?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")))
314 (?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")
315 (?W "\e$(3$F\e(B" (?a "\e$(3$F\e(B")
316 (?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")))
317 (?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")))
319 ("\e$(3"f\e(B" (?2 "\e$(3#8\e(B"))
321 ("\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")
322 (?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")))
324 ("\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")
325 (?W "\e$(3"B\e(B" (?a "\e$(3"B\e(B")
326 (?e "\e$(3"@%n\e(B") (?u "\e$(3"@%r\e(B") (?i "\e$(3"@%o\e(B") (?E "\e$(3"@%q\e(B")))
328 ("\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")
329 (?W "\e$(3#\\e(B" (?a "\e$(3#\\e(B")
330 (?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")))
332 ("\e$(3"c\e(B" (?2 "\e$(3#5\e(B") (?a "\e$(3"j\e(B"))
334 ("\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")
335 (?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"))
336 (?Y "\e$(3$a\e(B" (?a "\e$(3$a\e(B")))
338 ("\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")
339 (?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"))
340 (?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")))
342 ("\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")
343 (?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"))
344 (?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")
345 (?W "\e$(3"P\e(B" (?e "\e$(3"K\e(B") (?u "\e$(3"P\e(B") (?i "\e$(3"M\e(B") (?a "\e$(3"N\e(B") (?E "\e$(3"O\e(B"))))
347 ("\e$(3"e\e(B" (?2 "\e$(3#7\e(B"))
349 ("\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")
350 (?W "\e$(3#l\e(B" (?a "\e$(3#l\e(B")
351 (?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")))
353 ("\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")
354 (?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"))
355 (?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")))
357 ("\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 (?W "\e$(3!0\e(B" (?a "\e$(3!0\e(B")
359 (?e "\e$(3!.%n\e(B") (?u "\e$(3!.%r\e(B") (?i "\e$(3!.%o\e(B") (?E "\e$(3!.%q\e(B")))
361 ("\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 (?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"))
363 (?Y "\e$(3$_\e(B" (?a "\e$(3$_\e(B")))
365 ("\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")
366 (?W "\e$(3"Z\e(B" (?a "\e$(3"Z\e(B")
367 (?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")))
369 ("\e$(3"i\e(B" (?2 "\e$(3#;\e(B"))
371 ("\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")
372 (?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")))
374 ("\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")
375 (?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"))
376 (?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")))
378 ("\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")
379 (?W "\e$(3!P\e(B" (?a "\e$(3!P\e(B")
380 (?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"))
381 (?Y "\e$(3$`\e(B" (?a "\e$(3$`\e(B")))
383 ("\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")
384 (?W "\e$(3!X\e(B" (?a "\e$(3!X\e(B")
385 (?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"))
386 (?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")
387 (?W "\e$(3!H\e(B" (?a "\e$(3!H\e(B")
388 (?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"))))
390 ("\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")
391 (?W "\e$(3":\e(B" (?a "\e$(3":\e(B")
392 (?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")))
394 ("\e$(3"d\e(B" (?2 "\e$(3#6\e(B"))
396 ("\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")
397 (?W "\e$(3"2\e(B" (?a "\e$(3"2\e(B")
398 (?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")))
400 ("\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")
401 (?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")))
403 ("\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")
404 (?W "\e$(3!`\e(B" (?a "\e$(3!`\e(B")
405 (?e "\e$(3!^%n\e(B") (?u "\e$(3!^%r\e(B") (?i "\e$(3!^%o\e(B") (?E "\e$(3!^%q\e(B")))
407 ("\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")
408 (?W "\e$(3#T\e(B" (?a "\e$(3#T\e(B")
409 (?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")))
411 ("\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")
412 (?W "\e$(3#D\e(B" (?a "\e$(3#D\e(B")
413 (?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")))
419 (defun ethio-sera-to-fidel-region (beg end &optional secondary force)
420 "Convert the characters in region from SERA to FIDEL.
421 The variable `ethio-primary-language' specifies the primary language
422 and `ethio-secondary-language' specifies the secondary.
424 If the 3rd parameter SECONDARY is given and non-nil, assume the region
425 begins begins with the secondary language; otherwise with the primary
428 If the 4th parameter FORCE is given and non-nil, perform conversion
429 even if the buffer is read-only.
431 See also the descriptions of the variables
432 `ethio-use-colon-for-colon' and
433 `ethio-use-three-dot-question'."
437 (narrow-to-region beg end)
438 (ethio-sera-to-fidel-buffer secondary force)))
441 (defun ethio-sera-to-fidel-buffer (&optional secondary force)
442 "Convert the current buffer from SERA to FIDEL.
444 The variable `ethio-primary-language' specifies the primary
445 language and `ethio-secondary-language' specifies the secondary.
447 If the 1st optional parameter SECONDARY is non-nil, assume the buffer
448 begins with the secondary language; otherwise with the primary
451 If the 2nd optional parametr FORCE is non-nil, perform conversion even if the
454 See also the descriptions of the variables
455 `ethio-use-colon-for-colon' and
456 `ethio-use-three-dot-question'."
460 (if (and buffer-read-only
462 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
465 (let ((ethio-primary-language ethio-primary-language)
466 (ethio-secondary-language ethio-secondary-language)
467 (ethio-use-colon-for-colon ethio-use-colon-for-colon)
468 (ethio-use-three-dot-question ethio-use-three-dot-question)
469 ;; The above four variables may be changed temporary
470 ;; by tilde escapes during conversion. So we bind them to other
471 ;; variables but of the same names.
472 (buffer-read-only nil)
473 (case-fold-search nil)
477 (setq current-language
479 ethio-secondary-language
480 ethio-primary-language))
482 (goto-char (point-min))
487 ((eq current-language 'english)
488 (ethio-sera-to-fidel-english))
489 ((eq current-language 'amharic)
490 (ethio-sera-to-fidel-ethio 'amharic))
491 ((eq current-language 'tigrigna)
492 (ethio-sera-to-fidel-ethio 'tigrigna))
493 (t ; we don't know what to do
494 (ethio-sera-to-fidel-english))))
496 (setq current-language
499 ;; when language tag is explicitly specified
500 ((not (eq next-language 'toggle))
503 ;; found a toggle in a primary language section
504 ((eq current-language ethio-primary-language)
505 ethio-secondary-language)
507 ;; found a toggle in a secondary, third, fourth, ...
510 ethio-primary-language))))
512 ;; If ethio-implicit-period-conversion is non-nil, the
513 ;; Ethiopic dot "\e$(3%u\e(B" at the end of an Ethiopic sentence is
514 ;; replaced with the Ethiopic full stop "\e$(3$i\e(B".
515 (if ethio-implicit-period-conversion
517 (goto-char (point-min))
518 (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]\\)"
520 (replace-match "\\1\e$(3$i\e(B\\2"))
521 (goto-char (point-min))
522 (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)
523 (replace-match "\\1\e$(3$i\e(B"))))
526 (goto-char (point-min))
527 (while (re-search-forward "\\ce\e$(3%s\e(B" nil 0)
529 (save-excursion (backward-char 2) (point))
533 (defun ethio-sera-to-fidel-english nil
534 "Handle English section in SERA to FIDEL conversion.
535 Conversion stops when a language switch is found. Then delete that
536 switch and return the name of the new language as a symbol."
537 (let ((new-language nil))
539 (while (and (not (eobp)) (null new-language))
542 ;; if no more "\", nothing to do.
543 ((not (search-forward "\\" nil 0)))
545 ;; hereafter point is put after a "\".
546 ;; first delete that "\", then check the following chars
548 ;; "\\" : leave the second "\"
550 (delete-backward-char 1)
551 (= (following-char) ?\\ ))
554 ;; "\ " : delete the following " "
555 ((= (following-char) 32)
557 (setq new-language 'toggle))
560 ((setq new-language (ethio-process-language-flag)))
562 ;; just a "\" : not special sequence.
564 (setq new-language 'toggle))))
568 (defun ethio-sera-to-fidel-ethio (lang)
569 "Handle Ethiopic section in SERA to FIDEL conversion.
570 Conversion stops when a language switch is found. Then delete that
571 switch and return the name of the new language as a symbol.
573 The parameter LANG (symbol, either `amharic' or `tigrigna') affects
574 the conversion of \"a\"."
576 (let ((new-language nil)
578 start table table2 ch)
580 (setcar (aref ethio-sera-to-fidel-table ?a)
581 (if (eq lang 'tigrigna) "\e$(3"f\e(B" "\e$(3"c\e(B"))
583 (while (and (not (eobp)) (null new-language))
584 (setq ch (following-char))
587 ;; skip from "<" to ">" (or from "&" to ";") if in w3-mode
588 ((and (boundp 'sera-being-called-by-w3)
589 sera-being-called-by-w3
590 (or (= ch ?<) (= ch ?&)))
591 (search-forward (if (= ch ?<) ">" ";")
594 ;; leave non-ASCII characters as they are
599 ((looking-at "`[1-9][0-9]*")
601 (ethio-convert-digit))
603 ;; if not seeing a "\", do sera to fidel conversion
607 (setq table (aref ethio-sera-to-fidel-table ch))
608 (while (setq table2 (cdr (assoc (following-char) table)))
611 (if (setq ch (car table))
613 (delete-region start (point))
616 (insert (eval ch))))))
618 ;; if control reaches here, we must be looking at a "\"
622 (if (looking-at "\\\\~! ?")
624 ;; "\~!" or "\~! ". switch to non-verbatim mode
629 ;; "\" but not "\~!" nor "\~! ". skip the current "\".
632 ;; hereafter, non-verbatim mode and looking at a "\"
633 ;; first delete that "\", then check the following chars.
635 ;; "\ " : delete the following " "
638 (setq ch (following-char))
641 (setq new-language 'toggle))
643 ;; "\~!" or "\~! " : switch to verbatim mode
649 ((setq new-language (ethio-process-language-flag)))
651 ;; "\~" but not "\~!" nor a language flag
654 (ethio-tilde-escape))
656 ;; ASCII punctuation escape. skip
657 ((looking-at "\\(,\\|\\.\\|;\\|:\\|'\\|`\\|\?\\|\\\\\\)+")
658 (goto-char (match-end 0)))
660 ;; "\", but not special sequence
662 (setq new-language 'toggle))))
666 (defun ethio-process-language-flag nil
667 "Process a language flag of the form \"~lang\" or \"~lang1~lang2\".
669 If looking at \"~lang1~lang2\", set `ethio-primary-language' and
670 `ethio-une-secondary-language' based on \"lang1\" and \"lang2\".
671 Then delete the language flag \"~lang1~lang2\" from the buffer.
672 Return value is the new primary language.
674 If looking at \"~lang\", delete that language flag \"~lang\" from the
675 buffer and return that language. In this case
676 `ethio-primary-language' and `ethio-uni-secondary-language'
679 If an unsupported language flag is found, just return nil without
687 "~\\([a-z][a-z][a-z]?\\)~\\([a-z][a-z][a-z]?\\)[ \t\n\\]")
689 (ethio-flag-to-language
690 (buffer-substring (match-beginning 1) (match-end 1))))
692 (ethio-flag-to-language
693 (buffer-substring (match-beginning 2) (match-end 2)))))
694 (setq ethio-primary-language lang1
695 ethio-secondary-language lang2)
696 (delete-region (point) (match-end 2))
697 (if (= (following-char) 32)
699 ethio-primary-language)
702 ((and (looking-at "~\\([a-z][a-z][a-z]?\\)[ \t\n\\]")
704 (ethio-flag-to-language
705 (buffer-substring (match-beginning 1) (match-end 1)))))
706 (delete-region (point) (match-end 1))
707 (if (= (following-char) 32)
715 (defun ethio-tilde-escape nil
716 "Handle a SERA tilde escape in Ethiopic section and delete it.
717 Delete the escape even it is not recognised."
719 (let ((p (point)) command)
720 (skip-chars-forward "^ \t\n\\\\")
721 (setq command (buffer-substring p (point)))
722 (delete-region p (point))
723 (if (= (following-char) 32)
729 ((string= command "-:")
730 (setq ethio-use-colon-for-colon t))
733 ((string= command "`:")
734 (setq ethio-use-colon-for-colon nil))
737 ((string= command "?")
738 (setq ethio-use-three-dot-question nil))
741 ((string= command "`|")
742 (setq ethio-use-three-dot-question t))
745 ((string= command "e")
746 (insert "\e$(3%j\e(B"))
749 ((string= command "E")
750 (insert "\e$(3%k\e(B"))
753 ((string= command "a")
754 (insert "\e$(3%l\e(B"))
757 ((string= command "A")
758 (insert "\e$(3%m\e(B"))
761 ((string= command "X")
762 (insert "\e$(3%i\e(B"))
764 ;; unsupported tilde escape
768 (defun ethio-flag-to-language (flag)
770 ((or (string= flag "en") (string= flag "eng")) 'english)
771 ((or (string= flag "ti") (string= flag "tir")) 'tigrigna)
772 ((or (string= flag "am") (string= flag "amh")) 'amharic)
775 (defun ethio-convert-digit nil
776 "Convert Arabic digits to Ethiopic digits."
778 (while (and (>= (setq ch (following-char)) ?1)
782 ;; count up following zeros
784 (while (= (following-char) ?0)
790 ;; first digit is 10, 20, ..., or 90
792 (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)))
795 ;; first digit is 2, 3, ..., or 9
797 (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))))
801 (insert "\e$(3$p\e(B")))
805 (insert "\e$(3%$\e(B"))
808 (insert-char ?\e$(3%%\e(B (/ z 4)))))
811 (defun ethio-sera-to-fidel-mail-or-marker (&optional arg)
812 "Execute ethio-sera-to-fidel-mail or ethio-sera-to-fidel-marker depending on the current major mode.
813 If in rmail-mode or in mail-mode, execute the former; otherwise latter."
816 (if (or (eq major-mode 'rmail-mode)
817 (eq major-mode 'mail-mode))
818 (ethio-sera-to-fidel-mail (prefix-numeric-value arg))
819 (ethio-sera-to-fidel-marker arg)))
822 (defun ethio-sera-to-fidel-mail (&optional arg)
823 "Convert SERA to FIDEL to read/write mail and news.
825 If the buffer contains the markers \"<sera>\" and \"</sera>\",
826 convert the segments between them into FIDEL.
828 If invoked interactively and there is no marker, convert the subject field
829 and the body into FIDEL using `ethio-sera-to-fidel-region'."
832 (let ((buffer-read-only nil)
836 ;; follow RFC822 rules instead of looking for a fixed separator
839 (setq border (point))
841 ;; note that the point is placed at the border
842 (if (or (re-search-forward "^<sera>$" nil t)
844 (goto-char (point-min))
845 (re-search-forward "^Subject: <sera>" border t)))
849 ;; we start with the body so that the border will not change
850 ;; use "^<sera>\n" instead of "^<sera>$" not to leave a blank line
852 (while (re-search-forward "^<sera>\n" nil t)
854 (ethio-sera-to-fidel-region
857 (if (re-search-forward "^</sera>\n" nil 0)
860 ;; now process the subject
861 (goto-char (point-min))
862 (if (re-search-forward "^Subject: <sera>" border t)
863 (ethio-sera-to-fidel-region
864 (progn (delete-backward-char 6) (point))
866 (if (re-search-forward "</sera>$" (line-end-position) 0)
870 ;; in case there are no marks but invoked interactively
873 (ethio-sera-to-fidel-region border (point-max))
874 (goto-char (point-min))
875 (if (re-search-forward "^Subject: " border t)
876 (ethio-sera-to-fidel-region (point) (line-end-position))))))
878 ;; adjust the rmail marker
879 (if (eq major-mode 'rmail-mode)
881 (aref rmail-message-vector (1+ rmail-current-message))
885 (defun ethio-sera-to-fidel-marker (&optional force)
886 "Convert the regions surrounded by \"<sera>\" and \"</sera>\" from SERA to FIDEL.
887 Assume that each region begins with `ethio-primary-language'.
888 The markers \"<sera>\" and \"</sera>\" themselves are not deleted."
890 (if (and buffer-read-only
892 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
895 (goto-char (point-min))
896 (while (re-search-forward "<sera>" nil t)
897 (ethio-sera-to-fidel-region
899 (if (re-search-forward "</sera>" nil t)
909 (defconst ethio-fidel-to-sera-map
910 [ "he" "hu" "hi" "ha" "hE" "h" "ho" "" ;; 0 - 7
911 "le" "lu" "li" "la" "lE" "l" "lo" "lWa" ;; 8
912 "He" "Hu" "Hi" "Ha" "HE" "H" "Ho" "HWa" ;; 16
913 "me" "mu" "mi" "ma" "mE" "m" "mo" "mWa" ;; 24
914 "`se" "`su" "`si" "`sa" "`sE" "`s" "`so" "`sWa" ;; 32
915 "re" "ru" "ri" "ra" "rE" "r" "ro" "rWa" ;; 40
916 "se" "su" "si" "sa" "sE" "s" "so" "sWa" ;; 48
917 "xe" "xu" "xi" "xa" "xE" "x" "xo" "xWa" ;; 56
918 "qe" "qu" "qi" "qa" "qE" "q" "qo" "" ;; 64
919 "qWe" "" "qWi" "qWa" "qWE" "qW'" "" "" ;; 72
920 "Qe" "Qu" "Qi" "Qa" "QE" "Q" "Qo" "" ;; 80
921 "QWe" "" "QWi" "QWa" "QWE" "QW'" "" "" ;; 88
922 "be" "bu" "bi" "ba" "bE" "b" "bo" "bWa" ;; 96
923 "ve" "vu" "vi" "va" "vE" "v" "vo" "vWa" ;; 104
924 "te" "tu" "ti" "ta" "tE" "t" "to" "tWa" ;; 112
925 "ce" "cu" "ci" "ca" "cE" "c" "co" "cWa" ;; 120
926 "`he" "`hu" "`hi" "`ha" "`hE" "`h" "`ho" "" ;; 128
927 "hWe" "" "hWi" "hWa" "hWE" "hW'" "" "" ;; 136
928 "ne" "nu" "ni" "na" "nE" "n" "no" "nWa" ;; 144
929 "Ne" "Nu" "Ni" "Na" "NE" "N" "No" "NWa" ;; 152
930 "e" "u" "i" "A" "E" "I" "o" "ea" ;; 160
931 "ke" "ku" "ki" "ka" "kE" "k" "ko" "" ;; 168
932 "kWe" "" "kWi" "kWa" "kWE" "kW'" "" "" ;; 176
933 "Ke" "Ku" "Ki" "Ka" "KE" "K" "Ko" "" ;; 184
934 "KWe" "" "KWi" "KWa" "KWE" "KW'" "" "" ;; 192
935 "we" "wu" "wi" "wa" "wE" "w" "wo" "" ;; 200
936 "`e" "`u" "`i" "`a" "`E" "`I" "`o" "" ;; 208
937 "ze" "zu" "zi" "za" "zE" "z" "zo" "zWa" ;; 216
938 "Ze" "Zu" "Zi" "Za" "ZE" "Z" "Zo" "ZWa" ;; 224
939 "ye" "yu" "yi" "ya" "yE" "y" "yo" "yWa" ;; 232
940 "de" "du" "di" "da" "dE" "d" "do" "dWa" ;; 240
941 "De" "Du" "Di" "Da" "DE" "D" "Do" "DWa" ;; 248
942 "je" "ju" "ji" "ja" "jE" "j" "jo" "jWa" ;; 256
943 "ge" "gu" "gi" "ga" "gE" "g" "go" "" ;; 264
944 "gWe" "" "gWi" "gWa" "gWE" "gW'" "" "" ;; 272
945 "Ge" "Gu" "Gi" "Ga" "GE" "G" "Go" "GWa" ;; 280
946 "Te" "Tu" "Ti" "Ta" "TE" "T" "To" "TWa" ;; 288
947 "Ce" "Cu" "Ci" "Ca" "CE" "C" "Co" "CWa" ;; 296
948 "Pe" "Pu" "Pi" "Pa" "PE" "P" "Po" "PWa" ;; 304
949 "Se" "Su" "Si" "Sa" "SE" "S" "So" "SWa" ;; 312
950 "`Se" "`Su" "`Si" "`Sa" "`SE" "`S" "`So" "" ;; 320
951 "fe" "fu" "fi" "fa" "fE" "f" "fo" "fWa" ;; 328
952 "pe" "pu" "pi" "pa" "pE" "p" "po" "pWa" ;; 336
953 "mYa" "rYa" "fYa" "" "" "" "" "" ;; 344
954 " " " : " "::" "," ";" "-:" ":-" "`?" ;; 352
955 ":|:" "1" "2" "3" "4" "5" "6" "7" ;; 360
956 "8" "9" "10" "20" "30" "40" "50" "60" ;; 368
957 "70" "80" "90" "100" "10000" "" "" "" ;; 376
958 "`qe" "`qu" "`qi" "`qa" "`qE" "`q" "`qo" "" ;; 384
959 "mWe" "bWe" "GWe" "fWe" "pWe" "" "" "" ;; 392
960 "`ke" "`ku" "`ki" "`ka" "`kE" "`k" "`ko" "" ;; 400
961 "mWi" "bWi" "GWi" "fWi" "pWi" "" "" "" ;; 408
962 "Xe" "Xu" "Xi" "Xa" "XE" "X" "Xo" "" ;; 416
963 "mWE" "bWE" "GWE" "fWE" "pWE" "" "" "" ;; 424
964 "`ge" "`gu" "`gi" "`ga" "`gE" "`g" "`go" "" ;; 432
965 "mW'" "bW'" "GW'" "fW'" "pW'" "" "" "" ;; 440
966 "\\~X " "\\~e " "\\~E " "\\~a " "\\~A " "wWe" "wWi" "wWa" ;; 448
967 "wWE" "wW'" "''" "`!" "." "<<" ">>" "?" ]) ;; 456
969 (defun ethio-prefer-amharic-p nil
970 (or (eq ethio-primary-language 'amharic)
971 (and (not (eq ethio-primary-language 'tigrigna))
972 (eq ethio-secondary-language 'amharic))))
974 (defun ethio-language-to-flag (lang)
976 ((eq lang 'english) "eng")
977 ((eq lang 'tigrigna) "tir")
978 ((eq lang 'amharic) "amh")
982 (defun ethio-fidel-to-sera-region (begin end &optional secondary force)
983 "Replace all the FIDEL characters in the region to the SERA format.
984 The variable `ethio-primary-language' specifies the primary
985 language and `ethio-secondary-language' specifies the secondary.
987 If the 3dr parameter SECONDARY is given and non-nil, try to convert
988 the region so that it begins in the secondary language; otherwise with
989 the primary language.
991 If the 4th parameter FORCE is given and non-nil, convert even if the
994 See also the descriptions of the variables
995 `ethio-use-colon-for-colon', `ethio-use-three-dot-question',
996 `ethio-quote-vowel-always' and `ethio-numeric-reduction'."
1000 (narrow-to-region begin end)
1001 (ethio-fidel-to-sera-buffer secondary force)))
1004 (defun ethio-fidel-to-sera-buffer (&optional secondary force)
1005 "Replace all the FIDEL characters in the current buffer to the SERA format.
1006 The variable `ethio-primary-language' specifies the primary
1007 language and `ethio-secondary-language' specifies the secondary.
1009 If the 1st optional parameter SECONDARY is non-nil, try to convert the
1010 region so that it begins in the secondary language; otherwise with the
1013 If the 2nd optional parameter FORCE is non-nil, convert even if the
1014 buffer is read-only.
1016 See also the descriptions of the variables
1017 `ethio-use-colon-for-colon', `ethio-use-three-dot-question',
1018 `ethio-quote-vowel-always' and `ethio-numeric-reduction'."
1021 (if (and buffer-read-only
1023 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
1026 (let ((buffer-read-only nil)
1027 (case-fold-search nil)
1028 (lonec nil) ;; t means previous char was a lone consonant
1029 (fidel nil) ;; t means previous char was a FIDEL
1030 (digit nil) ;; t means previous char was an Ethiopic digit
1031 (flag (if (ethio-prefer-amharic-p) "\\~amh " "\\~tir "))
1034 ;; user's preference in transcription
1035 (if ethio-use-colon-for-colon
1037 (aset ethio-fidel-to-sera-map 353 "`:")
1038 (aset ethio-fidel-to-sera-map 357 ":"))
1039 (aset ethio-fidel-to-sera-map 353 " : ")
1040 (aset ethio-fidel-to-sera-map 357 "-:"))
1042 (if ethio-use-three-dot-question
1044 (aset ethio-fidel-to-sera-map 359 "?")
1045 (aset ethio-fidel-to-sera-map 463 "`?"))
1046 (aset ethio-fidel-to-sera-map 359 "`?")
1047 (aset ethio-fidel-to-sera-map 463 "?"))
1051 (aset (aref ethio-fidel-to-sera-map x)
1053 (if ethio-W-sixth-always ?' ?u)))
1054 '(77 93 141 181 197 277 440 441 442 443 444 457))
1056 (if (ethio-prefer-amharic-p)
1057 (aset ethio-fidel-to-sera-map 160 "a")
1058 (aset ethio-fidel-to-sera-map 160 "e"))
1059 ;; end of user's preference
1061 ;; first, decompose geminated characters
1062 (decompose-region (point-min) (point-max))
1064 ;; main conversion routine
1065 (goto-char (point-min))
1067 (setq ch (following-char))
1069 (cond ; ethiopic, english, neutral
1071 ;; ethiopic character. must go to ethiopic mode, if not in it.
1072 ((eq (char-charset ch) 'ethiopic)
1073 (setq ch (ethio-char-to-ethiocode ch))
1075 (if (not (eq mode 'ethiopic))
1078 (setq mode 'ethiopic)))
1080 (cond ; fidel, punc, digit
1083 ((or (<= ch 346) ; he - fYa
1084 (and (>= ch 384) (<= ch 444)) ; `qe - pw
1085 (and (>= ch 453) (<= ch 457))) ; wWe - wW
1086 (if (and (memq ch '(160 161 162 163 164 166 167)) ; (e - ea)
1088 (and ethio-quote-vowel-always
1091 (insert (aref ethio-fidel-to-sera-map ch))
1092 (setq lonec (ethio-lone-consonant-p ch)
1096 ;; punctuations or icons
1097 ((or (and (>= ch 353) (<= ch 360)) ; : - :|:
1098 (>= ch 458) ; '' - ?
1099 (and (>= ch 448) (<= ch 452))) ; \~X \~e \~E \~a \~A
1100 (insert (aref ethio-fidel-to-sera-map ch))
1105 ;; now CH must be an ethiopic digit
1107 ;; reduction = 0 or not preceded by Ethiopic number(s)
1108 ((or (= ethio-numeric-reduction 0)
1110 (insert "`" (aref ethio-fidel-to-sera-map ch))
1115 ;; reduction = 2 and following 10s, 100s, 10000s
1116 ((and (= ethio-numeric-reduction 2)
1117 (memq ch '(370 379 380)))
1118 (insert (substring (aref ethio-fidel-to-sera-map ch) 1))
1123 ;; ordinary following digits
1125 (insert (aref ethio-fidel-to-sera-map ch))
1130 ;; english character. must go to english mode, if not in it.
1131 ((or (and (>= ch ?a) (<= ch ?z))
1132 (and (>= ch ?A) (<= ch ?Z)))
1133 (if (not (eq mode 'english))
1141 ;; ch can appear both in ethiopic section and in english section.
1144 ;; we must decide the mode, if not decided yet
1149 ethio-secondary-language
1150 ethio-primary-language))
1151 (if (eq mode 'english)
1154 (setq mode 'ethiopic)))) ; tigrigna & amharic --> ethiopic
1156 (cond ; \ , eng-mode , punc , w3 , other
1158 ;; backslash is always quoted
1163 ;; nothing to do if in english mode
1167 ;; now we must be in ethiopic mode and seeing a non-"\"
1169 ;; ascii punctuations in ethiopic mode
1170 ((looking-at "[,.;:'`?]+")
1172 (goto-char (1+ (match-end 0)))) ; because we inserted one byte (\)
1174 ;; skip from "<" to ">" (or from "&" to ";") if called from w3
1175 ((and (boundp 'sera-being-called-by-w3)
1176 sera-being-called-by-w3
1177 (or (= ch ?<) (= ch ?&)))
1178 (search-forward (if (= ch ?<) ">" ";")
1181 ;; neutral character. no need to quote. just skip it.
1188 ;; end of main conversion routine
1191 (defun ethio-lone-consonant-p (ethiocode)
1192 "If ETHIOCODE is an Ethiopic lone consonant, return t."
1193 (or (and (< ethiocode 344) (= (% ethiocode 8) 5))
1195 ;; `q `k X `g mW bW GW fW pW wW
1196 (memq ethiocode '(389 405 421 437 440 441 442 443 444 457))))
1199 (defun ethio-fidel-to-sera-mail-or-marker (&optional arg)
1200 "Execute ethio-fidel-to-sera-mail or ethio-fidel-to-sera-marker depending on the current major mode.
1201 If in rmail-mode or in mail-mode, execute the former; otherwise latter."
1204 (if (or (eq major-mode 'rmail-mode)
1205 (eq major-mode 'mail-mode))
1206 (ethio-fidel-to-sera-mail)
1207 (ethio-fidel-to-sera-marker arg)))
1210 (defun ethio-fidel-to-sera-mail nil
1211 "Convert FIDEL to SERA to read/write mail and news.
1213 If the body contains at least one Ethiopic character,
1214 1) insert the string \"<sera>\" at the beginning of the body,
1215 2) insert \"</sera>\" at the end of the body, and
1216 3) convert the body into SERA.
1218 The very same procedure applies to the subject field, too."
1221 (let ((buffer-read-only nil)
1225 ;; follow RFC822 rules instead of looking for a fixed separator
1228 (setq border (point))
1230 ;; process body first not to change the border
1231 ;; note that the point is already at the border
1232 (if (re-search-forward "\\ce" nil t)
1234 (ethio-fidel-to-sera-region border (point-max))
1237 (goto-char (point-max))
1238 (insert "</sera>")))
1241 (goto-char (point-min))
1242 (if (re-search-forward "^Subject: " border t)
1244 (end (line-end-position)))
1245 (if (re-search-forward "\\ce" end t)
1247 (ethio-fidel-to-sera-region beg end)
1251 (insert "</sera>")))))
1253 ;; adjust the rmail marker
1254 (if (eq major-mode 'rmail-mode)
1256 (aref rmail-message-vector (1+ rmail-current-message))
1260 (defun ethio-fidel-to-sera-marker (&optional force)
1261 "Convert the regions surrounded by \"<sera>\" and \"</sera>\" from FIDEL to SERA.
1262 The markers \"<sera>\" and \"</sera>\" themselves are not deleted."
1265 (if (and buffer-read-only
1267 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
1270 (goto-char (point-min))
1271 (while (re-search-forward "<sera>" nil t)
1272 (ethio-fidel-to-sera-region
1274 (if (re-search-forward "</sera>" nil t)
1281 ;; vowel modification
1285 (defun ethio-modify-vowel nil
1286 "Modify the vowel of the FIDEL that is under the cursor."
1288 (let ((ch (following-char))
1289 (composite nil) ; geminated or not
1290 newch base vowel modulo)
1293 ;; in case of gemination
1294 ((eq (char-charset ch) 'composition)
1295 (setq ch (string-to-char (decompose-composite-char ch))
1297 ;; neither gemination nor fidel
1298 ((not (eq (char-charset ch) 'ethiopic))
1299 (error "Not a valid character.")))
1301 ;; set frequently referred character features
1302 (setq ch (ethio-char-to-ethiocode ch)
1306 (if (or (and (>= ch 344) (<= ch 380)) ;; mYa - `10000
1307 (and (>= ch 448) (<= ch 452)) ;; \~X - \~A
1308 (>= ch 458)) ;; private punctuations
1309 (error "Not a valid character."))
1315 ;; first standalone vowels
1317 (if (ethio-prefer-amharic-p)
1318 (message "Modify vowel to: [auiAEIoW\"] ")
1319 (message "Modify vowel to: [euiAEIoW\"] "))
1320 (setq vowel (read-char))
1330 ((= vowel ?a) (if (ethio-prefer-amharic-p) 160 163))
1331 ((= vowel ?\") (setq composite t) ch)
1334 ;; second standalone vowels
1336 (message "Modify vowel to: [euiaEIo\"] ")
1337 (setq vowel (read-char))
1346 ((= vowel ?\") (setq composite t) ch)
1349 ;; 12-form consonants, *W* form
1350 ((memq base '(72 88 136 176 192 272)) ; qW QW hW kW KW gW
1351 (message "Modify vowel to: [euiaE'\"] ")
1352 (setq vowel (read-char))
1355 ((= vowel ?u) (+ base 5))
1356 ((= vowel ?i) (+ base 2))
1357 ((= vowel ?a) (+ base 3))
1358 ((= vowel ?E) (+ base 4))
1359 ((= vowel ?') (+ base 5))
1360 ((= vowel ?\") (setq composite t) ch)
1363 ;; extended 12-form consonants, mWa bWa GWa fWa pWa
1365 (message "Modify vowel to: [euiaE'\"] ")
1366 (setq vowel (read-char))
1374 ((= vowel ?\") (setq composite t) ch)
1377 (message "Modify vowel to: [euiaE'\"] ")
1378 (setq vowel (read-char))
1386 ((= vowel ?\") (setq composite t) ch)
1389 (message "Modify vowel to: [euiaE'\"] ")
1390 (setq vowel (read-char))
1398 ((= vowel ?\") (setq composite t) ch)
1401 (message "Modify vowel to: [euiaE'\"] ")
1402 (setq vowel (read-char))
1410 ((= vowel ?\") (setq composite t) ch)
1413 (message "Modify vowel to: [euiaE'\"] ")
1414 (setq vowel (read-char))
1422 ((= vowel ?\") (setq composite t) ch)
1425 ;; extended 12-form consonatns, mW* bW* GW* fW* pW*
1426 ((memq base '(392 408 424 440)) ; *We *Wi *WE *W
1427 (message "Modify vowel to: [eiEau'\"] ")
1428 (setq vowel (read-char))
1430 ((= vowel ?e) (+ 392 modulo))
1431 ((= vowel ?i) (+ 408 modulo))
1432 ((= vowel ?E) (+ 424 modulo))
1434 ((= modulo 0) 31) ; mWa
1435 ((= modulo 1) 103) ; bWa
1436 ((= modulo 2) 287) ; GWa
1437 ((= modulo 3) 335) ; fWa
1438 ((= modulo 4) 343) ; pWa
1439 (t nil))) ; never reach here
1440 ((= vowel ?') (+ 440 modulo))
1441 ((= vowel ?u) (+ 440 modulo))
1442 ((= vowel ?\") (setq composite t) ch)
1445 ((and (>= ch 453) (<= ch 457)) ; wWe wWi wWa wWE wW
1446 (message "Modify vowel to: [eiaE'u\"] ")
1447 (setq vowel (read-char))
1455 ((= vowel ?\") (setq composite t) ch)
1458 ;; 7-form consonants, or
1459 ;; first 7 of 8-form consonants
1461 (message "Modify vowel to: [euiaE'o\"] ")
1462 (setq vowel (read-char))
1465 ((= vowel ?u) (+ base 1))
1466 ((= vowel ?i) (+ base 2))
1467 ((= vowel ?a) (+ base 3))
1468 ((= vowel ?E) (+ base 4))
1469 ((= vowel ?') (+ base 5))
1470 ((= vowel ?o) (+ base 6))
1471 ((= vowel ?\") (setq composite t) ch)
1480 ;; could not get new character
1482 (error "Invalid vowel"))
1484 ;; vowel changed on a composite Fidel
1489 (concat (char-to-string (ethio-ethiocode-to-char newch)) "\e$(3%s\e(B"))))
1491 ;; simple vowel modification
1494 (insert (ethio-ethiocode-to-char newch))))))
1496 (defun ethio-ethiocode-to-char (ethiocode)
1499 (+ (/ ethiocode 94) 33)
1500 (+ (mod ethiocode 94) 33)))
1502 (defun ethio-char-to-ethiocode (ch)
1503 (and (eq (char-charset ch) 'ethiopic)
1504 (let ((char-components (split-char ch)))
1505 (+ (* (- (nth 1 char-components) 33) 94)
1506 (- (nth 2 char-components) 33)))))
1509 ;; space replacement
1513 (defun ethio-replace-space (ch begin end)
1514 "Replace ASCII spaces with Ethiopic word separators in the region.
1516 In the specified region, replace word separators surrounded by two
1517 Ethiopic characters, depending on the first parameter CH, which should
1520 If CH = 1, word separator will be replaced with an ASCII space.
1521 If CH = 2, with two ASCII spaces.
1522 If CH = 3, with the Ethiopic colon-like word separator.
1524 The second and third parameters BEGIN and END specify the region."
1526 (interactive "*cReplace spaces to: 1 (sg col), 2 (dbl col), 3 (Ethiopic)\nr")
1527 (if (not (memq ch '(?1 ?2 ?3)))
1531 (narrow-to-region begin end)
1535 ;; an Ethiopic word separator --> an ASCII space
1536 (goto-char (point-min))
1537 (while (search-forward "\e$(3$h\e(B" nil t)
1538 (replace-match " " nil t))
1540 ;; two ASCII spaces between Ethiopic characters --> an ASCII space
1541 (goto-char (point-min))
1542 (while (re-search-forward "\\(\\ce\\) \\(\\ce\\)" nil t)
1543 (replace-match "\\1 \\2")
1544 (goto-char (match-beginning 2))))
1547 ;; An Ethiopic word separator --> two ASCII spaces
1548 (goto-char (point-min))
1549 (while (search-forward "\e$(3$h\e(B" nil t)
1550 (replace-match " "))
1552 ;; An ASCII space between Ethiopic characters --> two ASCII spaces
1553 (goto-char (point-min))
1554 (while (re-search-forward "\\(\\ce\\) \\(\\ce\\)" nil t)
1555 (replace-match "\\1 \\2")
1556 (goto-char (match-beginning 2))))
1559 ;; One or two ASCII spaces between Ethiopic characters
1560 ;; --> An Ethiopic word separator
1561 (goto-char (point-min))
1562 (while (re-search-forward "\\(\\ce\\) ?\\(\\ce\\)" nil t)
1563 (replace-match "\\1\e$(3$h\e(B\\2")
1564 (goto-char (match-beginning 2)))
1566 ;; Three or more ASCII spaces between Ethiopic characters
1567 ;; --> An Ethiopic word separator + (N - 2) ASCII spaces
1568 (goto-char (point-min))
1569 (while (re-search-forward "\\(\\ce\\) \\( *\\ce\\)" nil t)
1570 (replace-match "\\1\e$(3$h\e(B\\2")
1571 (goto-char (match-beginning 2))))))))
1578 (defun ethio-input-special-character (arg)
1579 "Allow the user to input special characters."
1580 (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")
1583 (insert "\e$(3%j\e(B"))
1585 (insert "\e$(3%k\e(B"))
1587 (insert "\e$(3%l\e(B"))
1589 (insert "\e$(3%m\e(B"))
1591 (insert "\e$(3%i\e(B"))
1599 (defconst ethio-fidel-to-tex-map
1600 [ "heG" "huG" "hiG" "haG" "hEG" "hG" "hoG" "" ;; 0 - 7
1601 "leG" "luG" "liG" "laG" "lEG" "lG" "loG" "lWaG" ;; 8
1602 "HeG" "HuG" "HiG" "HaG" "HEG" "HG" "HoG" "HWaG" ;; 16
1603 "meG" "muG" "miG" "maG" "mEG" "mG" "moG" "mWaG" ;; 24
1604 "sseG" "ssuG" "ssiG" "ssaG" "ssEG" "ssG" "ssoG" "ssWaG" ;; 32
1605 "reG" "ruG" "riG" "raG" "rEG" "rG" "roG" "rWaG" ;; 40
1606 "seG" "suG" "siG" "saG" "sEG" "sG" "soG" "sWaG" ;; 48
1607 "xeG" "xuG" "xiG" "xaG" "xEG" "xG" "xoG" "xWaG" ;; 56
1608 "qeG" "quG" "qiG" "qaG" "qEG" "qG" "qoG" "" ;; 64
1609 "qWeG" "" "qWiG" "qWaG" "qWEG" "qWG" "" "" ;; 72
1610 "QeG" "QuG" "QiG" "QaG" "QEG" "QG" "QoG" "" ;; 80
1611 "QWeG" "" "QWiG" "QWaG" "QWEG" "QWG" "" "" ;; 88
1612 "beG" "buG" "biG" "baG" "bEG" "bG" "boG" "bWaG" ;; 96
1613 "veG" "vuG" "viG" "vaG" "vEG" "vG" "voG" "vWaG" ;; 104
1614 "teG" "tuG" "tiG" "taG" "tEG" "tG" "toG" "tWaG" ;; 112
1615 "ceG" "cuG" "ciG" "caG" "cEG" "cG" "coG" "cWaG" ;; 120
1616 "hheG" "hhuG" "hhiG" "hhaG" "hhEG" "hhG" "hhoG" "" ;; 128
1617 "hWeG" "" "hWiG" "hWaG" "hWEG" "hWG" "" "" ;; 136
1618 "neG" "nuG" "niG" "naG" "nEG" "nG" "noG" "nWaG" ;; 144
1619 "NeG" "NuG" "NiG" "NaG" "NEG" "NG" "NoG" "NWaG" ;; 152
1620 "eG" "uG" "iG" "AG" "EG" "IG" "oG" "eaG" ;; 160
1621 "keG" "kuG" "kiG" "kaG" "kEG" "kG" "koG" "" ;; 168
1622 "kWeG" "" "kWiG" "kWaG" "kWEG" "kWG" "" "" ;; 176
1623 "KeG" "KuG" "KiG" "KaG" "KEG" "KG" "KoG" "" ;; 184
1624 "KWeG" "" "KWiG" "KWaG" "KWEG" "KWG" "" "" ;; 192
1625 "weG" "wuG" "wiG" "waG" "wEG" "wG" "woG" "" ;; 200
1626 "eeG" "uuG" "iiG" "aaG" "EEG" "IIG" "ooG" "" ;; 208
1627 "zeG" "zuG" "ziG" "zaG" "zEG" "zG" "zoG" "zWaG" ;; 216
1628 "ZeG" "ZuG" "ZiG" "ZaG" "ZEG" "ZG" "ZoG" "ZWaG" ;; 224
1629 "yeG" "yuG" "yiG" "yaG" "yEG" "yG" "yoG" "yWaG" ;; 232
1630 "deG" "duG" "diG" "daG" "dEG" "dG" "doG" "dWaG" ;; 240
1631 "DeG" "DuG" "DiG" "DaG" "DEG" "DG" "DoG" "DWaG" ;; 248
1632 "jeG" "juG" "jiG" "jaG" "jEG" "jG" "joG" "jWaG" ;; 256
1633 "geG" "guG" "giG" "gaG" "gEG" "gG" "goG" "" ;; 264
1634 "gWeG" "" "gWiG" "gWaG" "gWEG" "gWG" "" "" ;; 272
1635 "GeG" "GuG" "GiG" "GaG" "GEG" "GG" "GoG" "GWaG" ;; 280
1636 "TeG" "TuG" "TiG" "TaG" "TEG" "TG" "ToG" "TWaG" ;; 288
1637 "CeG" "CuG" "CiG" "CaG" "CEG" "CG" "CoG" "CWaG" ;; 296
1638 "PeG" "PuG" "PiG" "PaG" "PEG" "PG" "PoG" "PWaG" ;; 304
1639 "SeG" "SuG" "SiG" "SaG" "SEG" "SG" "SoG" "SWaG" ;; 312
1640 "SSeG" "SSuG" "SSiG" "SSaG" "SSEG" "SSG" "SSoG" "" ;; 320
1641 "feG" "fuG" "fiG" "faG" "fEG" "fG" "foG" "fWaG" ;; 328
1642 "peG" "puG" "piG" "paG" "pEG" "pG" "poG" "pWaG" ;; 336
1643 "mYaG" "rYaG" "fYaG" "" "" "" "" "" ;; 344
1644 "" "spaceG" "periodG" "commaG" ;; 352
1645 "semicolonG" "colonG" "precolonG" "oldqmarkG" ;; 356
1646 "pbreakG" "andG" "huletG" "sostG" "aratG" "amstG" "sadstG" "sabatG" ;; 360
1647 "smntG" "zeteNG" "asrG" "heyaG" "selasaG" "arbaG" "hemsaG" "slsaG" ;; 368
1648 "sebaG" "semanyaG" "zeTanaG" "metoG" "asrxiG" "" "" "" ;; 376
1649 "qqeG" "qquG" "qqiG" "qqaG" "qqEG" "qqG" "qqoG" "" ;; 384
1650 "mWeG" "bWeG" "GWeG" "fWeG" "pWeG" "" "" "" ;; 392
1651 "kkeG" "kkuG" "kkiG" "kkaG" "kkEG" "kkG" "kkoG" "" ;; 400
1652 "mWiG" "bWiG" "GWiG" "fWiG" "pWiG" "" "" "" ;; 408
1653 "XeG" "XuG" "GXiG" "XaG" "XEG" "XG" "XoG" "" ;; 416
1654 "mWEG" "bWEG" "GWEG" "fWEG" "pWEG" "" "" "" ;; 424
1655 "ggeG" "gguG" "ggiG" "ggaG" "ggEG" "ggG" "ggoG" "" ;; 432
1656 "mWG" "bWG" "GWG" "fWG" "pWG" "" "" "" ;; 440
1657 "ornamentG" "flandG" "iflandG" "africaG" ;; 448
1658 "iafricaG" "wWeG" "wWiG" "wWaG" ;; 452
1659 "wWEG" "wWG" "" "slaqG" "dotG" "lquoteG" "rquoteG" "qmarkG" ]) ;; 456
1662 ;; To make tex-to-fidel mapping.
1663 ;; The following code makes
1664 ;; (get 'ethio-tex-command-he 'ethio-fidel-char) ==> ?\e$(3!!\e(B
1669 (while (< i (length ethio-fidel-to-tex-map))
1670 (setq str (aref ethio-fidel-to-tex-map i))
1671 (if (not (string= str ""))
1673 (intern (concat "ethio-tex-command-" (aref ethio-fidel-to-tex-map i)))
1675 (ethio-ethiocode-to-char i)))
1679 (defun ethio-fidel-to-tex-buffer nil
1680 "Convert each fidel characters in the current buffer into a fidel-tex command.
1681 Each command is always surrounded by braces."
1683 (let ((buffer-read-only nil))
1685 ;; Isolated gemination marks need special treatement
1686 (goto-char (point-min))
1687 (while (search-forward "\e$(3%s\e(B" nil t)
1688 (replace-match "\\geminateG{}" t t))
1690 ;; First, decompose geminations
1691 ;; Here we assume that each composed character consists of
1692 ;; one Ethiopic character and the Ethiopic gemination mark.
1693 (decompose-region (point-min) (point-max))
1695 ;; Special treatment for geminated characters
1696 ;; The geminated character (la'') will be "\geminateG{\la}".
1697 (goto-char (point-min))
1698 (while (search-forward "\e$(3%s\e(B" nil t)
1699 (delete-backward-char 1)
1701 (insert "\\geminateG")
1704 ;; Ethiopic characters to TeX macros
1705 (goto-char (point-min))
1706 (while (re-search-forward "\\ce" nil t)
1709 (aref ethio-fidel-to-tex-map
1710 (prog1 (ethio-char-to-ethiocode (preceding-char))
1711 (backward-delete-char 1)))
1713 (goto-char (point-min))
1714 (set-buffer-modified-p nil)))
1717 (defun ethio-tex-to-fidel-buffer nil
1718 "Convert fidel-tex commands in the current buffer into fidel chars."
1720 (let ((buffer-read-only nil)
1723 ;; Special treatment for gemination
1724 ;; "\geminateG{\la}" or "\geminateG{{\la}}" will be "\la\e$(3%s\e(B"
1725 ;; "\geminateG{}" remains unchanged.
1726 (goto-char (point-min))
1727 (while (re-search-forward "\\\\geminateG{\\(\\\\[a-zA-Z]+\\)}" nil t)
1728 (replace-match "\\1\e$(3%s\e(B"))
1730 ;; TeX macros to Ethiopic characters
1731 (goto-char (point-min))
1732 (while (search-forward "\\" nil t)
1734 (skip-chars-forward "a-zA-Z")
1736 (get (intern (concat "ethio-tex-command-"
1737 (buffer-substring p (point))))
1741 (delete-region (1- p) (point)) ; don't forget the preceding "\"
1742 (if (and (= (preceding-char) ?{)
1743 (= (following-char) ?}))
1745 (backward-delete-char 1)
1749 ;; compose geminated characters
1750 (goto-char (point-min))
1751 (while (re-search-forward "\\ce\e$(3%s\e(B" nil 0)
1753 (save-excursion (backward-char 2) (point))
1756 ;; Now it's time to convert isolated gemination marks.
1757 (goto-char (point-min))
1758 (while (search-forward "\\geminateG{}" nil t)
1759 (replace-match "\e$(3%s\e(B"))
1761 (goto-char (point-min))
1762 (set-buffer-modified-p nil)))
1769 (defun ethio-fidel-to-java-buffer nil
1770 "Convert Ethiopic characters into the Java escape sequences.
1772 Each escape sequence is of the form \uXXXX, where XXXX is the
1773 character's codepoint (in hex) in Unicode.
1775 If `ethio-java-save-lowercase' is non-nil, use [0-9a-f].
1776 Otherwise, [0-9A-F]."
1779 ;; first, decompose geminations
1780 (decompose-region (point-min) (point-max))
1782 (goto-char (point-min))
1783 (while (re-search-forward "\\ce" nil t)
1784 (setq ucode (+ ?\x1200 (ethio-char-to-ethiocode (preceding-char))))
1785 (if (> ucode ?\x13bc)
1786 (setq ucode (+ ucode 59952)))
1787 (delete-backward-char 1)
1788 (if ethio-java-save-lowercase
1789 (insert (format "\\u%4x" ucode))
1790 (insert (upcase (format "\\u%4x" ucode)))))))
1793 (defun ethio-java-to-fidel-buffer nil
1794 "Convert the Java escape sequences into corresponding Ethiopic characters."
1796 (goto-char (point-min))
1797 (while (re-search-forward "\\\\u\\([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\\)" nil t)
1802 (buffer-substring (match-beginning 1) (match-end 1)))))
1804 ((and (>= ucode ?\x1200) (<= ucode ?\x13bc))
1806 (insert (ethio-ethiocode-to-char (- ucode ?\x1200))))
1807 ((and (>= ucode ?\xfdf1) (<= ucode ?\xfdff))
1809 (insert (ethio-ethiocode-to-char (- ucode 64560))))
1814 (goto-char (point-min))
1815 (while (re-search-forward "\\ce\e$(3%s\e(B" nil 0)
1817 (save-excursion (backward-char 2) (point))
1826 (defun ethio-find-file nil
1827 "Transcribe file content into Ethiopic dependig on filename suffix."
1830 ((string-match "\\.sera$" (buffer-file-name))
1832 (ethio-sera-to-fidel-buffer nil 'force)
1833 (set-buffer-modified-p nil)))
1835 ((string-match "\\.html$" (buffer-file-name))
1836 (let ((sera-being-called-by-w3 t))
1838 (ethio-sera-to-fidel-marker 'force)
1839 (goto-char (point-min))
1840 (while (re-search-forward "&[lr]aquote;" nil t)
1841 (if (= (char-after (1+ (match-beginning 0))) ?l)
1842 (replace-match "\e$(3%v\e(B")
1843 (replace-match "\e$(3%w\e(B")))
1844 (set-buffer-modified-p nil))))
1846 ((string-match "\\.tex$" (buffer-file-name))
1848 (ethio-tex-to-fidel-buffer)
1849 (set-buffer-modified-p nil)))
1851 ((string-match "\\.java$" (buffer-file-name))
1853 (ethio-java-to-fidel-buffer)
1854 (set-buffer-modified-p nil)))
1860 (defun ethio-write-file nil
1861 "Transcribe Ethiopic characters in ASCII depending on the file extension."
1864 ((string-match "\\.sera$" (buffer-file-name))
1866 (ethio-fidel-to-sera-buffer nil 'force)
1867 (goto-char (point-min))
1868 (ethio-record-user-preference)
1869 (set-buffer-modified-p nil)))
1871 ((string-match "\\.html$" (buffer-file-name))
1873 (let ((sera-being-called-by-w3 t)
1874 (lq (aref ethio-fidel-to-sera-map 461))
1875 (rq (aref ethio-fidel-to-sera-map 462)))
1876 (aset ethio-fidel-to-sera-map 461 "«te;")
1877 (aset ethio-fidel-to-sera-map 462 "»te;")
1878 (ethio-fidel-to-sera-marker 'force)
1879 (goto-char (point-min))
1880 (if (search-forward "<sera>" nil t)
1881 (ethio-record-user-preference))
1882 (aset ethio-fidel-to-sera-map 461 lq)
1883 (aset ethio-fidel-to-sera-map 462 rq)
1884 (set-buffer-modified-p nil))))
1886 ((string-match "\\.tex$" (buffer-file-name))
1888 (ethio-fidel-to-tex-buffer)
1889 (set-buffer-modified-p nil)))
1891 ((string-match "\\.java$" (buffer-file-name))
1893 (ethio-fidel-to-java-buffer)
1894 (set-buffer-modified-p nil)))
1899 (defun ethio-record-user-preference nil
1900 (if (looking-at "\\\\~\\(tir?\\|amh?\\) ")
1901 (goto-char (match-end 0))
1902 (insert (if (ethio-prefer-amharic-p) "\\~amh " "\\~tir ")))
1903 (insert (if ethio-use-colon-for-colon "\\~-: " "\\~`: ")
1904 (if ethio-use-three-dot-question "\\~`| " "\\~`? ")))
1907 ;; Ethiopic word separator vs. ASCII space
1910 (defvar ethio-prefer-ascii-space t)
1911 (make-variable-buffer-local 'ethio-prefer-ascii-space)
1913 (defun ethio-toggle-space nil
1914 "Toggle ASCII space and Ethiopic separator for keyboard input."
1916 (setq ethio-prefer-ascii-space
1917 (not ethio-prefer-ascii-space))
1918 (if (equal current-input-method "ethiopic")
1919 (setq current-input-method-title (quail-title)))
1920 (force-mode-line-update))
1922 (defun ethio-insert-space (arg)
1923 "Insert ASCII spaces or Ethiopic word separators depending on context.
1925 If the current word separator (indicated in mode-line) is the ASCII space,
1926 insert an ASCII space. With ARG, insert that many ASCII spaces.
1928 If the current word separator is the colon-like Ethiopic word
1929 separator and the point is preceded by `an Ethiopic punctuation mark
1930 followed by zero or more ASCII spaces', then insert also an ASCII
1931 space. With ARG, insert that many ASCII spaces.
1933 Otherwise, insert a colon-like Ethiopic word separator. With ARG, insert that
1934 many Ethiopic word separators."
1938 (ethio-prefer-ascii-space
1939 (insert-char 32 arg))
1941 (skip-chars-backward " ")
1942 (memq (preceding-char)
1943 '(?\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)))
1944 (insert-char 32 arg))
1946 (insert-char ?\e$(3$h\e(B arg))))
1948 (defun ethio-insert-ethio-space (arg)
1949 "Insert the Ethiopic word delimiter (the colon-like character).
1950 With ARG, insert that many delimiters."
1952 (insert-char ?\e$(3$h\e(B arg))
1955 ;; Ethiopic punctuation vs. ASCII punctuation
1958 (defvar ethio-prefer-ascii-punctuation nil)
1959 (make-variable-buffer-local 'ethio-prefer-ascii-punctuation)
1961 (defun ethio-toggle-punctuation nil
1962 "Toggle Ethiopic punctuations and ASCII punctuations for keyboard input."
1964 (setq ethio-prefer-ascii-punctuation
1965 (not ethio-prefer-ascii-punctuation))
1966 (let* ((keys '("." ".." "..." "," ",," ";" ";;" ":" "::" ":::" "*" "**"))
1968 (if ethio-prefer-ascii-punctuation
1969 '(?. [".."] ["..."] ?, [",,"] ?\; [";;"] ?: ["::"] [":::"] ?* ["**"])
1970 '(?\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))))
1972 (quail-defrule (car keys) (car puncs) "ethiopic")
1973 (setq keys (cdr keys)
1975 (if (equal current-input-method "ethiopic")
1976 (setq current-input-method-title (quail-title)))
1977 (force-mode-line-update)))
1983 (defun ethio-gemination nil
1984 "Compose the character before the point with the Ethiopic gemination mark.
1985 If the characater is already composed, decompose it and remove the gemination
1989 ((eq (char-charset (preceding-char)) 'ethiopic)
1990 (insert "\e$(3%s\e(B")
1992 (save-excursion (backward-char 2) (point))
1995 ((eq (char-charset (preceding-char)) 'leading-code-composition)
1997 (save-excursion (backward-char 1) (point))
1999 (delete-backward-char 1))
2004 (provide 'ethio-util)
2006 ;;; ethio-util.el ends here