(frame.o, keyboard.o, xdisp.o, xfaces.o): Depend on macgui.h.
[emacs.git] / lisp / language / ethio-util.el
blob8fd0b6b684c557c7bb9e7fc31ad8543b168129e6
1 ;;; ethio-util.el --- utilities for Ethiopic -*- coding: iso-2022-7bit; -*-
3 ;; Copyright (C) 1997, 1998, 2002, 2003, 2004, 2005, 2006, 2007, 2008
4 ;; Free Software Foundation, Inc.
5 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
6 ;; 2006, 2007, 2008
7 ;; National Institute of Advanced Industrial Science and Technology (AIST)
8 ;; Registration Number H14PRO021
10 ;; Keywords: mule, multilingual, Ethiopic
12 ;; This file is part of GNU Emacs.
14 ;; GNU Emacs is free software; you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation; either version 3, or (at your option)
17 ;; any later version.
19 ;; GNU Emacs is distributed in the hope that it will be useful,
20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 ;; GNU General Public License for more details.
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with GNU Emacs; see the file COPYING. If not, write to the
26 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27 ;; Boston, MA 02110-1301, USA.
29 ;; Author: TAKAHASHI Naoto <ntakahas@m17n.org>
31 ;;; Commentary:
33 ;;; Code:
35 (defvar rmail-current-message)
36 (defvar rmail-message-vector)
38 ;; Information for exiting Ethiopic environment.
39 (defvar exit-ethiopic-environment-data nil)
41 ;;;###autoload
42 (defun setup-ethiopic-environment-internal ()
43 (let ((key-bindings '((" " . ethio-insert-space)
44 ([?\S- ] . ethio-insert-ethio-space)
45 ([?\C-'] . ethio-gemination)
47 ;; these old bindings conflict
48 ;; with Emacs' binding policy
50 ;; ([f2] . ethio-toggle-space)
51 ;; ([S-f2] . ethio-replace-space) ; as requested
52 ;; ([f3] . ethio-toggle-punctuation)
53 ;; ([f4] . ethio-sera-to-fidel-buffer)
54 ;; ([S-f4] . ethio-sera-to-fidel-region)
55 ;; ([C-f4] . ethio-sera-to-fidel-mail-or-marker)
56 ;; ([f5] . ethio-fidel-to-sera-buffer)
57 ;; ([S-f5] . ethio-fidel-to-sera-region)
58 ;; ([C-f5] . ethio-fidel-to-sera-mail-or-marker)
59 ;; ([f6] . ethio-modify-vowel)
60 ;; ([f7] . ethio-replace-space)
61 ;; ([f8] . ethio-input-special-character)
63 ;; this is the rewritten bindings
65 ([f3] . ethio-fidel-to-sera-buffer)
66 ([S-f3] . ethio-fidel-to-sera-region)
67 ([C-f3] . ethio-fidel-to-sera-mail-or-marker)
68 ([f4] . ethio-sera-to-fidel-buffer)
69 ([S-f4] . ethio-sera-to-fidel-region)
70 ([C-f4] . ethio-sera-to-fidel-mail-or-marker)
71 ([S-f5] . ethio-toggle-punctuation)
72 ([S-f6] . ethio-modify-vowel)
73 ([S-f7] . ethio-replace-space)
74 ([S-f8] . ethio-input-special-character)
75 ([C-f9] . ethio-toggle-space)
76 ([S-f9] . ethio-replace-space) ; as requested
78 kb)
79 (while key-bindings
80 (setq kb (car (car key-bindings)))
81 (setq exit-ethiopic-environment-data
82 (cons (cons kb (global-key-binding kb))
83 exit-ethiopic-environment-data))
84 (global-set-key kb (cdr (car key-bindings)))
85 (setq key-bindings (cdr key-bindings))))
87 (add-hook 'quail-activate-hook 'ethio-select-a-translation)
88 (add-hook 'find-file-hook 'ethio-find-file)
89 (add-hook 'write-file-functions 'ethio-write-file)
90 (add-hook 'after-save-hook 'ethio-find-file))
92 (defun exit-ethiopic-environment ()
93 "Exit Ethiopic language environment."
94 (while exit-ethiopic-environment-data
95 (global-set-key (car (car exit-ethiopic-environment-data))
96 (cdr (car exit-ethiopic-environment-data)))
97 (setq exit-ethiopic-environment-data
98 (cdr exit-ethiopic-environment-data)))
100 (remove-hook 'quail-activate-hook 'ethio-select-a-translation)
101 (remove-hook 'find-file-hook 'ethio-find-file)
102 (remove-hook 'write-file-functions 'ethio-write-file)
103 (remove-hook 'after-save-hook 'ethio-find-file))
106 ;; ETHIOPIC UTILITY FUNCTIONS
109 ;; If the filename ends in ".sera", editing is done in fidel
110 ;; but file I/O is done in SERA.
112 ;; If the filename ends in ".java", editing is done in fidel
113 ;; but file I/O is done in the \uXXXX style, where XXXX is
114 ;; the Unicode codepoint for the Ethiopic character.
116 ;; If the filename ends in ".tex", editing is done in fidel
117 ;; but file I/O is done in EthioTeX format.
119 ;; To automatically convert Ethiopic text to SERA format when sending mail,
120 ;; (add-hook 'mail-send-hook 'ethio-fidel-to-sera-mail)
122 ;; To automatically convert SERA format to Ethiopic when receiving mail,
123 ;; (add-hook 'rmail-show-message-hook 'ethio-sera-to-fidel-mail)
125 ;; To automatically convert Ethiopic text to SERA format when posting news,
126 ;; (add-hook 'news-inews-hook 'ethio-fidel-to-sera-mail)
129 ;; users' preference
132 (defvar ethio-primary-language 'tigrigna
133 "*Symbol that defines the primary language in SERA --> FIDEL conversion.
134 The value should be one of: `tigrigna', `amharic' or `english'.")
136 (defvar ethio-secondary-language 'english
137 "*Symbol that defines the secondary language in SERA --> FIDEL conversion.
138 The value should be one of: `tigrigna', `amharic' or `english'.")
140 (defvar ethio-use-colon-for-colon nil
141 "*Non-nil means associate ASCII colon with Ethiopic colon.
142 If nil, associate ASCII colon with Ethiopic word separator, i.e., two
143 vertically stacked dots. All SERA <--> FIDEL converters refer this
144 variable.")
146 (defvar ethio-use-three-dot-question nil
147 "*Non-nil means associate ASCII question mark with Ethiopic old style question mark (three vertically stacked dots).
148 If nil, associate ASCII question mark with Ethiopic stylized question
149 mark. All SERA <--> FIDEL converters refer this variable.")
151 (defvar ethio-quote-vowel-always nil
152 "*Non-nil means always put an apostrophe before an isolated vowel (except at word initial) in FIDEL --> SERA conversion.
153 If nil, put an apostrophe only between a sixth-form consonant and an
154 isolated vowel.")
156 (defvar ethio-W-sixth-always nil
157 "*Non-nil means convert the Wu-form of a 12-form consonant to \"W'\" instead of \"Wu\" in FIDEL --> SERA conversion.")
159 (defvar ethio-numeric-reduction 0
160 "*Degree of reduction in converting Ethiopic digits into Arabic digits.
161 Should be 0, 1 or 2.
162 For example, ({10}{9}{100}{80}{7}) is converted into:
163 `10`9`100`80`7 if `ethio-numeric-reduction' is 0,
164 `109100807 if `ethio-numeric-reduction' is 1,
165 `10900807 if `ethio-numeric-reduction' is 2.")
167 (defvar ethio-implicit-period-conversion t
168 "*Non-nil means replacing the Ethiopic dot at the end of an Ethiopic sentence
169 with an Ethiopic full stop.")
171 (defvar ethio-java-save-lowercase nil
172 "*Non-nil means save Ethiopic characters in lowercase hex numbers to Java files.
173 If nil, use uppercases.")
176 ;; SERA to FIDEL
179 (defconst ethio-sera-to-fidel-table
181 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
182 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
183 ;;; SP
184 (" "
185 (?: (if ethio-use-colon-for-colon " \e$(3$l\e(B" "\e$(3$h\e(B")
186 (32 (if ethio-use-colon-for-colon " \e$(3$l\e(B " "\e$(3$h\e(B"))
187 (?- " \e$(3$m\e(B")
188 (?: " \e$(3$i\e(B")
189 (?| (if ethio-use-colon-for-colon " \e$(3$l\e(B|" " \e$(3$h\e(B|")
190 (?: " \e$(3$o\e(B"))))
192 ;;; ! " # $ % & '
193 nil nil nil nil nil nil ("" (?' "\e$(3%s\e(B"))
194 ;;; ( ) * + , - .
195 nil nil nil nil ("\e$(3$j\e(B") ("-" (?: "\e$(3$l\e(B")) ("\e$(3%u\e(B")
196 ;;; / 0 1 2 3 4 5 6 7 8 9
197 nil nil nil nil nil nil nil nil nil nil nil
198 ;;; :
199 ((if ethio-use-colon-for-colon "\e$(3$l\e(B" "\e$(3$h\e(B")
200 (32 (if ethio-use-colon-for-colon "\e$(3$l\e(B " "\e$(3$h\e(B"))
201 (?- "\e$(3$m\e(B")
202 (?: "\e$(3$i\e(B")
203 (?| (if ethio-use-colon-for-colon "\e$(3$l\e(B|" "\e$(3$h\e(B|")
204 (?: "\e$(3$o\e(B")))
205 ;;; ; < = >
206 ("\e$(3$k\e(B") ("<" (?< "\e$(3%v\e(B")) nil (">" (?> "\e$(3%w\e(B"))
207 ;;; ?
208 ((if ethio-use-three-dot-question "\e$(3$n\e(B" "\e$(3%x\e(B"))
209 ;;; @
211 ;;; A
212 ("\e$(3"f\e(B" (?2 "\e$(3#8\e(B"))
213 ;;; B
214 ("\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")
215 (?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")))
216 ;;; C
217 ("\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")
218 (?W "\e$(3$6\e(B" (?a "\e$(3$6\e(B")
219 (?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")))
220 ;;; D
221 ("\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")
222 (?W "\e$(3#d\e(B" (?a "\e$(3#d\e(B")
223 (?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")))
224 ;;; E
225 ("\e$(3"g\e(B" (?2 "\e$(3#9\e(B"))
226 ;;; F
227 ("\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")
228 (?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"))
229 (?Y "\e$(3$a\e(B" (?a "\e$(3$a\e(B")))
230 ;;; G
231 ("\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")
232 (?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")))
233 ;;; H
234 ("\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")
235 (?W "\e$(3!8\e(B" (?a "\e$(3!8\e(B")
236 (?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")))
237 ;;; I
238 ("\e$(3"h\e(B" (?2 "\e$(3#:\e(B"))
239 ;;; J
240 ("\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")
241 (?W "\e$(3#l\e(B" (?a "\e$(3#l\e(B")
242 (?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")))
243 ;;; K
244 ("\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")
245 (?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")))
246 ;;; L
247 ("\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")
248 (?W "\e$(3!0\e(B" (?a "\e$(3!0\e(B")
249 (?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 ;;; M
251 ("\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")
252 (?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"))
253 (?Y "\e$(3$_\e(B" (?a "\e$(3$_\e(B")))
254 ;;; N
255 ("\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")
256 (?W "\e$(3"b\e(B" (?a "\e$(3"b\e(B")
257 (?e "\e$(3"`%n\e(B") (?u "\e$(3"`%r\e(B") (?i "\e$(3"`%o\e(B") (?E "\e$(3"`%q\e(B")))
258 ;;; O
259 ("\e$(3"i\e(B" (?2 "\e$(3#;\e(B"))
260 ;;; P
261 ("\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")
262 (?W "\e$(3$>\e(B" (?a "\e$(3$>\e(B")
263 (?e "\e$(3$<%n\e(B") (?u "\e$(3$<%r\e(B") (?i "\e$(3$<%o\e(B") (?E "\e$(3$<%q\e(B")))
264 ;;; Q
265 ("\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")
266 (?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")))
267 ;;; R
268 ("\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")
269 (?W "\e$(3!P\e(B" (?a "\e$(3!P\e(B")
270 (?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"))
271 (?Y "\e$(3$`\e(B" (?a "\e$(3$`\e(B")))
272 ;;; S
273 ("\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")
274 (?W "\e$(3$F\e(B" (?a "\e$(3$F\e(B")
275 (?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"))
276 (?2 "\e$(3$L\e(B"
277 (?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")
278 (?W "\e$(3$F\e(B" (?a "\e$(3$F\e(B")
279 (?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"))))
280 ;;; T
281 ("\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")
282 (?W "\e$(3$.\e(B" (?a "\e$(3$.\e(B")
283 (?e "\e$(3$,%n\e(B") (?u "\e$(3$,%r\e(B") (?i "\e$(3$,%o\e(B") (?E "\e$(3$,%q\e(B")))
284 ;;; U
285 ("\e$(3"d\e(B" (?2 "\e$(3#6\e(B"))
286 ;;; V
287 ("\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")
288 (?W "\e$(3"2\e(B" (?a "\e$(3"2\e(B")
289 (?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")))
290 ;;; W
291 ("\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"))
292 ;;; X
293 ("\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"))
294 ;;; Y
295 ("\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")
296 (?W "\e$(3#T\e(B" (?a "\e$(3#T\e(B")
297 (?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")))
298 ;;; Z
299 ("\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")
300 (?W "\e$(3#L\e(B" (?a "\e$(3#L\e(B")
301 (?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")))
302 ;;; [ \ ] ^ _
303 nil nil nil nil nil
304 ;;; `
306 (?: "\e$(3$h\e(B")
307 (?? (if ethio-use-three-dot-question "\e$(3%x\e(B" "\e$(3$n\e(B"))
308 (?! "\e$(3%t\e(B")
309 (?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")
310 (?E "\e$(3#9\e(B") (?I "\e$(3#:\e(B") (?o "\e$(3#;\e(B") (?O "\e$(3#;\e(B")
311 (?g "\e$(3%^\e(B"
312 (?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"))
313 (?h "\e$(3"H\e(B"
314 (?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")
315 (?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")))
316 (?k "\e$(3%>\e(B"
317 (?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"))
318 (?s "\e$(3!F\e(B"
319 (?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")
320 (?W "\e$(3!H\e(B" (?a "\e$(3!H\e(B")
321 (?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")))
322 (?S "\e$(3$L\e(B"
323 (?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")
324 (?W "\e$(3$F\e(B" (?a "\e$(3$F\e(B")
325 (?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")))
326 (?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")))
327 ;;; a
328 ("\e$(3"f\e(B" (?2 "\e$(3#8\e(B"))
329 ;;; b
330 ("\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")
331 (?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")))
332 ;;; c
333 ("\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")
334 (?W "\e$(3"B\e(B" (?a "\e$(3"B\e(B")
335 (?e "\e$(3"@%n\e(B") (?u "\e$(3"@%r\e(B") (?i "\e$(3"@%o\e(B") (?E "\e$(3"@%q\e(B")))
336 ;;; d
337 ("\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")
338 (?W "\e$(3#\\e(B" (?a "\e$(3#\\e(B")
339 (?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")))
340 ;;; e
341 ("\e$(3"c\e(B" (?2 "\e$(3#5\e(B") (?a "\e$(3"j\e(B"))
342 ;;; f
343 ("\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")
344 (?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"))
345 (?Y "\e$(3$a\e(B" (?a "\e$(3$a\e(B")))
346 ;;; g
347 ("\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")
348 (?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"))
349 (?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")))
350 ;;; h
351 ("\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")
352 (?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"))
353 (?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")
354 (?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"))))
355 ;;; i
356 ("\e$(3"e\e(B" (?2 "\e$(3#7\e(B"))
357 ;;; j
358 ("\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")
359 (?W "\e$(3#l\e(B" (?a "\e$(3#l\e(B")
360 (?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")))
361 ;;; k
362 ("\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")
363 (?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"))
364 (?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")))
365 ;;; l
366 ("\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")
367 (?W "\e$(3!0\e(B" (?a "\e$(3!0\e(B")
368 (?e "\e$(3!.%n\e(B") (?u "\e$(3!.%r\e(B") (?i "\e$(3!.%o\e(B") (?E "\e$(3!.%q\e(B")))
369 ;;; m
370 ("\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")
371 (?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"))
372 (?Y "\e$(3$_\e(B" (?a "\e$(3$_\e(B")))
373 ;;; n
374 ("\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")
375 (?W "\e$(3"Z\e(B" (?a "\e$(3"Z\e(B")
376 (?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")))
377 ;;; o
378 ("\e$(3"i\e(B" (?2 "\e$(3#;\e(B"))
379 ;;; p
380 ("\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")
381 (?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")))
382 ;;; q
383 ("\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")
384 (?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"))
385 (?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")))
386 ;;; r
387 ("\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")
388 (?W "\e$(3!P\e(B" (?a "\e$(3!P\e(B")
389 (?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"))
390 (?Y "\e$(3$`\e(B" (?a "\e$(3$`\e(B")))
391 ;;; s
392 ("\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")
393 (?W "\e$(3!X\e(B" (?a "\e$(3!X\e(B")
394 (?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"))
395 (?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")
396 (?W "\e$(3!H\e(B" (?a "\e$(3!H\e(B")
397 (?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"))))
398 ;;; t
399 ("\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")
400 (?W "\e$(3":\e(B" (?a "\e$(3":\e(B")
401 (?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")))
402 ;;; u
403 ("\e$(3"d\e(B" (?2 "\e$(3#6\e(B"))
404 ;;; v
405 ("\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")
406 (?W "\e$(3"2\e(B" (?a "\e$(3"2\e(B")
407 (?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")))
408 ;;; w
409 ("\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")
410 (?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")))
411 ;;; x
412 ("\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")
413 (?W "\e$(3!`\e(B" (?a "\e$(3!`\e(B")
414 (?e "\e$(3!^%n\e(B") (?u "\e$(3!^%r\e(B") (?i "\e$(3!^%o\e(B") (?E "\e$(3!^%q\e(B")))
415 ;;; y
416 ("\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")
417 (?W "\e$(3#T\e(B" (?a "\e$(3#T\e(B")
418 (?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")))
419 ;;; z
420 ("\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")
421 (?W "\e$(3#D\e(B" (?a "\e$(3#D\e(B")
422 (?e "\e$(3#B%n\e(B") (?u "\e$(3#B%r\e(B") (?i "\e$(3#B%o\e(B") (?E "\e$(3#B%q\e(B")))
423 ;;; { | } ~ DEL
424 nil nil nil nil nil
427 ;; To avoid byte-compiler warnings. It should never be set globally.
428 (defvar ethio-sera-being-called-by-w3)
429 ;; This variable will be bound by some third-party package.
430 (defvar sera-being-called-by-w3)
432 ;;;###autoload
433 (defun ethio-sera-to-fidel-region (beg end &optional secondary force)
434 "Convert the characters in region from SERA to FIDEL.
435 The variable `ethio-primary-language' specifies the primary language
436 and `ethio-secondary-language' specifies the secondary.
438 If the 3rd parameter SECONDARY is given and non-nil, assume the region
439 begins with the secondary language; otherwise with the primary
440 language.
442 If the 4th parameter FORCE is given and non-nil, perform conversion
443 even if the buffer is read-only.
445 See also the descriptions of the variables
446 `ethio-use-colon-for-colon' and
447 `ethio-use-three-dot-question'."
449 (interactive "r\nP")
450 (save-restriction
451 (narrow-to-region beg end)
452 (ethio-sera-to-fidel-buffer secondary force)))
454 ;;;###autoload
455 (defun ethio-sera-to-fidel-buffer (&optional secondary force)
456 "Convert the current buffer from SERA to FIDEL.
458 The variable `ethio-primary-language' specifies the primary
459 language and `ethio-secondary-language' specifies the secondary.
461 If the 1st optional parameter SECONDARY is non-nil, assume the buffer
462 begins with the secondary language; otherwise with the primary
463 language.
465 If the 2nd optional parametr FORCE is non-nil, perform conversion even if the
466 buffer is read-only.
468 See also the descriptions of the variables
469 `ethio-use-colon-for-colon' and
470 `ethio-use-three-dot-question'."
472 (interactive "P")
474 (if (and buffer-read-only
475 (not force)
476 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
477 (error ""))
479 (let ((ethio-primary-language ethio-primary-language)
480 (ethio-secondary-language ethio-secondary-language)
481 (ethio-use-colon-for-colon ethio-use-colon-for-colon)
482 (ethio-use-three-dot-question ethio-use-three-dot-question)
483 ;; The above four variables may be changed temporary
484 ;; by tilde escapes during conversion. So we bind them to other
485 ;; variables but of the same names.
486 (buffer-read-only nil)
487 (case-fold-search nil)
488 current-language
489 next-language)
491 (setq current-language
492 (if secondary
493 ethio-secondary-language
494 ethio-primary-language))
496 (goto-char (point-min))
498 (while (not (eobp))
499 (setq next-language
500 (cond
501 ((eq current-language 'english)
502 (ethio-sera-to-fidel-english))
503 ((eq current-language 'amharic)
504 (ethio-sera-to-fidel-ethio 'amharic))
505 ((eq current-language 'tigrigna)
506 (ethio-sera-to-fidel-ethio 'tigrigna))
507 (t ; we don't know what to do
508 (ethio-sera-to-fidel-english))))
510 (setq current-language
511 (cond
513 ;; when language tag is explicitly specified
514 ((not (eq next-language 'toggle))
515 next-language)
517 ;; found a toggle in a primary language section
518 ((eq current-language ethio-primary-language)
519 ethio-secondary-language)
521 ;; found a toggle in a secondary, third, fourth, ...
522 ;; language section
524 ethio-primary-language))))
526 ;; If ethio-implicit-period-conversion is non-nil, the
527 ;; Ethiopic dot "\e$(3%u\e(B" at the end of an Ethiopic sentence is
528 ;; replaced with the Ethiopic full stop "\e$(3$i\e(B".
529 (if ethio-implicit-period-conversion
530 (progn
531 (goto-char (point-min))
532 (while (re-search-forward "\\([\e$(3!!\e(B-\e$(3$a%)\e(B-\e$(3%e%n\e(B-\e$(3%r%s\e(B]\\)\e$(3%u\e(B\\([ \t]\\)"
533 nil t)
534 (replace-match "\\1\e$(3$i\e(B\\2"))
535 (goto-char (point-min))
536 (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)
537 (replace-match "\\1\e$(3$i\e(B"))))
539 ;; gemination
540 (goto-char (point-min))
541 (while (re-search-forward "\\ce\e$(3%s\e(B" nil 0)
542 (compose-region
543 (save-excursion (backward-char 2) (point))
544 (point)))
547 (defun ethio-sera-to-fidel-english nil
548 "Handle English section in SERA to FIDEL conversion.
549 Conversion stops when a language switch is found. Then delete that
550 switch and return the name of the new language as a symbol."
551 (let ((new-language nil))
553 (while (and (not (eobp)) (null new-language))
554 (cond
556 ;; if no more "\", nothing to do.
557 ((not (search-forward "\\" nil 0)))
559 ;; hereafter point is put after a "\".
560 ;; first delete that "\", then check the following chars
562 ;; "\\" : leave the second "\"
563 ((progn
564 (delete-backward-char 1)
565 (= (following-char) ?\\ ))
566 (forward-char 1))
568 ;; "\ " : delete the following " "
569 ((= (following-char) 32)
570 (delete-char 1)
571 (setq new-language 'toggle))
573 ;; a language flag
574 ((setq new-language (ethio-process-language-flag)))
576 ;; just a "\" : not special sequence.
578 (setq new-language 'toggle))))
580 new-language))
582 (defun ethio-sera-to-fidel-ethio (lang)
583 "Handle Ethiopic section in SERA to FIDEL conversion.
584 Conversion stops when a language switch is found. Then delete that
585 switch and return the name of the new language as a symbol.
587 The parameter LANG (symbol, either `amharic' or `tigrigna') affects
588 the conversion of \"a\"."
590 (let ((new-language nil)
591 (verbatim nil)
592 start table table2 ch)
594 (setcar (aref ethio-sera-to-fidel-table ?a)
595 (if (eq lang 'tigrigna) "\e$(3"f\e(B" "\e$(3"c\e(B"))
597 (while (and (not (eobp)) (null new-language))
598 (setq ch (following-char))
599 (cond
601 ;; skip from "<" to ">" (or from "&" to ";") if in w3-mode
602 ((and (or (= ch ?<) (= ch ?&))
603 (or (and (boundp 'ethio-sera-being-called-by-w3)
604 ethio-sera-being-called-by-w3)
605 (and (boundp 'sera-being-called-by-w3)
606 sera-being-called-by-w3)))
607 (search-forward (if (= ch ?<) ">" ";")
608 nil 0))
610 ;; leave non-ASCII characters as they are
611 ((>= ch 128)
612 (forward-char 1))
614 ;; ethiopic digits
615 ((looking-at "`[1-9][0-9]*")
616 (delete-char 1)
617 (ethio-convert-digit))
619 ;; if not seeing a "\", do sera to fidel conversion
620 ((/= ch ?\\ )
621 (setq start (point))
622 (forward-char 1)
623 (setq table (aref ethio-sera-to-fidel-table ch))
624 (while (setq table2 (cdr (assoc (following-char) table)))
625 (setq table table2)
626 (forward-char 1))
627 (if (setq ch (car table))
628 (progn
629 (delete-region start (point))
630 (if (stringp ch)
631 (insert ch)
632 (insert (eval ch))))))
634 ;; if control reaches here, we must be looking at a "\"
636 ;; verbatim mode
637 (verbatim
638 (if (looking-at "\\\\~! ?")
640 ;; "\~!" or "\~! ". switch to non-verbatim mode
641 (progn
642 (replace-match "")
643 (setq verbatim nil))
645 ;; "\" but not "\~!" nor "\~! ". skip the current "\".
646 (forward-char 1)))
648 ;; hereafter, non-verbatim mode and looking at a "\"
649 ;; first delete that "\", then check the following chars.
651 ;; "\ " : delete the following " "
652 ((progn
653 (delete-char 1)
654 (setq ch (following-char))
655 (= ch 32))
656 (delete-char 1)
657 (setq new-language 'toggle))
659 ;; "\~!" or "\~! " : switch to verbatim mode
660 ((looking-at "~! ?")
661 (replace-match "")
662 (setq verbatim t))
664 ;; a language flag
665 ((setq new-language (ethio-process-language-flag)))
667 ;; "\~" but not "\~!" nor a language flag
668 ((= ch ?~)
669 (delete-char 1)
670 (ethio-tilde-escape))
672 ;; ASCII punctuation escape. skip
673 ((looking-at "\\(,\\|\\.\\|;\\|:\\|'\\|`\\|\?\\|\\\\\\)+")
674 (goto-char (match-end 0)))
676 ;; "\", but not special sequence
678 (setq new-language 'toggle))))
680 new-language))
682 (defun ethio-process-language-flag nil
683 "Process a language flag of the form \"~lang\" or \"~lang1~lang2\".
685 If looking at \"~lang1~lang2\", set `ethio-primary-language' and
686 `ethio-une-secondary-language' based on \"lang1\" and \"lang2\".
687 Then delete the language flag \"~lang1~lang2\" from the buffer.
688 Return value is the new primary language.
690 If looking at \"~lang\", delete that language flag \"~lang\" from the
691 buffer and return that language. In this case
692 `ethio-primary-language' and `ethio-uni-secondary-language'
693 are left unchanged.
695 If an unsupported language flag is found, just return nil without
696 changing anything."
698 (let (lang1 lang2)
699 (cond
701 ;; ~lang1~lang2
702 ((and (looking-at
703 "~\\([a-z][a-z][a-z]?\\)~\\([a-z][a-z][a-z]?\\)[ \t\n\\]")
704 (setq lang1
705 (ethio-flag-to-language
706 (buffer-substring (match-beginning 1) (match-end 1))))
707 (setq lang2
708 (ethio-flag-to-language
709 (buffer-substring (match-beginning 2) (match-end 2)))))
710 (setq ethio-primary-language lang1
711 ethio-secondary-language lang2)
712 (delete-region (point) (match-end 2))
713 (if (= (following-char) 32)
714 (delete-char 1))
715 ethio-primary-language)
717 ;; ~lang
718 ((and (looking-at "~\\([a-z][a-z][a-z]?\\)[ \t\n\\]")
719 (setq lang1
720 (ethio-flag-to-language
721 (buffer-substring (match-beginning 1) (match-end 1)))))
722 (delete-region (point) (match-end 1))
723 (if (= (following-char) 32)
724 (delete-char 1))
725 lang1)
727 ;; otherwise
729 nil))))
731 (defun ethio-tilde-escape nil
732 "Handle a SERA tilde escape in Ethiopic section and delete it.
733 Delete the escape even it is not recognized."
735 (let ((p (point)) command)
736 (skip-chars-forward "^ \t\n\\\\")
737 (setq command (buffer-substring p (point)))
738 (delete-region p (point))
739 (if (= (following-char) 32)
740 (delete-char 1))
742 (cond
744 ;; \~-:
745 ((string= command "-:")
746 (setq ethio-use-colon-for-colon t))
748 ;; \~`:
749 ((string= command "`:")
750 (setq ethio-use-colon-for-colon nil))
752 ;; \~?
753 ((string= command "?")
754 (setq ethio-use-three-dot-question nil))
756 ;; \~`|
757 ((string= command "`|")
758 (setq ethio-use-three-dot-question t))
760 ;; \~e
761 ((string= command "e")
762 (insert "\e$(3%j\e(B"))
764 ;; \~E
765 ((string= command "E")
766 (insert "\e$(3%k\e(B"))
768 ;; \~a
769 ((string= command "a")
770 (insert "\e$(3%l\e(B"))
772 ;; \~A
773 ((string= command "A")
774 (insert "\e$(3%m\e(B"))
776 ;; \~X
777 ((string= command "X")
778 (insert "\e$(3%i\e(B"))
780 ;; unsupported tilde escape
782 nil))))
784 (defun ethio-flag-to-language (flag)
785 (cond
786 ((or (string= flag "en") (string= flag "eng")) 'english)
787 ((or (string= flag "ti") (string= flag "tir")) 'tigrigna)
788 ((or (string= flag "am") (string= flag "amh")) 'amharic)
789 (t nil)))
791 (defun ethio-convert-digit nil
792 "Convert Arabic digits to Ethiopic digits."
793 (let (ch z)
794 (while (and (>= (setq ch (following-char)) ?1)
795 (<= ch ?9))
796 (delete-char 1)
798 ;; count up following zeros
799 (setq z 0)
800 (while (= (following-char) ?0)
801 (delete-char 1)
802 (setq z (1+ z)))
804 (cond
806 ;; first digit is 10, 20, ..., or 90
807 ((= (mod z 2) 1)
808 (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)))
809 (setq z (1- z)))
811 ;; first digit is 2, 3, ..., or 9
812 ((/= ch ?1)
813 (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))))
815 ;; single 1
816 ((= z 0)
817 (insert "\e$(3$p\e(B")))
819 ;; 100
820 (if (= (mod z 4) 2)
821 (insert "\e$(3%$\e(B"))
823 ;; 10000
824 (insert-char ?\e$(3%%\e(B (/ z 4)))))
826 ;;;###autoload
827 (defun ethio-sera-to-fidel-mail-or-marker (&optional arg)
828 "Execute `ethio-sera-to-fidel-mail' or `ethio-sera-to-fidel-marker' depending on the current major mode.
829 If in rmail-mode or in mail-mode, execute the former; otherwise latter."
831 (interactive "P")
832 (if (or (eq major-mode 'rmail-mode)
833 (eq major-mode 'mail-mode))
834 (ethio-sera-to-fidel-mail (prefix-numeric-value arg))
835 (ethio-sera-to-fidel-marker arg)))
837 ;;;###autoload
838 (defun ethio-sera-to-fidel-mail (&optional arg)
839 "Convert SERA to FIDEL to read/write mail and news.
841 If the buffer contains the markers \"<sera>\" and \"</sera>\",
842 convert the segments between them into FIDEL.
844 If invoked interactively and there is no marker, convert the subject field
845 and the body into FIDEL using `ethio-sera-to-fidel-region'."
847 (interactive "p")
848 (let ((buffer-read-only nil)
849 border)
850 (save-excursion
852 ;; follow RFC822 rules instead of looking for a fixed separator
853 (rfc822-goto-eoh)
854 (forward-line 1)
855 (setq border (point))
857 ;; note that the point is placed at the border
858 (if (or (re-search-forward "^<sera>$" nil t)
859 (progn
860 (goto-char (point-min))
861 (re-search-forward "^Subject: <sera>" border t)))
863 ;; there are markers
864 (progn
865 ;; we start with the body so that the border will not change
866 ;; use "^<sera>\n" instead of "^<sera>$" not to leave a blank line
867 (goto-char border)
868 (while (re-search-forward "^<sera>\n" nil t)
869 (replace-match "")
870 (ethio-sera-to-fidel-region
871 (point)
872 (progn
873 (if (re-search-forward "^</sera>\n" nil 0)
874 (replace-match ""))
875 (point))))
876 ;; now process the subject
877 (goto-char (point-min))
878 (if (re-search-forward "^Subject: <sera>" border t)
879 (ethio-sera-to-fidel-region
880 (progn (delete-backward-char 6) (point))
881 (progn
882 (if (re-search-forward "</sera>$" (line-end-position) 0)
883 (replace-match ""))
884 (point)))))
886 ;; in case there are no marks but invoked interactively
887 (if arg
888 (progn
889 (ethio-sera-to-fidel-region border (point-max))
890 (goto-char (point-min))
891 (if (re-search-forward "^Subject: " border t)
892 (ethio-sera-to-fidel-region (point) (line-end-position))))))
894 ;; adjust the rmail marker
895 (if (eq major-mode 'rmail-mode)
896 (set-marker
897 (aref rmail-message-vector (1+ rmail-current-message))
898 (point-max))))))
900 ;;;###autoload
901 (defun ethio-sera-to-fidel-marker (&optional force)
902 "Convert the regions surrounded by \"<sera>\" and \"</sera>\" from SERA to FIDEL.
903 Assume that each region begins with `ethio-primary-language'.
904 The markers \"<sera>\" and \"</sera>\" themselves are not deleted."
905 (interactive "P")
906 (if (and buffer-read-only
907 (not force)
908 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
909 (error ""))
910 (save-excursion
911 (goto-char (point-min))
912 (while (re-search-forward "<sera>" nil t)
913 (ethio-sera-to-fidel-region
914 (point)
915 (if (re-search-forward "</sera>" nil t)
916 (match-beginning 0)
917 (point-max))
919 'force))))
922 ;; FIDEL to SERA
925 (defconst ethio-fidel-to-sera-map
926 [ "he" "hu" "hi" "ha" "hE" "h" "ho" "" ;; 0 - 7
927 "le" "lu" "li" "la" "lE" "l" "lo" "lWa" ;; 8
928 "He" "Hu" "Hi" "Ha" "HE" "H" "Ho" "HWa" ;; 16
929 "me" "mu" "mi" "ma" "mE" "m" "mo" "mWa" ;; 24
930 "`se" "`su" "`si" "`sa" "`sE" "`s" "`so" "`sWa" ;; 32
931 "re" "ru" "ri" "ra" "rE" "r" "ro" "rWa" ;; 40
932 "se" "su" "si" "sa" "sE" "s" "so" "sWa" ;; 48
933 "xe" "xu" "xi" "xa" "xE" "x" "xo" "xWa" ;; 56
934 "qe" "qu" "qi" "qa" "qE" "q" "qo" "" ;; 64
935 "qWe" "" "qWi" "qWa" "qWE" "qW'" "" "" ;; 72
936 "Qe" "Qu" "Qi" "Qa" "QE" "Q" "Qo" "" ;; 80
937 "QWe" "" "QWi" "QWa" "QWE" "QW'" "" "" ;; 88
938 "be" "bu" "bi" "ba" "bE" "b" "bo" "bWa" ;; 96
939 "ve" "vu" "vi" "va" "vE" "v" "vo" "vWa" ;; 104
940 "te" "tu" "ti" "ta" "tE" "t" "to" "tWa" ;; 112
941 "ce" "cu" "ci" "ca" "cE" "c" "co" "cWa" ;; 120
942 "`he" "`hu" "`hi" "`ha" "`hE" "`h" "`ho" "" ;; 128
943 "hWe" "" "hWi" "hWa" "hWE" "hW'" "" "" ;; 136
944 "ne" "nu" "ni" "na" "nE" "n" "no" "nWa" ;; 144
945 "Ne" "Nu" "Ni" "Na" "NE" "N" "No" "NWa" ;; 152
946 "e" "u" "i" "A" "E" "I" "o" "ea" ;; 160
947 "ke" "ku" "ki" "ka" "kE" "k" "ko" "" ;; 168
948 "kWe" "" "kWi" "kWa" "kWE" "kW'" "" "" ;; 176
949 "Ke" "Ku" "Ki" "Ka" "KE" "K" "Ko" "" ;; 184
950 "KWe" "" "KWi" "KWa" "KWE" "KW'" "" "" ;; 192
951 "we" "wu" "wi" "wa" "wE" "w" "wo" "" ;; 200
952 "`e" "`u" "`i" "`a" "`E" "`I" "`o" "" ;; 208
953 "ze" "zu" "zi" "za" "zE" "z" "zo" "zWa" ;; 216
954 "Ze" "Zu" "Zi" "Za" "ZE" "Z" "Zo" "ZWa" ;; 224
955 "ye" "yu" "yi" "ya" "yE" "y" "yo" "yWa" ;; 232
956 "de" "du" "di" "da" "dE" "d" "do" "dWa" ;; 240
957 "De" "Du" "Di" "Da" "DE" "D" "Do" "DWa" ;; 248
958 "je" "ju" "ji" "ja" "jE" "j" "jo" "jWa" ;; 256
959 "ge" "gu" "gi" "ga" "gE" "g" "go" "" ;; 264
960 "gWe" "" "gWi" "gWa" "gWE" "gW'" "" "" ;; 272
961 "Ge" "Gu" "Gi" "Ga" "GE" "G" "Go" "GWa" ;; 280
962 "Te" "Tu" "Ti" "Ta" "TE" "T" "To" "TWa" ;; 288
963 "Ce" "Cu" "Ci" "Ca" "CE" "C" "Co" "CWa" ;; 296
964 "Pe" "Pu" "Pi" "Pa" "PE" "P" "Po" "PWa" ;; 304
965 "Se" "Su" "Si" "Sa" "SE" "S" "So" "SWa" ;; 312
966 "`Se" "`Su" "`Si" "`Sa" "`SE" "`S" "`So" "" ;; 320
967 "fe" "fu" "fi" "fa" "fE" "f" "fo" "fWa" ;; 328
968 "pe" "pu" "pi" "pa" "pE" "p" "po" "pWa" ;; 336
969 "mYa" "rYa" "fYa" "" "" "" "" "" ;; 344
970 " " " : " "::" "," ";" "-:" ":-" "`?" ;; 352
971 ":|:" "1" "2" "3" "4" "5" "6" "7" ;; 360
972 "8" "9" "10" "20" "30" "40" "50" "60" ;; 368
973 "70" "80" "90" "100" "10000" "" "" "" ;; 376
974 "`qe" "`qu" "`qi" "`qa" "`qE" "`q" "`qo" "" ;; 384
975 "mWe" "bWe" "GWe" "fWe" "pWe" "" "" "" ;; 392
976 "`ke" "`ku" "`ki" "`ka" "`kE" "`k" "`ko" "" ;; 400
977 "mWi" "bWi" "GWi" "fWi" "pWi" "" "" "" ;; 408
978 "Xe" "Xu" "Xi" "Xa" "XE" "X" "Xo" "" ;; 416
979 "mWE" "bWE" "GWE" "fWE" "pWE" "" "" "" ;; 424
980 "`ge" "`gu" "`gi" "`ga" "`gE" "`g" "`go" "" ;; 432
981 "mW'" "bW'" "GW'" "fW'" "pW'" "" "" "" ;; 440
982 "\\~X " "\\~e " "\\~E " "\\~a " "\\~A " "wWe" "wWi" "wWa" ;; 448
983 "wWE" "wW'" "''" "`!" "." "<<" ">>" "?" ]) ;; 456
985 (defun ethio-prefer-amharic-p nil
986 (or (eq ethio-primary-language 'amharic)
987 (and (not (eq ethio-primary-language 'tigrigna))
988 (eq ethio-secondary-language 'amharic))))
990 (defun ethio-language-to-flag (lang)
991 (cond
992 ((eq lang 'english) "eng")
993 ((eq lang 'tigrigna) "tir")
994 ((eq lang 'amharic) "amh")
995 (t "")))
997 ;;;###autoload
998 (defun ethio-fidel-to-sera-region (begin end &optional secondary force)
999 "Replace all the FIDEL characters in the region to the SERA format.
1000 The variable `ethio-primary-language' specifies the primary
1001 language and `ethio-secondary-language' specifies the secondary.
1003 If the 3dr parameter SECONDARY is given and non-nil, try to convert
1004 the region so that it begins in the secondary language; otherwise with
1005 the primary language.
1007 If the 4th parameter FORCE is given and non-nil, convert even if the
1008 buffer is read-only.
1010 See also the descriptions of the variables
1011 `ethio-use-colon-for-colon', `ethio-use-three-dot-question',
1012 `ethio-quote-vowel-always' and `ethio-numeric-reduction'."
1014 (interactive "r\nP")
1015 (save-restriction
1016 (narrow-to-region begin end)
1017 (ethio-fidel-to-sera-buffer secondary force)))
1019 ;;;###autoload
1020 (defun ethio-fidel-to-sera-buffer (&optional secondary force)
1021 "Replace all the FIDEL characters in the current buffer to the SERA format.
1022 The variable `ethio-primary-language' specifies the primary
1023 language and `ethio-secondary-language' specifies the secondary.
1025 If the 1st optional parameter SECONDARY is non-nil, try to convert the
1026 region so that it begins in the secondary language; otherwise with the
1027 primary language.
1029 If the 2nd optional parameter FORCE is non-nil, convert even if the
1030 buffer is read-only.
1032 See also the descriptions of the variables
1033 `ethio-use-colon-for-colon', `ethio-use-three-dot-question',
1034 `ethio-quote-vowel-always' and `ethio-numeric-reduction'."
1036 (interactive "P")
1037 (if (and buffer-read-only
1038 (not force)
1039 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
1040 (error ""))
1042 (let ((buffer-read-only nil)
1043 (case-fold-search nil)
1044 (lonec nil) ;; t means previous char was a lone consonant
1045 (fidel nil) ;; t means previous char was a FIDEL
1046 (digit nil) ;; t means previous char was an Ethiopic digit
1047 (flag (if (ethio-prefer-amharic-p) "\\~amh " "\\~tir "))
1048 mode ch)
1050 ;; user's preference in transcription
1051 (if ethio-use-colon-for-colon
1052 (progn
1053 (aset ethio-fidel-to-sera-map 353 "`:")
1054 (aset ethio-fidel-to-sera-map 357 ":"))
1055 (aset ethio-fidel-to-sera-map 353 " : ")
1056 (aset ethio-fidel-to-sera-map 357 "-:"))
1058 (if ethio-use-three-dot-question
1059 (progn
1060 (aset ethio-fidel-to-sera-map 359 "?")
1061 (aset ethio-fidel-to-sera-map 463 "`?"))
1062 (aset ethio-fidel-to-sera-map 359 "`?")
1063 (aset ethio-fidel-to-sera-map 463 "?"))
1065 (mapcar
1066 '(lambda (x)
1067 (aset (aref ethio-fidel-to-sera-map x)
1069 (if ethio-W-sixth-always ?' ?u)))
1070 '(77 93 141 181 197 277 440 441 442 443 444 457))
1072 (if (ethio-prefer-amharic-p)
1073 (aset ethio-fidel-to-sera-map 160 "a")
1074 (aset ethio-fidel-to-sera-map 160 "e"))
1075 ;; end of user's preference
1077 ;; first, decompose geminated characters
1078 (decompose-region (point-min) (point-max))
1080 ;; main conversion routine
1081 (goto-char (point-min))
1082 (while (not (eobp))
1083 (setq ch (following-char))
1085 (cond ; ethiopic, english, neutral
1087 ;; ethiopic character. must go to ethiopic mode, if not in it.
1088 ((eq (char-charset ch) 'ethiopic)
1089 (setq ch (ethio-char-to-ethiocode ch))
1090 (delete-char 1)
1091 (if (not (eq mode 'ethiopic))
1092 (progn
1093 (insert flag)
1094 (setq mode 'ethiopic)))
1096 (cond ; fidel, punc, digit
1098 ;; fidels
1099 ((or (<= ch 346) ; he - fYa
1100 (and (>= ch 384) (<= ch 444)) ; `qe - pw
1101 (and (>= ch 453) (<= ch 457))) ; wWe - wW
1102 (if (and (memq ch '(160 161 162 163 164 166 167)) ; (e - ea)
1103 (or lonec
1104 (and ethio-quote-vowel-always
1105 fidel)))
1106 (insert "'"))
1107 (insert (aref ethio-fidel-to-sera-map ch))
1108 (setq lonec (ethio-lone-consonant-p ch)
1109 fidel t
1110 digit nil))
1112 ;; punctuations or icons
1113 ((or (and (>= ch 353) (<= ch 360)) ; : - :|:
1114 (>= ch 458) ; '' - ?
1115 (and (>= ch 448) (<= ch 452))) ; \~X \~e \~E \~a \~A
1116 (insert (aref ethio-fidel-to-sera-map ch))
1117 (setq lonec nil
1118 fidel nil
1119 digit nil))
1121 ;; now CH must be an ethiopic digit
1123 ;; reduction = 0 or not preceded by Ethiopic number(s)
1124 ((or (= ethio-numeric-reduction 0)
1125 (not digit))
1126 (insert "`" (aref ethio-fidel-to-sera-map ch))
1127 (setq lonec nil
1128 fidel nil
1129 digit t))
1131 ;; reduction = 2 and following 10s, 100s, 10000s
1132 ((and (= ethio-numeric-reduction 2)
1133 (memq ch '(370 379 380)))
1134 (insert (substring (aref ethio-fidel-to-sera-map ch) 1))
1135 (setq lonec nil
1136 fidel nil
1137 digit t))
1139 ;; ordinary following digits
1141 (insert (aref ethio-fidel-to-sera-map ch))
1142 (setq lonec nil
1143 fidel nil
1144 digit t))))
1146 ;; english character. must go to english mode, if not in it.
1147 ((or (and (>= ch ?a) (<= ch ?z))
1148 (and (>= ch ?A) (<= ch ?Z)))
1149 (if (not (eq mode 'english))
1150 (insert "\\~eng "))
1151 (forward-char 1)
1152 (setq mode 'english
1153 lonec nil
1154 fidel nil
1155 digit nil))
1157 ;; ch can appear both in ethiopic section and in english section.
1160 ;; we must decide the mode, if not decided yet
1161 (if (null mode)
1162 (progn
1163 (setq mode
1164 (if secondary
1165 ethio-secondary-language
1166 ethio-primary-language))
1167 (if (eq mode 'english)
1168 (insert "\\~eng ")
1169 (insert flag)
1170 (setq mode 'ethiopic)))) ; tigrigna & amharic --> ethiopic
1172 (cond ; \ , eng-mode , punc , w3 , other
1174 ;; backslash is always quoted
1175 ((= ch ?\\ )
1176 (insert "\\")
1177 (forward-char 1))
1179 ;; nothing to do if in english mode
1180 ((eq mode 'english)
1181 (forward-char 1))
1183 ;; now we must be in ethiopic mode and seeing a non-"\"
1185 ;; ascii punctuations in ethiopic mode
1186 ((looking-at "[,.;:'`?]+")
1187 (insert "\\")
1188 (goto-char (1+ (match-end 0)))) ; because we inserted one byte (\)
1190 ;; skip from "<" to ">" (or from "&" to ";") if called from w3
1191 ((and (or (= ch ?<) (= ch ?&))
1192 (or (and (boundp 'ethio-sera-being-called-by-w3)
1193 ethio-sera-being-called-by-w3)
1194 (and (boundp 'sera-being-called-by-w3)
1195 sera-being-called-by-w3)))
1196 (search-forward (if (= ch ?<) ">" ";")
1197 nil 0))
1199 ;; neutral character. no need to quote. just skip it.
1201 (forward-char 1)))
1203 (setq lonec nil
1204 fidel nil
1205 digit nil)))
1206 ;; end of main conversion routine
1209 (defun ethio-lone-consonant-p (ethiocode)
1210 "If ETHIOCODE is an Ethiopic lone consonant, return t."
1211 (or (and (< ethiocode 344) (= (% ethiocode 8) 5))
1213 ;; `q `k X `g mW bW GW fW pW wW
1214 (memq ethiocode '(389 405 421 437 440 441 442 443 444 457))))
1216 ;;;###autoload
1217 (defun ethio-fidel-to-sera-mail-or-marker (&optional arg)
1218 "Execute `ethio-fidel-to-sera-mail' or `ethio-fidel-to-sera-marker' depending on the current major mode.
1219 If in rmail-mode or in mail-mode, execute the former; otherwise latter."
1221 (interactive "P")
1222 (if (or (eq major-mode 'rmail-mode)
1223 (eq major-mode 'mail-mode))
1224 (ethio-fidel-to-sera-mail)
1225 (ethio-fidel-to-sera-marker arg)))
1227 ;;;###autoload
1228 (defun ethio-fidel-to-sera-mail nil
1229 "Convert FIDEL to SERA to read/write mail and news.
1231 If the body contains at least one Ethiopic character,
1232 1) insert the string \"<sera>\" at the beginning of the body,
1233 2) insert \"</sera>\" at the end of the body, and
1234 3) convert the body into SERA.
1236 The very same procedure applies to the subject field, too."
1238 (interactive)
1239 (let ((buffer-read-only nil)
1240 border)
1241 (save-excursion
1243 ;; follow RFC822 rules instead of looking for a fixed separator
1244 (rfc822-goto-eoh)
1245 (forward-line 1)
1246 (setq border (point))
1248 ;; process body first not to change the border
1249 ;; note that the point is already at the border
1250 (if (re-search-forward "\\ce" nil t)
1251 (progn
1252 (ethio-fidel-to-sera-region border (point-max))
1253 (goto-char border)
1254 (insert "<sera>")
1255 (goto-char (point-max))
1256 (insert "</sera>")))
1258 ;; process subject
1259 (goto-char (point-min))
1260 (if (re-search-forward "^Subject: " border t)
1261 (let ((beg (point))
1262 (end (line-end-position)))
1263 (if (re-search-forward "\\ce" end t)
1264 (progn
1265 (ethio-fidel-to-sera-region beg end)
1266 (goto-char beg)
1267 (insert "<sera>")
1268 (end-of-line)
1269 (insert "</sera>")))))
1271 ;; adjust the rmail marker
1272 (if (eq major-mode 'rmail-mode)
1273 (set-marker
1274 (aref rmail-message-vector (1+ rmail-current-message))
1275 (point-max))))))
1277 ;;;###autoload
1278 (defun ethio-fidel-to-sera-marker (&optional force)
1279 "Convert the regions surrounded by \"<sera>\" and \"</sera>\" from FIDEL to SERA.
1280 The markers \"<sera>\" and \"</sera>\" themselves are not deleted."
1282 (interactive "P")
1283 (if (and buffer-read-only
1284 (not force)
1285 (not (y-or-n-p "Buffer is read-only. Force to convert? ")))
1286 (error ""))
1287 (save-excursion
1288 (goto-char (point-min))
1289 (while (re-search-forward "<sera>" nil t)
1290 (ethio-fidel-to-sera-region
1291 (point)
1292 (if (re-search-forward "</sera>" nil t)
1293 (match-beginning 0)
1294 (point-max))
1296 'force))))
1299 ;; vowel modification
1302 ;;;###autoload
1303 (defun ethio-modify-vowel nil
1304 "Modify the vowel of the FIDEL that is under the cursor."
1305 (interactive)
1306 (let ((ch (following-char))
1307 (composite nil) ; geminated or not
1308 newch base vowel modulo)
1310 (cond
1311 ;; in case of gemination
1312 ((eq (char-charset ch) 'composition)
1313 (setq ch (string-to-char (char-to-string ch))
1314 composite t))
1315 ;; neither gemination nor fidel
1316 ((not (eq (char-charset ch) 'ethiopic))
1317 (error "Not a valid character")))
1319 ;; set frequently referred character features
1320 (setq ch (ethio-char-to-ethiocode ch)
1321 base (* (/ ch 8) 8)
1322 modulo (% ch 8))
1324 (if (or (and (>= ch 344) (<= ch 380)) ;; mYa - `10000
1325 (and (>= ch 448) (<= ch 452)) ;; \~X - \~A
1326 (>= ch 458)) ;; private punctuations
1327 (error "Not a valid character"))
1329 (setq
1330 newch
1331 (cond
1333 ;; first standalone vowels
1334 ((= base 160)
1335 (if (ethio-prefer-amharic-p)
1336 (message "Modify vowel to: [auiAEIoW\"] ")
1337 (message "Modify vowel to: [euiAEIoW\"] "))
1338 (setq vowel (read-char))
1339 (cond
1340 ((= vowel ?e) 160)
1341 ((= vowel ?u) 161)
1342 ((= vowel ?i) 162)
1343 ((= vowel ?A) 163)
1344 ((= vowel ?E) 164)
1345 ((= vowel ?I) 165)
1346 ((= vowel ?o) 166)
1347 ((= vowel ?W) 167)
1348 ((= vowel ?a) (if (ethio-prefer-amharic-p) 160 163))
1349 ((= vowel ?\") (setq composite t) ch)
1350 (t nil)))
1352 ;; second standalone vowels
1353 ((= base 208)
1354 (message "Modify vowel to: [euiaEIo\"] ")
1355 (setq vowel (read-char))
1356 (cond
1357 ((= vowel ?e) 208)
1358 ((= vowel ?u) 209)
1359 ((= vowel ?i) 210)
1360 ((= vowel ?a) 211)
1361 ((= vowel ?E) 212)
1362 ((= vowel ?I) 213)
1363 ((= vowel ?o) 214)
1364 ((= vowel ?\") (setq composite t) ch)
1365 (t nil)))
1367 ;; 12-form consonants, *W* form
1368 ((memq base '(72 88 136 176 192 272)) ; qW QW hW kW KW gW
1369 (message "Modify vowel to: [euiaE'\"] ")
1370 (setq vowel (read-char))
1371 (cond
1372 ((= vowel ?e) base)
1373 ((= vowel ?u) (+ base 5))
1374 ((= vowel ?i) (+ base 2))
1375 ((= vowel ?a) (+ base 3))
1376 ((= vowel ?E) (+ base 4))
1377 ((= vowel ?') (+ base 5))
1378 ((= vowel ?\") (setq composite t) ch)
1379 (t nil)))
1381 ;; extended 12-form consonants, mWa bWa GWa fWa pWa
1382 ((= ch 31) ; mWa
1383 (message "Modify vowel to: [euiaE'\"] ")
1384 (setq vowel (read-char))
1385 (cond
1386 ((= vowel ?e) 392)
1387 ((= vowel ?u) 440)
1388 ((= vowel ?i) 408)
1389 ((= vowel ?a) ch)
1390 ((= vowel ?E) 424)
1391 ((= vowel ?') 440)
1392 ((= vowel ?\") (setq composite t) ch)
1393 (t nil)))
1394 ((= ch 103) ; bWa
1395 (message "Modify vowel to: [euiaE'\"] ")
1396 (setq vowel (read-char))
1397 (cond
1398 ((= vowel ?e) 393)
1399 ((= vowel ?u) 441)
1400 ((= vowel ?i) 409)
1401 ((= vowel ?a) ch)
1402 ((= vowel ?E) 425)
1403 ((= vowel ?') 441)
1404 ((= vowel ?\") (setq composite t) ch)
1405 (t nil)))
1406 ((= ch 287) ; GWa
1407 (message "Modify vowel to: [euiaE'\"] ")
1408 (setq vowel (read-char))
1409 (cond
1410 ((= vowel ?e) 394)
1411 ((= vowel ?u) 442)
1412 ((= vowel ?i) 410)
1413 ((= vowel ?a) ch)
1414 ((= vowel ?E) 426)
1415 ((= vowel ?') 442)
1416 ((= vowel ?\") (setq composite t) ch)
1417 (t nil)))
1418 ((= ch 335) ; fWa
1419 (message "Modify vowel to: [euiaE'\"] ")
1420 (setq vowel (read-char))
1421 (cond
1422 ((= vowel ?e) 395)
1423 ((= vowel ?u) 443)
1424 ((= vowel ?i) 411)
1425 ((= vowel ?a) ch)
1426 ((= vowel ?E) 427)
1427 ((= vowel ?') 443)
1428 ((= vowel ?\") (setq composite t) ch)
1429 (t nil)))
1430 ((= ch 343) ; pWa
1431 (message "Modify vowel to: [euiaE'\"] ")
1432 (setq vowel (read-char))
1433 (cond
1434 ((= vowel ?e) 396)
1435 ((= vowel ?u) 444)
1436 ((= vowel ?i) 412)
1437 ((= vowel ?a) ch)
1438 ((= vowel ?E) 428)
1439 ((= vowel ?') 444)
1440 ((= vowel ?\") (setq composite t) ch)
1441 (t nil)))
1443 ;; extended 12-form consonatns, mW* bW* GW* fW* pW*
1444 ((memq base '(392 408 424 440)) ; *We *Wi *WE *W
1445 (message "Modify vowel to: [eiEau'\"] ")
1446 (setq vowel (read-char))
1447 (cond
1448 ((= vowel ?e) (+ 392 modulo))
1449 ((= vowel ?i) (+ 408 modulo))
1450 ((= vowel ?E) (+ 424 modulo))
1451 ((= vowel ?a) (cond
1452 ((= modulo 0) 31) ; mWa
1453 ((= modulo 1) 103) ; bWa
1454 ((= modulo 2) 287) ; GWa
1455 ((= modulo 3) 335) ; fWa
1456 ((= modulo 4) 343) ; pWa
1457 (t nil))) ; never reach here
1458 ((= vowel ?') (+ 440 modulo))
1459 ((= vowel ?u) (+ 440 modulo))
1460 ((= vowel ?\") (setq composite t) ch)
1461 (t nil)))
1463 ((and (>= ch 453) (<= ch 457)) ; wWe wWi wWa wWE wW
1464 (message "Modify vowel to: [eiaE'u\"] ")
1465 (setq vowel (read-char))
1466 (cond
1467 ((= vowel ?e) 453)
1468 ((= vowel ?i) 454)
1469 ((= vowel ?a) 455)
1470 ((= vowel ?E) 456)
1471 ((= vowel ?') 457)
1472 ((= vowel ?u) 457)
1473 ((= vowel ?\") (setq composite t) ch)
1474 (t nil)))
1476 ;; 7-form consonants, or
1477 ;; first 7 of 8-form consonants
1478 ((<= modulo 6)
1479 (message "Modify vowel to: [euiaE'o\"] ")
1480 (setq vowel (read-char))
1481 (cond
1482 ((= vowel ?e) base)
1483 ((= vowel ?u) (+ base 1))
1484 ((= vowel ?i) (+ base 2))
1485 ((= vowel ?a) (+ base 3))
1486 ((= vowel ?E) (+ base 4))
1487 ((= vowel ?') (+ base 5))
1488 ((= vowel ?o) (+ base 6))
1489 ((= vowel ?\") (setq composite t) ch)
1490 (t nil)))
1492 ;; otherwise
1494 nil)))
1496 (cond
1498 ;; could not get new character
1499 ((null newch)
1500 (error "Invalid vowel"))
1502 ;; vowel changed on a composite Fidel
1503 (composite
1504 (delete-char 1)
1505 (insert
1506 (compose-string
1507 (concat (char-to-string (ethio-ethiocode-to-char newch)) "\e$(3%s\e(B"))))
1509 ;; simple vowel modification
1511 (delete-char 1)
1512 (insert (ethio-ethiocode-to-char newch))))))
1514 (defun ethio-ethiocode-to-char (ethiocode)
1515 (make-char
1516 'ethiopic
1517 (+ (/ ethiocode 94) 33)
1518 (+ (mod ethiocode 94) 33)))
1520 (defun ethio-char-to-ethiocode (ch)
1521 (and (eq (char-charset ch) 'ethiopic)
1522 (let ((char-components (split-char ch)))
1523 (+ (* (- (nth 1 char-components) 33) 94)
1524 (- (nth 2 char-components) 33)))))
1527 ;; space replacement
1530 ;;;###autoload
1531 (defun ethio-replace-space (ch begin end)
1532 "Replace ASCII spaces with Ethiopic word separators in the region.
1534 In the specified region, replace word separators surrounded by two
1535 Ethiopic characters, depending on the first parameter CH, which should
1536 be 1, 2, or 3.
1538 If CH = 1, word separator will be replaced with an ASCII space.
1539 If CH = 2, with two ASCII spaces.
1540 If CH = 3, with the Ethiopic colon-like word separator.
1542 The second and third parameters BEGIN and END specify the region."
1544 (interactive "*cReplace spaces to: 1 (sg col), 2 (dbl col), 3 (Ethiopic)\nr")
1545 (if (not (memq ch '(?1 ?2 ?3)))
1546 (error ""))
1547 (save-excursion
1548 (save-restriction
1549 (narrow-to-region begin end)
1551 (cond
1552 ((= ch ?1)
1553 ;; an Ethiopic word separator --> an ASCII space
1554 (goto-char (point-min))
1555 (while (search-forward "\e$(3$h\e(B" nil t)
1556 (replace-match " " nil t))
1558 ;; two ASCII spaces between Ethiopic characters --> an ASCII space
1559 (goto-char (point-min))
1560 (while (re-search-forward "\\(\\ce\\) \\(\\ce\\)" nil t)
1561 (replace-match "\\1 \\2")
1562 (goto-char (match-beginning 2))))
1564 ((= ch ?2)
1565 ;; An Ethiopic word separator --> two ASCII spaces
1566 (goto-char (point-min))
1567 (while (search-forward "\e$(3$h\e(B" nil t)
1568 (replace-match " "))
1570 ;; An ASCII space between Ethiopic characters --> two ASCII spaces
1571 (goto-char (point-min))
1572 (while (re-search-forward "\\(\\ce\\) \\(\\ce\\)" nil t)
1573 (replace-match "\\1 \\2")
1574 (goto-char (match-beginning 2))))
1577 ;; One or two ASCII spaces between Ethiopic characters
1578 ;; --> An Ethiopic word separator
1579 (goto-char (point-min))
1580 (while (re-search-forward "\\(\\ce\\) ?\\(\\ce\\)" nil t)
1581 (replace-match "\\1\e$(3$h\e(B\\2")
1582 (goto-char (match-beginning 2)))
1584 ;; Three or more ASCII spaces between Ethiopic characters
1585 ;; --> An Ethiopic word separator + (N - 2) ASCII spaces
1586 (goto-char (point-min))
1587 (while (re-search-forward "\\(\\ce\\) \\( *\\ce\\)" nil t)
1588 (replace-match "\\1\e$(3$h\e(B\\2")
1589 (goto-char (match-beginning 2))))))))
1592 ;; special icons
1595 ;;;###autoload
1596 (defun ethio-input-special-character (arg)
1597 "Allow the user to input special characters."
1598 (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")
1599 (cond
1600 ((= arg ?1)
1601 (insert "\e$(3%j\e(B"))
1602 ((= arg ?2)
1603 (insert "\e$(3%k\e(B"))
1604 ((= arg ?3)
1605 (insert "\e$(3%l\e(B"))
1606 ((= arg ?4)
1607 (insert "\e$(3%m\e(B"))
1608 ((= arg ?5)
1609 (insert "\e$(3%i\e(B"))
1611 (error ""))))
1614 ;; TeX support
1617 (defconst ethio-fidel-to-tex-map
1618 [ "heG" "huG" "hiG" "haG" "hEG" "hG" "hoG" "" ;; 0 - 7
1619 "leG" "luG" "liG" "laG" "lEG" "lG" "loG" "lWaG" ;; 8
1620 "HeG" "HuG" "HiG" "HaG" "HEG" "HG" "HoG" "HWaG" ;; 16
1621 "meG" "muG" "miG" "maG" "mEG" "mG" "moG" "mWaG" ;; 24
1622 "sseG" "ssuG" "ssiG" "ssaG" "ssEG" "ssG" "ssoG" "ssWaG" ;; 32
1623 "reG" "ruG" "riG" "raG" "rEG" "rG" "roG" "rWaG" ;; 40
1624 "seG" "suG" "siG" "saG" "sEG" "sG" "soG" "sWaG" ;; 48
1625 "xeG" "xuG" "xiG" "xaG" "xEG" "xG" "xoG" "xWaG" ;; 56
1626 "qeG" "quG" "qiG" "qaG" "qEG" "qG" "qoG" "" ;; 64
1627 "qWeG" "" "qWiG" "qWaG" "qWEG" "qWG" "" "" ;; 72
1628 "QeG" "QuG" "QiG" "QaG" "QEG" "QG" "QoG" "" ;; 80
1629 "QWeG" "" "QWiG" "QWaG" "QWEG" "QWG" "" "" ;; 88
1630 "beG" "buG" "biG" "baG" "bEG" "bG" "boG" "bWaG" ;; 96
1631 "veG" "vuG" "viG" "vaG" "vEG" "vG" "voG" "vWaG" ;; 104
1632 "teG" "tuG" "tiG" "taG" "tEG" "tG" "toG" "tWaG" ;; 112
1633 "ceG" "cuG" "ciG" "caG" "cEG" "cG" "coG" "cWaG" ;; 120
1634 "hheG" "hhuG" "hhiG" "hhaG" "hhEG" "hhG" "hhoG" "" ;; 128
1635 "hWeG" "" "hWiG" "hWaG" "hWEG" "hWG" "" "" ;; 136
1636 "neG" "nuG" "niG" "naG" "nEG" "nG" "noG" "nWaG" ;; 144
1637 "NeG" "NuG" "NiG" "NaG" "NEG" "NG" "NoG" "NWaG" ;; 152
1638 "eG" "uG" "iG" "AG" "EG" "IG" "oG" "eaG" ;; 160
1639 "keG" "kuG" "kiG" "kaG" "kEG" "kG" "koG" "" ;; 168
1640 "kWeG" "" "kWiG" "kWaG" "kWEG" "kWG" "" "" ;; 176
1641 "KeG" "KuG" "KiG" "KaG" "KEG" "KG" "KoG" "" ;; 184
1642 "KWeG" "" "KWiG" "KWaG" "KWEG" "KWG" "" "" ;; 192
1643 "weG" "wuG" "wiG" "waG" "wEG" "wG" "woG" "" ;; 200
1644 "eeG" "uuG" "iiG" "aaG" "EEG" "IIG" "ooG" "" ;; 208
1645 "zeG" "zuG" "ziG" "zaG" "zEG" "zG" "zoG" "zWaG" ;; 216
1646 "ZeG" "ZuG" "ZiG" "ZaG" "ZEG" "ZG" "ZoG" "ZWaG" ;; 224
1647 "yeG" "yuG" "yiG" "yaG" "yEG" "yG" "yoG" "yWaG" ;; 232
1648 "deG" "duG" "diG" "daG" "dEG" "dG" "doG" "dWaG" ;; 240
1649 "DeG" "DuG" "DiG" "DaG" "DEG" "DG" "DoG" "DWaG" ;; 248
1650 "jeG" "juG" "jiG" "jaG" "jEG" "jG" "joG" "jWaG" ;; 256
1651 "geG" "guG" "giG" "gaG" "gEG" "gG" "goG" "" ;; 264
1652 "gWeG" "" "gWiG" "gWaG" "gWEG" "gWG" "" "" ;; 272
1653 "GeG" "GuG" "GiG" "GaG" "GEG" "GG" "GoG" "GWaG" ;; 280
1654 "TeG" "TuG" "TiG" "TaG" "TEG" "TG" "ToG" "TWaG" ;; 288
1655 "CeG" "CuG" "CiG" "CaG" "CEG" "CG" "CoG" "CWaG" ;; 296
1656 "PeG" "PuG" "PiG" "PaG" "PEG" "PG" "PoG" "PWaG" ;; 304
1657 "SeG" "SuG" "SiG" "SaG" "SEG" "SG" "SoG" "SWaG" ;; 312
1658 "SSeG" "SSuG" "SSiG" "SSaG" "SSEG" "SSG" "SSoG" "" ;; 320
1659 "feG" "fuG" "fiG" "faG" "fEG" "fG" "foG" "fWaG" ;; 328
1660 "peG" "puG" "piG" "paG" "pEG" "pG" "poG" "pWaG" ;; 336
1661 "mYaG" "rYaG" "fYaG" "" "" "" "" "" ;; 344
1662 "" "spaceG" "periodG" "commaG" ;; 352
1663 "semicolonG" "colonG" "precolonG" "oldqmarkG" ;; 356
1664 "pbreakG" "andG" "huletG" "sostG" "aratG" "amstG" "sadstG" "sabatG" ;; 360
1665 "smntG" "zeteNG" "asrG" "heyaG" "selasaG" "arbaG" "hemsaG" "slsaG" ;; 368
1666 "sebaG" "semanyaG" "zeTanaG" "metoG" "asrxiG" "" "" "" ;; 376
1667 "qqeG" "qquG" "qqiG" "qqaG" "qqEG" "qqG" "qqoG" "" ;; 384
1668 "mWeG" "bWeG" "GWeG" "fWeG" "pWeG" "" "" "" ;; 392
1669 "kkeG" "kkuG" "kkiG" "kkaG" "kkEG" "kkG" "kkoG" "" ;; 400
1670 "mWiG" "bWiG" "GWiG" "fWiG" "pWiG" "" "" "" ;; 408
1671 "XeG" "XuG" "GXiG" "XaG" "XEG" "XG" "XoG" "" ;; 416
1672 "mWEG" "bWEG" "GWEG" "fWEG" "pWEG" "" "" "" ;; 424
1673 "ggeG" "gguG" "ggiG" "ggaG" "ggEG" "ggG" "ggoG" "" ;; 432
1674 "mWG" "bWG" "GWG" "fWG" "pWG" "" "" "" ;; 440
1675 "ornamentG" "flandG" "iflandG" "africaG" ;; 448
1676 "iafricaG" "wWeG" "wWiG" "wWaG" ;; 452
1677 "wWEG" "wWG" "" "slaqG" "dotG" "lquoteG" "rquoteG" "qmarkG" ]) ;; 456
1680 ;; To make tex-to-fidel mapping.
1681 ;; The following code makes
1682 ;; (get 'ethio-tex-command-he 'ethio-fidel-char) ==> ?\e$(3!!\e(B
1683 ;; etc.
1686 (let ((i 0) str)
1687 (while (< i (length ethio-fidel-to-tex-map))
1688 (setq str (aref ethio-fidel-to-tex-map i))
1689 (if (not (string= str ""))
1690 (put
1691 (intern (concat "ethio-tex-command-" (aref ethio-fidel-to-tex-map i)))
1692 'ethio-fidel-char
1693 (ethio-ethiocode-to-char i)))
1694 (setq i (1+ i))))
1696 ;;;###autoload
1697 (defun ethio-fidel-to-tex-buffer nil
1698 "Convert each fidel characters in the current buffer into a fidel-tex command.
1699 Each command is always surrounded by braces."
1700 (interactive)
1701 (let ((buffer-read-only nil))
1703 ;; Isolated gemination marks need special treatement
1704 (goto-char (point-min))
1705 (while (search-forward "\e$(3%s\e(B" nil t)
1706 (replace-match "\\geminateG{}" t t))
1708 ;; First, decompose geminations
1709 ;; Here we assume that each composed character consists of
1710 ;; one Ethiopic character and the Ethiopic gemination mark.
1711 (decompose-region (point-min) (point-max))
1713 ;; Special treatment for geminated characters
1714 ;; The geminated character (la'') will be "\geminateG{\la}".
1715 (goto-char (point-min))
1716 (while (search-forward "\e$(3%s\e(B" nil t)
1717 (delete-backward-char 1)
1718 (backward-char 1)
1719 (insert "\\geminateG")
1720 (forward-char 1))
1722 ;; Ethiopic characters to TeX macros
1723 (goto-char (point-min))
1724 (while (re-search-forward "\\ce" nil t)
1725 (insert
1726 "{\\"
1727 (aref ethio-fidel-to-tex-map
1728 (prog1 (ethio-char-to-ethiocode (preceding-char))
1729 (backward-delete-char 1)))
1730 "}"))
1731 (goto-char (point-min))
1732 (set-buffer-modified-p nil)))
1734 ;;;###autoload
1735 (defun ethio-tex-to-fidel-buffer nil
1736 "Convert fidel-tex commands in the current buffer into fidel chars."
1737 (interactive)
1738 (let ((buffer-read-only nil)
1739 (p) (ch))
1741 ;; Special treatment for gemination
1742 ;; "\geminateG{\la}" or "\geminateG{{\la}}" will be "\la\e$(3%s\e(B"
1743 ;; "\geminateG{}" remains unchanged.
1744 (goto-char (point-min))
1745 (while (re-search-forward "\\\\geminateG{\\(\\\\[a-zA-Z]+\\)}" nil t)
1746 (replace-match "\\1\e$(3%s\e(B"))
1748 ;; TeX macros to Ethiopic characters
1749 (goto-char (point-min))
1750 (while (search-forward "\\" nil t)
1751 (setq p (point))
1752 (skip-chars-forward "a-zA-Z")
1753 (setq ch
1754 (get (intern (concat "ethio-tex-command-"
1755 (buffer-substring p (point))))
1756 'ethio-fidel-char))
1757 (if ch
1758 (progn
1759 (delete-region (1- p) (point)) ; don't forget the preceding "\"
1760 (if (and (= (preceding-char) ?{)
1761 (= (following-char) ?}))
1762 (progn
1763 (backward-delete-char 1)
1764 (delete-char 1)))
1765 (insert ch))))
1767 ;; compose geminated characters
1768 (goto-char (point-min))
1769 (while (re-search-forward "\\ce\e$(3%s\e(B" nil 0)
1770 (compose-region
1771 (save-excursion (backward-char 2) (point))
1772 (point)))
1774 ;; Now it's time to convert isolated gemination marks.
1775 (goto-char (point-min))
1776 (while (search-forward "\\geminateG{}" nil t)
1777 (replace-match "\e$(3%s\e(B"))
1779 (goto-char (point-min))
1780 (set-buffer-modified-p nil)))
1783 ;; Java support
1786 ;;;###autoload
1787 (defun ethio-fidel-to-java-buffer nil
1788 "Convert Ethiopic characters into the Java escape sequences.
1790 Each escape sequence is of the form \\uXXXX, where XXXX is the
1791 character's codepoint (in hex) in Unicode.
1793 If `ethio-java-save-lowercase' is non-nil, use [0-9a-f].
1794 Otherwise, [0-9A-F]."
1795 (let ((ucode))
1797 ;; first, decompose geminations
1798 (decompose-region (point-min) (point-max))
1800 (goto-char (point-min))
1801 (while (re-search-forward "\\ce" nil t)
1802 (setq ucode (+ ?\x1200 (ethio-char-to-ethiocode (preceding-char))))
1803 (if (> ucode ?\x13bc)
1804 (setq ucode (+ ucode 59952)))
1805 (delete-backward-char 1)
1806 (if ethio-java-save-lowercase
1807 (insert (format "\\u%4x" ucode))
1808 (insert (upcase (format "\\u%4x" ucode)))))))
1810 ;;;###autoload
1811 (defun ethio-java-to-fidel-buffer nil
1812 "Convert the Java escape sequences into corresponding Ethiopic characters."
1813 (let ((ucode))
1814 (goto-char (point-min))
1815 (while (re-search-forward "\\\\u\\([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\\)" nil t)
1816 (setq ucode
1817 (read
1818 (concat
1819 "?\\x"
1820 (buffer-substring (match-beginning 1) (match-end 1)))))
1821 (cond
1822 ((and (>= ucode ?\x1200) (<= ucode ?\x13bc))
1823 (replace-match "")
1824 (insert (ethio-ethiocode-to-char (- ucode ?\x1200))))
1825 ((and (>= ucode ?\xfdf1) (<= ucode ?\xfdff))
1826 (replace-match "")
1827 (insert (ethio-ethiocode-to-char (- ucode 64560))))
1829 nil)))
1831 ;; gemination
1832 (goto-char (point-min))
1833 (while (re-search-forward "\\ce\e$(3%s\e(B" nil 0)
1834 (compose-region
1835 (save-excursion (backward-char 2) (point))
1836 (point)))
1840 ;; file I/O hooks
1843 ;;;###autoload
1844 (defun ethio-find-file nil
1845 "Transcribe file content into Ethiopic depending on filename suffix."
1846 (cond
1848 ((string-match "\\.sera$" (buffer-file-name))
1849 (save-excursion
1850 (ethio-sera-to-fidel-buffer nil 'force)
1851 (set-buffer-modified-p nil)))
1853 ((string-match "\\.html$" (buffer-file-name))
1854 (let ((ethio-sera-being-called-by-w3 t))
1855 (save-excursion
1856 (ethio-sera-to-fidel-marker 'force)
1857 (goto-char (point-min))
1858 (while (re-search-forward "&[lr]aquote;" nil t)
1859 (if (= (char-after (1+ (match-beginning 0))) ?l)
1860 (replace-match "\e$(3%v\e(B")
1861 (replace-match "\e$(3%w\e(B")))
1862 (set-buffer-modified-p nil))))
1864 ((string-match "\\.tex$" (buffer-file-name))
1865 (save-excursion
1866 (ethio-tex-to-fidel-buffer)
1867 (set-buffer-modified-p nil)))
1869 ((string-match "\\.java$" (buffer-file-name))
1870 (save-excursion
1871 (ethio-java-to-fidel-buffer)
1872 (set-buffer-modified-p nil)))
1875 nil)))
1877 ;;;###autoload
1878 (defun ethio-write-file nil
1879 "Transcribe Ethiopic characters in ASCII depending on the file extension."
1880 (cond
1882 ((string-match "\\.sera$" (buffer-file-name))
1883 (save-excursion
1884 (ethio-fidel-to-sera-buffer nil 'force)
1885 (goto-char (point-min))
1886 (ethio-record-user-preference)
1887 (set-buffer-modified-p nil)))
1889 ((string-match "\\.html$" (buffer-file-name))
1890 (save-excursion
1891 (let ((ethio-sera-being-called-by-w3 t)
1892 (lq (aref ethio-fidel-to-sera-map 461))
1893 (rq (aref ethio-fidel-to-sera-map 462)))
1894 (aset ethio-fidel-to-sera-map 461 "&laquote;")
1895 (aset ethio-fidel-to-sera-map 462 "&raquote;")
1896 (ethio-fidel-to-sera-marker 'force)
1897 (goto-char (point-min))
1898 (if (search-forward "<sera>" nil t)
1899 (ethio-record-user-preference))
1900 (aset ethio-fidel-to-sera-map 461 lq)
1901 (aset ethio-fidel-to-sera-map 462 rq)
1902 (set-buffer-modified-p nil))))
1904 ((string-match "\\.tex$" (buffer-file-name))
1905 (save-excursion
1906 (ethio-fidel-to-tex-buffer)
1907 (set-buffer-modified-p nil)))
1909 ((string-match "\\.java$" (buffer-file-name))
1910 (save-excursion
1911 (ethio-fidel-to-java-buffer)
1912 (set-buffer-modified-p nil)))
1915 nil)))
1917 (defun ethio-record-user-preference nil
1918 (if (looking-at "\\\\~\\(tir?\\|amh?\\) ")
1919 (goto-char (match-end 0))
1920 (insert (if (ethio-prefer-amharic-p) "\\~amh " "\\~tir ")))
1921 (insert (if ethio-use-colon-for-colon "\\~-: " "\\~`: ")
1922 (if ethio-use-three-dot-question "\\~`| " "\\~`? ")))
1925 ;; Ethiopic word separator vs. ASCII space
1928 (defvar ethio-prefer-ascii-space t)
1929 (make-variable-buffer-local 'ethio-prefer-ascii-space)
1931 (defun ethio-toggle-space nil
1932 "Toggle ASCII space and Ethiopic separator for keyboard input."
1933 (interactive)
1934 (setq ethio-prefer-ascii-space
1935 (not ethio-prefer-ascii-space))
1936 (if (equal current-input-method "ethiopic")
1937 (setq current-input-method-title (quail-title)))
1938 (force-mode-line-update))
1940 (defun ethio-insert-space (arg)
1941 "Insert ASCII spaces or Ethiopic word separators depending on context.
1943 If the current word separator (indicated in mode-line) is the ASCII space,
1944 insert an ASCII space. With ARG, insert that many ASCII spaces.
1946 If the current word separator is the colon-like Ethiopic word
1947 separator and the point is preceded by `an Ethiopic punctuation mark
1948 followed by zero or more ASCII spaces', then insert also an ASCII
1949 space. With ARG, insert that many ASCII spaces.
1951 Otherwise, insert a colon-like Ethiopic word separator. With ARG, insert that
1952 many Ethiopic word separators."
1954 (interactive "*p")
1955 (cond
1956 (ethio-prefer-ascii-space
1957 (insert-char 32 arg))
1958 ((save-excursion
1959 (skip-chars-backward " ")
1960 (memq (preceding-char)
1961 '(?\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)))
1962 (insert-char 32 arg))
1964 (insert-char ?\e$(3$h\e(B arg))))
1966 (defun ethio-insert-ethio-space (arg)
1967 "Insert the Ethiopic word delimiter (the colon-like character).
1968 With ARG, insert that many delimiters."
1969 (interactive "*p")
1970 (insert-char ?\e$(3$h\e(B arg))
1973 ;; Ethiopic punctuation vs. ASCII punctuation
1976 (defvar ethio-prefer-ascii-punctuation nil)
1977 (make-variable-buffer-local 'ethio-prefer-ascii-punctuation)
1979 (defun ethio-toggle-punctuation nil
1980 "Toggle Ethiopic punctuations and ASCII punctuations for keyboard input."
1981 (interactive)
1982 (setq ethio-prefer-ascii-punctuation
1983 (not ethio-prefer-ascii-punctuation))
1984 (let* ((keys '("." ".." "..." "," ",," ";" ";;" ":" "::" ":::" "*" "**"))
1985 (puncs
1986 (if ethio-prefer-ascii-punctuation
1987 '(?. [".."] ["..."] ?, [",,"] ?\; [";;"] ?: ["::"] [":::"] ?* ["**"])
1988 '(?\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))))
1989 (while keys
1990 (quail-defrule (car keys) (car puncs) "ethiopic")
1991 (setq keys (cdr keys)
1992 puncs (cdr puncs)))
1993 (if (equal current-input-method "ethiopic")
1994 (setq current-input-method-title (quail-title)))
1995 (force-mode-line-update)))
1998 ;; Gemination
2001 (defun ethio-gemination nil
2002 "Compose the character before the point with the Ethiopic gemination mark.
2003 If the character is already composed, decompose it and remove the gemination
2004 mark."
2005 (interactive "*")
2006 (cond
2007 ((eq (char-charset (preceding-char)) 'ethiopic)
2008 (insert "\e$(3%s\e(B")
2009 (compose-region
2010 (save-excursion (backward-char 2) (point))
2011 (point))
2012 (forward-char 1))
2013 ((eq (char-charset (preceding-char)) 'leading-code-composition)
2014 (decompose-region
2015 (save-excursion (backward-char 1) (point))
2016 (point))
2017 (delete-backward-char 1))
2019 (error ""))))
2022 (provide 'ethio-util)
2024 ;;; arch-tag: c8feb3d6-39bf-4b0a-b6ef-26f03fbc8140
2025 ;;; ethio-util.el ends here