Commit | Line | Data |
---|---|---|
bf4de26a | 1 | ;;; iso-acc.el -- minor mode providing electric accent keys |
b578f267 EN |
2 | |
3 | ;; Copyright (C) 1993, 1994 Free Software Foundation, Inc. | |
bf4de26a RS |
4 | |
5 | ;; Author: Johan Vromans <jv@mh.nl> | |
a2b2b91b | 6 | ;; Version: 1.7 (modified) |
7ab500f0 RS |
7 | ;; Maintainer: FSF |
8 | ;; Keywords: i18n | |
bf4de26a RS |
9 | |
10 | ;; This file is part of GNU Emacs. | |
11 | ||
12 | ;; GNU Emacs is free software; you can redistribute it and/or modify | |
13 | ;; it under the terms of the GNU General Public License as published by | |
14 | ;; the Free Software Foundation; either version 2, or (at your option) | |
15 | ;; any later version. | |
16 | ||
17 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
18 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | ;; GNU General Public License for more details. | |
21 | ||
22 | ;; You should have received a copy of the GNU General Public License | |
b578f267 EN |
23 | ;; along with GNU Emacs; see the file COPYING. If not, write to the |
24 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
25 | ;; Boston, MA 02111-1307, USA. | |
bf4de26a RS |
26 | |
27 | ;;; Commentary: | |
28 | ||
a4332c3f RS |
29 | ;; Function `iso-accents-mode' activates a minor mode in which |
30 | ;; typewriter "dead keys" are emulated. The purpose of this emulation | |
31 | ;; is to provide a simple means for inserting accented characters | |
32 | ;; according to the ISO-8859-1 character set. | |
bf4de26a | 33 | ;; |
a4332c3f | 34 | ;; In `iso-accents-mode', pseudo accent characters are used to |
298613df | 35 | ;; introduce accented keys. The pseudo-accent characters are: |
bf4de26a RS |
36 | ;; |
37 | ;; ' (minute) -> grave accent | |
38 | ;; ` (backtick) -> acute accent | |
39 | ;; " (second) -> diaeresis | |
7ab500f0 RS |
40 | ;; ^ (caret) -> circumflex |
41 | ;; ~ (tilde) -> tilde over the character | |
42 | ;; / (slash) -> slash through the character. | |
a2b2b91b | 43 | ;; Also: /A is A-with-ring and /E is AE ligature. |
bf4de26a RS |
44 | ;; |
45 | ;; The action taken depends on the key that follows the pseudo accent. | |
46 | ;; In general: | |
47 | ;; | |
48 | ;; pseudo-accent + appropriate letter -> accented letter | |
49 | ;; pseudo-accent + space -> pseudo-accent | |
50 | ;; pseudo-accent + pseudo-accent -> accent (if available) | |
51 | ;; pseudo-accent + other -> pseudo-accent + other | |
52 | ;; | |
53 | ;; If the pseudo-accent is followed by anything else than a | |
54 | ;; self-insert-command, the dead-key code is terminated, the | |
55 | ;; pseudo-accent inserted 'as is' and the bell is rung to signal this. | |
56 | ;; | |
8669cecf RS |
57 | ;; Function `iso-accents-mode' can be used to enable the iso accents |
58 | ;; minor mode, or disable it. | |
6da676ad RS |
59 | |
60 | ;; If you want only some of these characters to serve as accents, | |
72c2a4c1 KH |
61 | ;; add a language to iso-languages which specifies the accent characters |
62 | ;; that you want, then select the language with iso-accents-customize. | |
bf4de26a RS |
63 | \f |
64 | ;;; Code: | |
65 | ||
66 | (provide 'iso-acc) | |
67 | ||
700be2bd RS |
68 | (defvar iso-languages |
69 | '(("portuguese" | |
70 | (?' ?` ?^ ?\" ?~) | |
71 | (((?' ?A) ?\301) ((?' ?E) ?\311) ((?' ?I) ?\315) ((?' ?O) ?\323) | |
72 | ((?' ?U) ?\332) ((?' ?C) ?\307) ((?' ?a) ?\341) ((?' ?e) ?\351) | |
73 | ((?' ?i) ?\355) ((?' ?o) ?\363) ((?' ?u) ?\372) ((?' ?c) ?\347) | |
74 | ((?' ? ) ?') ((?` ?A) ?\300) ((?` ?a) ?\340) ((?` ? ) ?`) | |
75 | ((?^ ?A) ?\302) ((?^ ?E) ?\312) ((?^ ?O) ?\324) ((?^ ?a) ?\342) | |
76 | ((?^ ?e) ?\352) ((?^ ?o) ?\364) ((?^ ? ) ?^) ((?\" ?U) ?\334) | |
77 | ((?\" ?u) ?\374) ((?\" ? ) ?\") ((?\~ ?A) ?\303) ((?\~ ?O) ?\325) | |
78 | ((?\~ ?a) ?\343) ((?\~ ?o) ?\365) ((?\~ ?\ ) ?\~))) | |
8a452828 RS |
79 | ("irish" |
80 | (?') | |
81 | (((?' ?A) ?\301) ((?' ?E) ?\311) ((?' ?I) ?\315) ((?' ?O) ?\323) | |
82 | ((?' ?U) ?\332) ((?' ?a) ?\341) ((?' ?e) ?\351) | |
83 | ((?' ?i) ?\355) ((?' ?o) ?\363) ((?' ?u) ?\372) | |
84 | ((?' ? ) ?') )) | |
700be2bd RS |
85 | ("french" |
86 | (?' ?` ?^ ?\" ?~) | |
87 | (((?' ?A) ?\301) ((?' ?E) ?\311) ((?' ?I) ?\315) ((?' ?O) ?\323) | |
88 | ((?' ?U) ?\332) ((?' ?C) ?\307) ((?' ?a) ?\341) ((?' ?e) ?\351) | |
89 | ((?' ?i) ?\355) ((?' ?o) ?\363) ((?' ?u) ?\372) ((?' ?c) ?\347) | |
90 | ((?' ? ) ?') ((?` ?A) ?\300) ((?` ?E) ?\310) ((?` ?a) ?\340) | |
91 | ((?` ?e) ?\350) ((?` ? ) ?`) ((?^ ?A) ?\302) ((?^ ?E) ?\312) | |
92 | ((?^ ?I) ?\316) ((?^ ?O) ?\324) ((?^ ?U) ?\333) ((?^ ?a) ?\342) | |
93 | ((?^ ?e) ?\352) ((?^ ?i) ?\356) ((?^ ?o) ?\364) ((?^ ?u) ?\373) | |
94 | ((?^ ? ) ?^) ((?\" ?U) ?\334) ((?\" ?u) ?\374) ((?\" ? ) ?\") | |
95 | ((?\~ ?A) ?\303) ((?\~ ?O) ?\325) ((?\~ ?a) ?\343) ((?\~ ?o) ?\365) | |
96 | ((?\~ ?\ ) ?\~))) | |
97 | ("default" | |
98 | (?' ?` ?^ ?\" ?~ ?/) | |
99 | (((?' ?A) ?\301) ((?' ?E) ?\311) ((?' ?I) ?\315) ((?' ?O) ?\323) | |
100 | ((?' ?U) ?\332) ((?' ?Y) ?\335) ((?' ?a) ?\341) ((?' ?e) ?\351) | |
101 | ((?' ?i) ?\355) ((?' ?o) ?\363) ((?' ?u) ?\372) ((?' ?y) ?\375) | |
102 | ((?' ?') ?\264) ((?' ? ) ?') ((?` ?A) ?\300) ((?` ?E) ?\310) | |
103 | ((?` ?I) ?\314) ((?` ?O) ?\322) ((?` ?U) ?\331) ((?` ?a) ?\340) | |
104 | ((?` ?e) ?\350) ((?` ?i) ?\354) ((?` ?o) ?\362) ((?` ?u) ?\371) | |
105 | ((?` ? ) ?`) ((?` ?`) ?`) ((?^ ?A) ?\302) ((?^ ?E) ?\312) | |
106 | ((?^ ?I) ?\316) ((?^ ?O) ?\324) ((?^ ?U) ?\333) ((?^ ?a) ?\342) | |
107 | ((?^ ?e) ?\352) ((?^ ?i) ?\356) ((?^ ?o) ?\364) ((?^ ?u) ?\373) | |
108 | ((?^ ? ) ?^) ((?^ ?^) ?^) ((?\" ?A) ?\304) ((?\" ?E) ?\313) | |
109 | ((?\" ?I) ?\317) ((?\" ?O) ?\326) ((?\" ?U) ?\334) ((?\" ?a) ?\344) | |
110 | ((?\" ?e) ?\353) ((?\" ?i) ?\357) ((?\" ?o) ?\366) ((?\" ?s) ?\337) | |
111 | ((?\" ?u) ?\374) ((?\" ?y) ?\377) ((?\" ? ) ?\") ((?\" ?\") ?\250) | |
112 | ((?\~ ?A) ?\303) ((?\~ ?C) ?\307) ((?\~ ?D) ?\320) ((?\~ ?N) ?\321) | |
113 | ((?\~ ?O) ?\325) ((?\~ ?T) ?\336) ((?\~ ?a) ?\343) ((?\~ ?c) ?\347) | |
114 | ((?\~ ?d) ?\360) ((?\~ ?n) ?\361) ((?\~ ?o) ?\365) ((?\~ ?t) ?\376) | |
115 | ((?\~ ?>) ?\273) ((?\~ ?<) ?\253) ((?\~ ?\ ) ?\~) ((?\~ ?\~) ?\270) | |
116 | ((?\/ ?A) ?\305) ((?\/ ?E) ?\306) ((?\/ ?O) ?\330) ((?\/ ?a) ?\345) | |
117 | ((?\/ ?e) ?\346) ((?\/ ?o) ?\370) ((?\/ ?\ ) ?\/) ((?\/ ?\/) ?\260)))) | |
118 | ||
119 | "List of language-specific customizations for the ISO Accents mode. | |
120 | ||
9a71dcfd | 121 | Each element of the list is of the form (LANGUAGE PREFIXES LIST). |
700be2bd RS |
122 | |
123 | LANGUAGE is a string naming the language. | |
124 | ||
9a71dcfd KH |
125 | PREFIXES is a list of characters that will be used as accent prefixes. |
126 | It is currently not used. | |
700be2bd RS |
127 | |
128 | LIST is a list of accent translations. It will be the value of the | |
72c2a4c1 | 129 | `iso-accents-list' variable.") |
700be2bd RS |
130 | |
131 | (defvar iso-language nil | |
132 | "Language for which ISO Accents mode is currently customized. | |
133 | Change it with the `iso-accents-customize' function.") | |
134 | ||
135 | (defvar iso-accents-list nil | |
136 | "Association list for ISO accent combinations, for the chosen language.") | |
bf4de26a | 137 | |
a4332c3f | 138 | (defvar iso-accents-mode nil |
884f2b81 | 139 | "*Non-nil enables ISO Accents mode. |
9c89d223 | 140 | Setting this variable makes it local to the current buffer. |
700be2bd | 141 | See the function `iso-accents-mode'.") |
a4332c3f | 142 | (make-variable-buffer-local 'iso-accents-mode) |
bf4de26a | 143 | |
9a71dcfd KH |
144 | (defvar iso-accents-enable '(?' ?` ?^ ?\" ?~ ?/) |
145 | "*List of accent keys that become prefixes in ISO Accents mode. | |
146 | The default is (?' ?` ?^ ?\" ?~ ?/), which contains all the supported | |
147 | accent keys. If you set this variable to a list in which some of those | |
148 | characters are missing, the missing ones do not act as accents. | |
149 | ||
150 | Note that if you specify a language with `iso-accents-customize', | |
151 | that can also turn off certain prefixes (whichever ones are not needed in | |
152 | the language you choose).") | |
153 | ||
da8d0b9e RS |
154 | (defun iso-accents-accent-key (prompt) |
155 | "Modify the following character by adding an accent to it." | |
156 | ;; Pick up the accent character. | |
9a71dcfd KH |
157 | (if (and iso-accents-mode |
158 | (memq last-input-char iso-accents-enable)) | |
da8d0b9e RS |
159 | (iso-accents-compose prompt) |
160 | (char-to-string last-input-char))) | |
9c89d223 | 161 | |
da8d0b9e RS |
162 | (defun iso-accents-compose-key (prompt) |
163 | "Modify the following character by adding an accent to it." | |
164 | ;; Pick up the accent character. | |
165 | (let ((combined (iso-accents-compose prompt))) | |
166 | (if unread-command-events | |
167 | (let ((unread unread-command-events)) | |
168 | (setq unread-command-events nil) | |
169 | (error "Characters %s and %s cannot be composed" | |
170 | (single-key-description (aref combined 0)) | |
171 | (single-key-description (car unread))))) | |
172 | combined)) | |
173 | ||
174 | (defun iso-accents-compose (prompt) | |
175 | (let* ((first-char last-input-char) | |
176 | ;; Wait for the second key and look up the combination. | |
177 | (second-char (if (or prompt | |
178 | (not (eq (key-binding "a") | |
9ebce7e1 RS |
179 | 'self-insert-command)) |
180 | ;; Called from anything but the command loop. | |
181 | this-command) | |
da8d0b9e RS |
182 | (progn |
183 | (message "%s%c" | |
184 | (or prompt "Compose with ") | |
185 | first-char) | |
186 | (read-event)) | |
187 | (insert first-char) | |
188 | (prog1 (read-event) | |
189 | (delete-region (1- (point)) (point))))) | |
190 | (entry (assoc (list first-char second-char) iso-accents-list))) | |
191 | (if entry | |
192 | ;; Found it: delete the first character and insert the combination. | |
193 | (concat (list (nth 1 entry))) | |
194 | ;; Otherwise, advance and schedule the second key for execution. | |
195 | (setq unread-command-events (list second-char)) | |
196 | (vector first-char)))) | |
197 | ||
bf4de26a RS |
198 | ;; It is a matter of taste if you want the minor mode indicated |
199 | ;; in the mode line... | |
9c89d223 | 200 | ;; If so, uncomment the next four lines. |
a4332c3f | 201 | ;; (or (assq 'iso-accents-mode minor-mode-map-alist) |
bf4de26a RS |
202 | ;; (setq minor-mode-alist |
203 | ;; (append minor-mode-alist | |
a4332c3f | 204 | ;; '((iso-accents-mode " ISO-Acc"))))) |
bf4de26a RS |
205 | |
206 | ;;;###autoload | |
8669cecf | 207 | (defun iso-accents-mode (&optional arg) |
884f2b81 | 208 | "Toggle ISO Accents mode, in which accents modify the following letter. |
8669cecf RS |
209 | This permits easy insertion of accented characters according to ISO-8859-1. |
210 | When Iso-accents mode is enabled, accent character keys | |
7ab500f0 | 211 | \(`, ', \", ^, / and ~) do not self-insert; instead, they modify the following |
8669cecf RS |
212 | letter key so that it inserts an ISO accented letter. |
213 | ||
72c2a4c1 KH |
214 | You can customize ISO Accents mode to a particular language |
215 | with the command `iso-accents-customize'. | |
6da676ad | 216 | |
7ab500f0 | 217 | Special combinations: ~c gives a c with cedilla, |
298613df KH |
218 | ~d gives an Icelandic eth (d with dash). |
219 | ~t gives an Icelandic thorn. | |
ab4d6ceb RS |
220 | \"s gives German sharp s. |
221 | /a gives a with ring. | |
222 | /e gives an a-e ligature. | |
5e92ec88 | 223 | ~< and ~> give guillemots. |
947447f4 RS |
224 | ~! gives an inverted exclamation mark. |
225 | ~? gives an inverted question mark. | |
7ab500f0 | 226 | |
6da676ad | 227 | With an argument, a positive argument enables ISO Accents mode, |
8669cecf | 228 | and a negative argument disables it." |
bf4de26a RS |
229 | |
230 | (interactive "P") | |
231 | ||
8669cecf RS |
232 | (if (if arg |
233 | ;; Negative arg means switch it off. | |
234 | (<= (prefix-numeric-value arg) 0) | |
235 | ;; No arg means toggle. | |
a4332c3f RS |
236 | iso-accents-mode) |
237 | (setq iso-accents-mode nil) | |
bf4de26a RS |
238 | |
239 | ;; Enable electric accents. | |
a4332c3f | 240 | (setq iso-accents-mode t))) |
bf4de26a | 241 | |
700be2bd RS |
242 | (defun iso-accents-customize (language) |
243 | "Customize the ISO accents machinery for a particular language. | |
244 | It selects the customization based on the specifications in the | |
245 | `iso-languages' variable." | |
246 | (interactive (list (completing-read "Language: " iso-languages nil t))) | |
247 | (let ((table (assoc language iso-languages)) | |
9a71dcfd | 248 | all-accents tail) |
700be2bd RS |
249 | (if (not table) |
250 | (error "Unknown language") | |
251 | (setq iso-language language) | |
700be2bd RS |
252 | (setq iso-accents-list (car (cdr (cdr table)))) |
253 | (if key-translation-map | |
254 | (substitute-key-definition | |
255 | 'iso-accents-accent-key nil key-translation-map) | |
256 | (setq key-translation-map (make-sparse-keymap))) | |
9a71dcfd KH |
257 | ;; Find all the characters that are used as accent prefixes |
258 | ;; in this language, and set up translation for them. | |
259 | (setq tail iso-accents-list) | |
260 | (while tail | |
261 | (or (memq (car (car tail)) all-accents) | |
262 | (setq all-accents (cons (car (car tail)) all-accents))) | |
263 | (setq tail (cdr tail))) | |
264 | (setq tail all-accents) | |
265 | (while tail | |
266 | (define-key key-translation-map (char-to-string (car tail)) | |
267 | 'iso-accents-accent-key) | |
268 | (setq tail (cdr tail)))))) | |
700be2bd RS |
269 | |
270 | (defun iso-accentuate (start end) | |
271 | "Convert two-character sequences in region into accented characters. | |
272 | Noninteractively, this operates on text from START to END. | |
273 | This uses the same conversion that ISO Accents mode uses for type-in." | |
274 | (interactive "r") | |
275 | (save-excursion | |
276 | (save-restriction | |
277 | (narrow-to-region start end) | |
278 | (goto-char start) | |
279 | (forward-char 1) | |
280 | (let (entry) | |
281 | (while (< (point) end) | |
282 | (if (and (memq (preceding-char) iso-accents-enable) | |
283 | (<= ?A (following-char)) | |
284 | (<= (following-char) ?z) | |
285 | (setq entry (assoc (list (preceding-char) (following-char)) | |
286 | iso-accents-list))) | |
287 | (progn | |
288 | (forward-char -1) | |
289 | (delete-char 2) | |
290 | (insert (car (cdr entry))) | |
291 | (setq end (1- end))) | |
292 | (forward-char 1))))))) | |
293 | ||
294 | (defun iso-accent-rassoc-unit (value alist) | |
295 | (while (and alist | |
296 | (not (eq (car (cdr (car alist))) value))) | |
297 | (setq alist (cdr alist))) | |
298 | (if alist | |
299 | (car alist) | |
300 | nil)) | |
301 | ||
302 | (defun iso-unaccentuate (start end) | |
303 | "Convert accented characters in the region into two-character sequences. | |
304 | Noninteractively, this operates on text from START to END. | |
305 | This uses the opposite of the conversion done by ISO Accents mode for type-in." | |
306 | (interactive "r") | |
307 | (save-excursion | |
308 | (save-restriction | |
309 | (narrow-to-region start end) | |
310 | (goto-char start) | |
311 | (let (entry) | |
312 | (while (< (point) end) | |
313 | (if (and (> (following-char) 127) | |
314 | (setq entry (iso-accent-rassoc-unit (following-char) | |
315 | iso-accents-list))) | |
316 | (progn | |
317 | (delete-char 1) | |
318 | (insert (car (car entry)) (car (cdr (car entry)))) | |
319 | (setq end (1+ end))) | |
320 | (forward-char 1))))))) | |
321 | ||
322 | (defun iso-deaccentuate (start end) | |
323 | "Convert accented characters in the region into unaccented characters. | |
324 | Noninteractively, this operates on text from START to END." | |
325 | (interactive "r") | |
326 | (save-excursion | |
327 | (save-restriction | |
328 | (narrow-to-region start end) | |
329 | (goto-char start) | |
330 | (let (entry) | |
331 | (while (< (point) end) | |
332 | (if (and (> (following-char) 127) | |
333 | (setq entry (iso-accent-rassoc-unit (following-char) | |
334 | iso-accents-list))) | |
335 | (progn | |
336 | (delete-char 1) | |
337 | (insert (car (cdr (car entry))))) | |
338 | (forward-char 1))))))) | |
339 | ||
9a71dcfd KH |
340 | ;; Set up the default settings. |
341 | (iso-accents-customize "default") | |
700be2bd | 342 | |
bf4de26a | 343 | ;;; iso-acc.el ends here |