2 National Institute of Advanced Industrial Science and Technology (AIST)
3 Registration Number H15PRO112
4 See the end for copying conditions. */
8 @page mdbTutorialIM Tutorial of input method
10 @section im-struct Structure of an input method file
12 An input method is defined in a *.mim file with this format.
15 (input-method LANG NAME)
17 (description (_ "DESCRIPTION"))
19 (title "TITLE-STRING")
23 (KEYSEQ MAP-ACTION MAP-ACTION ...) <- rule
24 (KEYSEQ MAP-ACTION MAP-ACTION ...) <- rule
27 (KEYSEQ MAP-ACTION MAP-ACTION ...) <- rule
28 (KEYSEQ MAP-ACTION MAP-ACTION ...) <- rule
34 (MAP-NAME BRANCH-ACTION BRANCH-ACTION ...) <- branch
37 (MAP-NAME BRANCH-ACTION BRANCH-ACTION ...) <- branch
41 Lowercase letters and parentheses are literals, so they must be
42 written as they are. Uppercase letters represent arbitrary strings.
44 KEYSEQ specifies a sequence of keys in this format:
46 (SYMBOLIC-KEY SYMBOLIC-KEY ...)
48 where SYMBOLIC-KEY is the keysym value returned by the xev command.
53 represents a key sequence of \<n\> and \<i\>.
54 If all SYMBOLIC-KEYs are ASCII characters, you can use the short form
58 instead. Consult @ref mdbIM for Non-ASCII characters.
60 Both MAP-ACTION and BRANCH-ACTION are a sequence of actions of this format:
64 The most common action is <tt>insert</tt>, which is written as this:
68 But as it is very frequently used, you can use the short form
72 If <TT>"TEXT"</TT> contains only one character "C", you can write it as
80 So the shortest notation for an action of inserting "a" is
85 @section im-upcase Simple example of capslock
87 Here is a simple example of an input method that works as CapsLock.
90 (input-method en capslock)
91 (description (_ "Upcase all lowercase letters"))
94 (toupper ("a" "A") ("b" "B") ("c" "C") ("d" "D") ("e" "E")
95 ("f" "F") ("g" "G") ("h" "H") ("i" "I") ("j" "J")
96 ("k" "K") ("l" "L") ("m" "M") ("n" "N") ("o" "O")
97 ("p" "P") ("q" "Q") ("r" "R") ("s" "S") ("t" "T")
98 ("u" "U") ("v" "V") ("w" "W") ("x" "X") ("y" "Y")
104 When this input method is activated, it is in the initial condition of
105 the first state (in this case, the only state <tt>init</tt>). In the
106 initial condition, no key is being processed and no action is
107 suspended. When the input method receives a key event \<a\>, it
108 searches branches in the current state for a rule that matches \<a\>
109 and finds one in the map <tt>toupper</tt>. Then it executes MAP-ACTIONs
110 (in this case, just inserting "A" in the preedit buffer). After all
111 MAP-ACTIONs have been executed, the input method shifts to the initial
112 condition of the current state.
114 The shift to <em>the initial condition of the first state</em> has a special
115 meaning; it commits all characters in the preedit buffer then clears
118 As a result, "A" is given to the application program.
120 When a key event does not match with any rule in the current state,
121 that event is unhandled and given back to the application program.
123 Turkish users may want to extend the above example for "İ" (U+0130:
124 LATIN CAPITAL LETTER I WITH DOT ABOVE). It seems that assigning the
125 key sequence \<i\> \<i\> for that character is convenient. So, he
126 will add this rule in <tt>toupper</tt>.
132 However, we already have the following rule:
138 What will happen when a key event \<i\> is sent to the input method?
140 No problem. When the input method receives \<i\>, it inserts "I" in the
141 preedit buffer. It knows that there is another rule that may
142 match the additional key event \<i\>. So, after inserting "I", it
143 suspends the normal behavior of shifting to the initial condition, and
144 waits for another key. Thus, the user sees "I" with underline, which
145 indicates it is not yet committed.
147 When the input method receives the next \<i\>, it cancels the effects
148 done by the rule for the previous "i" (in this case, the preedit buffer is
149 cleared), and executes MAP-ACTIONs of the rule for "ii". So, "İ" is
150 inserted in the preedit buffer. This time, as there are no other rules
151 that match with an additional key, it shifts to the initial condition
152 of the current state, which leads to commit "İ".
154 Then, what will happen when the next key event is \<a\> instead of \<i\>?
158 The input method knows that there are no rules that match the \<i\> \<a\> key
159 sequence. So, when it receives the next \<a\>, it executes the
160 suspended behavior (i.e. shifting to the initial condition), which
161 leads to commit "I". Then the input method tries to handle \<a\> in
162 the current state, which leads to commit "A".
164 So far, we have explained MAP-ACTION, but not
165 BRANCH-ACTION. The format of BRANCH-ACTION is the same as that of MAP-ACTION.
166 It is executed only after a matching rule has been determined and the
167 corresponding MAP-ACTIONs have been executed. A typical use of
168 BRANCH-ACTION is to shift to a different state.
170 To see this effect, let us modify the current input method to upcase only
171 word-initial letters (i.e. to capitalize). For that purpose,
172 we modify the "init" state as this:
176 (toupper (shift non-upcase)))
179 Here <tt>(shift non-upcase)</tt> is an action to shift to the new state
180 <tt>non-upcase</tt>, which has two branches as below:
188 The first branch is simple. We can define the new map <tt>lower</tt> as the
189 following to insert lowercase letters as they are.
194 (lower ("a" "a") ("b" "b") ("c" "c") ("d" "d") ("e" "e")
195 ("f" "f") ("g" "g") ("h" "h") ("i" "i") ("j" "j")
196 ("k" "k") ("l" "l") ("m" "m") ("n" "n") ("o" "o")
197 ("p" "p") ("q" "q") ("r" "r") ("s" "s") ("t" "t")
198 ("u" "u") ("v" "v") ("w" "w") ("x" "x") ("y" "y")
202 The second branch has a special meaning. The map name <tt>nil</tt> means
203 that it matches with any key event that does not match any rules in the
204 other maps in the current state. In addition, it does not
205 consume any key event. We will show the full code of the new input
206 method before explaining how it works.
209 (input-method en titlecase)
210 (description (_ "Titlecase letters"))
213 (toupper ("a" "A") ("b" "B") ("c" "C") ("d" "D") ("e" "E")
214 ("f" "F") ("g" "G") ("h" "H") ("i" "I") ("j" "J")
215 ("k" "K") ("l" "L") ("m" "M") ("n" "N") ("o" "O")
216 ("p" "P") ("q" "Q") ("r" "R") ("s" "S") ("t" "T")
217 ("u" "U") ("v" "V") ("w" "W") ("x" "X") ("y" "Y")
218 ("z" "Z") ("ii" "İ"))
219 (lower ("a" "a") ("b" "b") ("c" "c") ("d" "d") ("e" "e")
220 ("f" "f") ("g" "g") ("h" "h") ("i" "i") ("j" "j")
221 ("k" "k") ("l" "l") ("m" "m") ("n" "n") ("o" "o")
222 ("p" "p") ("q" "q") ("r" "r") ("s" "s") ("t" "t")
223 ("u" "u") ("v" "v") ("w" "w") ("x" "x") ("y" "y")
227 (toupper (shift non-upcase)))
233 Let's see what happens when the user types the key sequence \<a\> \<b\> \< \>.
234 Upon \<a\>, "A" is inserted into the buffer and the state shifts to <tt>non-upcase</tt>.
235 So, the next \<b\> is handled in the <tt>non-upcase</tt> state.
237 rule in the map <tt>lower</tt>, "b" is inserted in the preedit buffer and characters in the
239 are committed explicitly by the "commit" command in BRANCH-ACTION. After
240 that, the input method is still in the <tt>non-upcase</tt> state. So the next \< \>
241 is also handled in <tt>non-upcase</tt>. For this time, no rule in this state
242 matches it. Thus the branch <tt>(nil (shift init))</tt> is selected and the
243 state is shifted to <tt>init</tt>. Please note that \< \> is not yet
244 handled because the map <tt>nil</tt> does not consume any key event.
245 So, the input method tries to handle it in the <tt>init</tt> state. Again no
246 rule matches it. Therefore, that event is given back to the application
247 program, which usually inserts a space for that.
249 When you type "a quick blown fox" with this input method, you get "A
250 Quick Blown Fox". OK, you find a typo in "blown", which should be
251 "brown". To correct it, you probably move the cursor after "l" and type
252 \<Backspace\> and \<r\>. However, if the current input method is still
253 active, a capital "R" is inserted. It is not a sophisticated
256 @section im-surrounding-text Example of utilizing surrounding text support
258 To make the input method work well also in such a case, we must use
259 "surrounding text support". It is a way to check characters around
260 the inputting spot and delete them if necessary. Note that
261 this facility is available only with Gtk+ applications and Qt
262 applications. You cannot use it with applications that use XIM
263 to communicate with an input method.
265 Before explaining how to utilize "surrounding text support", you must
266 understand how to use variables, arithmetic comparisons, and
269 At first, any symbol (except for several preserved ones) used as ARG
270 of an action is treated as a variable. For instance, the commands
273 (set X 32) (insert X)
276 set the variable <tt>X</tt> to integer value 32, then insert a character
277 whose Unicode character code is 32 (i.e. SPACE).
279 The second argument of the <tt>set</tt> action can be an expression of this form:
282 (OPERATOR ARG1 [ARG2])
285 Both ARG1 and ARG2 can be an expression. So,
288 (set X (+ (* Y 32) Z))
291 sets <tt>X</tt> to the value of <tt>Y * 32 + Z</tt>.
293 We have the following arithmetic/bitwise OPERATORs (require two arguments):
299 these relational OPERATORs (require two arguments):
305 and this logical OPERATOR (requires one argument):
311 For surrounding text support, we have these preserved variables:
314 @-0, @-N, @+N (N is a positive integer)
317 The values of them are predefined as below and can not be altered.
322 -1 if surrounding text is supported, -2 if not.
326 The Nth previous character in the preedit buffer. If there are only M
327 (M<N) previous characters in it, the value is the (N-M)th previous
328 character from the inputting spot.
332 The Nth following character in the preedit buffer. If there are only M
333 (M<N) following characters in it, the value is the (N-M)th following
334 character from the inputting spot.
338 So, provided that you have this context:
344 ("def" is in the preedit buffer, two "|"s indicate borders between the
345 preedit buffer and the surrounding text) and your current position in
346 the preedit buffer is between "d" and "e", you get these values:
357 Next, you have to understand the conditional action of this form:
361 (EXPR1 ACTION ACTION ...)
362 (EXPR2 ACTION ACTION ...)
366 where EXPRn are expressions. When an input method executes this
367 action, it resolves the values of EXPRn one by one from the first branch.
368 If the value of EXPRn is resolved into nonzero, the corresponding
369 actions are executed.
371 Now you are ready to write a new version of the input method "Titlecase".
374 (input-method en titlecase2)
375 (description (_ "Titlecase letters"))
378 (toupper ("a" "A") ("b" "B") ("c" "C") ("d" "D") ("e" "E")
379 ("f" "F") ("g" "G") ("h" "H") ("i" "I") ("j" "J")
380 ("k" "K") ("l" "L") ("m" "M") ("n" "N") ("o" "O")
381 ("p" "P") ("q" "Q") ("r" "R") ("s" "S") ("t" "T")
382 ("u" "U") ("v" "V") ("w" "W") ("x" "X") ("y" "Y")
383 ("z" "Z") ("ii" "İ")))
388 ;; Now we have exactly one uppercase character in the preedit
389 ;; buffer. So, "@-2" is the character just before the inputting
392 (cond ((| (& (>= @-2 ?A) (<= @-2 ?Z))
393 (& (>= @-2 ?a) (<= @-2 ?z))
396 ;; If the character before the inputting spot is A..Z,
397 ;; a..z, or İ, remember the only character in the preedit
398 ;; buffer in the variable X and delete it.
400 (set X @-1) (delete @-)
402 ;; Then insert the lowercase version of X.
405 (1 (set X (+ X 32)) (insert X))))))))
408 The above example contains the new action <tt>delete</tt>. So, it is time
409 to explain more about the preedit buffer. The preedit buffer is a
410 temporary place to store a sequence of characters. In this buffer,
411 the input method keeps a position called the "current position". The
412 current position exists between two characters, at the beginning of
413 the buffer, or at the end of the buffer. The <tt>insert</tt> action inserts
414 characters before the current position. For instance, when your
415 preedit buffer contains "ab.c" ("." indicates the current position),
421 changes the buffer to "abxyz.c".
423 There are several predefined variables that represent a specific position in the
424 preedit buffer. They are:
427 <li> <tt>@@<, @@=, @@></tt>
429 The first, current, and last positions.
431 <li> <tt>@@-, @@+</tt>
433 The previous and the next positions.
436 The format of the <tt>delete</tt> action is this:
442 where POS is a predefined positional variable.
443 The above action deletes the characters between POS and
444 the current position. So, <tt>(delete @-)</tt> deletes one character before
445 the current position. The other examples of <tt>delete</tt> include the followings:
448 (delete @+) ; delete the next character
449 (delete @<) ; delete all the preceding characters in the buffer
450 (delete @>) ; delete all the following characters in the buffer
453 You can change the current position using the <tt>move</tt> action as below:
456 (move @-) ; move the current position to the position before the
458 (move @<) ; move to the first position
461 Other positional variables work similarly.
463 Let's see how our new example works. Whatever a key event is, the
464 input method is in its only state, <tt>init</tt>. Since an event of a lower letter
465 key is firstly handled by MAP-ACTIONs, every key is changed into the
466 corresponding uppercase and put into the preedit buffer. Now this character
467 can be accessed with <tt>@-1</tt>.
469 How can we tell whether the new character should be a lowercase or an
470 uppercase? We can do so by checking the character before it, i.e.
471 <tt>@-2</tt>. BRANCH-ACTIONs in the <tt>init</tt> state do the job.
473 It first checks if the character <tt>@-2</tt> is between A to Z, between
474 a to z, or İ by the conditional below.
477 (cond ((| (& (>= @-2 ?A) (<= @-2 ?Z))
478 (& (>= @-2 ?a) (<= @-2 ?z))
482 If not, there is nothing to do specially. If so, our new key should
483 be changed back into lowercase. Since the uppercase character is
484 already in the preedit buffer, we retrieve and remember it in the
485 variable <tt>X</tt> by
491 and then delete that character by
497 Lastly we re-insert the character in its lowercase form. The
498 problem here is that "İ" must be changed into "i", so we need another
499 conditional. The first branch
505 means that "if the character remembered in X is 'İ', 'i' is inserted".
510 (1 (set X (+ X 32)) (insert X))
513 starts with "1", which is always resolved into nonzero, so this branch
514 is a catchall. Actions in this branch increase <tt>X</tt> by 32, then
515 insert <tt>X</tt>. In other words, they change A...Z into a...z
516 respectively and insert the resulting lowercase character into the
517 preedit buffer. As the input method reaches the end of the
518 BRANCH-ACTIONs, the character is commited.
520 This new input method always checks the character before the current
521 position, so "A Quick Blown Fox" will be successfully fixed to "A
522 Quick Brown Fox" by the key sequence \<BackSpace\> \<r\>.
529 National Institute of Advanced Industrial Science and Technology (AIST)
530 Registration Number H15PRO112
532 This file is part of the m17n database; a sub-part of the m17n
535 The m17n library is free software; you can redistribute it and/or
536 modify it under the terms of the GNU Lesser General Public License
537 as published by the Free Software Foundation; either version 2.1 of
538 the License, or (at your option) any later version.
540 The m17n library is distributed in the hope that it will be useful,
541 but WITHOUT ANY WARRANTY; without even the implied warranty of
542 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
543 Lesser General Public License for more details.
545 You should have received a copy of the GNU Lesser General Public
546 License along with the m17n library; if not, write to the Free
547 Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
548 Boston, MA 02110-1301, USA.