Remove non-free old and crusty clearcase pkg
[packages] / mule-packages / skk / skk-isearch.el
1 ;; -*- byte-compile-dynamic-docstring: t;-*-
2 ;;; skk-isearch.el --- isearch mode for skk with Emacs 19 or later and XEmacs.
3 ;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999
4 ;; Enami Tsugutomo <enami@ba2.so-net.or.jp>
5
6 ;; Author: Enami Tsugutomo <enami@ba2.so-net.or.jp>
7 ;; Maintainer: Mikio Nakajima <minakaji@osaka.email.ne.jp>
8 ;; Version: $Id: skk-isearch.el,v 1.4 2002-04-28 07:12:27 youngs Exp $
9 ;; Keywords: japanese
10 ;; Last Modified: $Date: 2002-04-28 07:12:27 $
11
12 ;; This file is part of SKK.
13
14 ;; SKK 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 versions 2, or (at your option)
17 ;; any later version.
18
19 ;; SKK 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.
23
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with SKK, see the file COPYING.  If not, write to the Free
26 ;; Software Foundation Inc., 59 Temple Place - Suite 330, Boston,
27 ;; MA 02111-1307, USA.
28
29 ;;; Commentary:
30 ;; functions for hooks.
31 ;;
32 ;; 1. always invoke skk isearch.
33 ;; (add-hook 'isearch-mode-hook 
34 ;;           (function (lambda () (require 'skk) (skk-isearch-mode-setup))))
35 ;; (add-hook 'isearch-mode-end-hook 'skk-isearch-mode-cleanup)
36 ;;
37 ;; 2. invoke only if skk-mode is on.
38 ;; (add-hook 'isearch-mode-hook
39 ;;           (function (lambda ()
40 ;;                       (and (boundp 'skk-mode) skk-mode
41 ;;                            (skk-isearch-mode-setup)))))
42 ;;
43 ;; (add-hook 'isearch-mode-end-hook
44 ;;           (function
45 ;;            (lambda ()
46 ;;              (and (boundp 'skk-mode) skk-mode (skk-isearch-mode-cleanup)))))
47 ;; 
48 ;; 3. invoke if current buffer has japanese characters.
49 ;; ...
50 ;;
51 ;; skk-isearch-initial-mode examine the variable of skk before calling
52 ;; skk-mode.
53
54 ;;; Code:
55 (require 'skk)
56 (require 'skk-foreword)
57 \f
58 ;; user variables
59 ;;;###autoload
60 (defgroup skk-isearch nil "SKK incremental search related customization."
61   :prefix "skk-isearch-"
62   :group 'skk )
63
64 (defcustom skk-isearch-mode-string-alist
65   '((hiragana . "[\e$B$+\e(B] ") (katakana . "[\e$B%+\e(B] ") (jisx0208-latin . "[\e$B1Q\e(B] ")
66     (latin . "[aa] ") (nil . "[--] "))
67   ;;  "*Alist of \(MODE-SYMBOL . PROMPT-STRING\).
68   ;;MODE-SYMBOL is a symbol indicates canonical mode of skk for skk-isearch.
69   ;;Valid MODE-SYMBOL is one of `hiragana', `katakana', `jisx0208-latin',
70   ;;`latin' or nil.
71   ;;PROMPT-STRING is a string used in prompt to indicates current mode of
72   ;;skk for skk-isearch. "
73   "*isearch \e$B;~$KF~NO%b!<%I$K=>$$=P$9%W%m%s%W%H;XDj$N$?$a$N%(!<%j%9%H!#\e(B
74 \e$B3FMWAG$O!"\e(B
75
76   \(MODE-SYMBOL . PROMPT-STRING\)
77
78 \e$B$H$$$&\e(B cons cell\e$B!#\e(B
79 MODE-SYMBOL \e$B$OF~NO%b!<%I$rI=$o$9%7%s%\%k$G!"\e(B
80 \e$B2<5-$N$$$:$l$+$r;XDj$9$k!#\e(B
81
82    \e$B$+$J%b!<%I!'\e(B `hiragana'
83    \e$B%+%J%b!<%I!'\e(B `katakana'
84    \e$BA41Q%b!<%I!'\e(B `jisx0208-latin'
85    \e$B%"%9%-!<%b!<%I!'\e(B `latin'
86
87 nil \e$B$O!"\e(BSKK \e$B%b!<%I%*%U$rI=$o$9!#\e(B
88 PROMPT-STRING \e$B$O!"3:Ev$N\e(B SKK \e$B%b!<%I$KBP$7=P$9%W%m%s%W%H$NJ8;zNs!#\e(B"
89   :type '(repeat (cons (choice :tag "Mode symbol"
90                                (const hiragana)
91                                (const katakana)
92                                (const jisx0208-latin)
93                                (const latin)
94                                (const nil))
95                        (string :tag "Prompt string")))
96   :group 'skk-isearch )
97
98 (defcustom skk-isearch-start-mode nil
99   ;;  "*Specifies the search mode when isearch is called.
100   ;;This variable is valid only when `skk-isearch-use-previous-mode' is nil.
101   ;;If nil, it means that if skk-mode has been called in this buffer, same as
102   ;;the mode of the buffer, otherwise perform ascii search.
103   ;;If `latin' or `ascii' perfrom ascii search.
104   ;;If `hiragana', `hirakana' or `kana' -> hira kana search.
105   ;;If `jisx0208-latin' or `eiji', perform zenkaku eiji (i.e. JIS X0208 alphabet) search."
106   "*\e$B%+%l%s%H%P%C%U%!$G\e(B isearch \e$B$r9T$J$&:]$NF~NO%b!<%I!#\e(B
107 `skk-isearch-use-previous-mode' \e$B$,\e(B nil \e$B$N>l9g$N$_M-8z!#\e(B
108 isearch \e$B$r9T$J$&>l9g!">o$K$3$NJQ?t$G;XDj$7$?F~NO%b!<%I$,;HMQ$5$l$k\e(B (\e$B%f!<%6!<$,\e(B
109 \e$BL@<(E*$KJQ99$r9T$J$&$3$H$O2D\e(B)\e$B!#\e(B
110 \e$B2<5-$N$$$:$l$+$N%7%s%\%k$G;XDj$9$k!#\e(B
111
112    nil:  \e$B%+%l%s%H%P%C%U%!$G\e(B SKK \e$B%b!<%I$,5/F0$5$l$F$$$l$P$=$N%b!<%I!"\e(B
113          \e$B5/F0$5$l$F$$$J$1$l$P\e(B \e$B%"%9%-!<%b!<%I!#\e(B
114    `hiragana' (`hiragana' or `kana'): \e$B$+$J%b!<%I\e(B
115    `jisx0208-latin' (`eiji') : \e$BA41Q%b!<%I\e(B
116    `latin' (`ascii'): \e$B%"%9%-!<%b!<%I\e(B"
117   :type '(choice (const :tag "Succeed an input mode of current buffer" nil)
118                  (const :tag "Ascii search" latin)
119                  (const :tag "Hiragana search" hiragana)
120                  (const :tag "JISX0208 alphabet search" jisx0208-latin))
121   :group 'skk-isearch )
122
123 (defcustom skk-isearch-use-previous-mode nil
124   ;; "*Non-nil means use same search mode as the search mode of the last search in the buffer."
125   "*Non-nil \e$B$G$"$l$P!"%+%l%s%H%P%C%U%!$G:G8e$K9T$J$C$?\e(B isearch \e$B$N\e(B SKK \e$B%b!<%I$HF1$8%b!<%I$r;HMQ$9$k!#\e(B"
126   :type 'boolean
127   :group 'skk-isearch )
128
129 (defcustom skk-isearch-initial-mode-when-skk-mode-disabled 'latin
130   ;;  "*Symbol indicates the mode to use as initial mode for skk-isearch when
131   ;;skk is turned off in the current buffer."
132   "*SKK \e$B%b!<%I$,%*%U$N%+%l%s%H%P%C%U%!$G!":G=i$K\e(B isearch \e$B$r9T$J$&:]$NF~NO%b!<%I!#\e(B"
133   :type '(choice (const :tag "Ascii search" latin)
134                  (const :tag "Hiragana search" hiragana)
135                  (const :tag "JISX0208 alphabet search" jisx0208-latin))
136   :group 'skk-isearch )
137
138 (defcustom skk-isearch-whitespace-regexp "\\(\\s \\|[ \t\n\r\f]\\)*"
139   ;;  "*Regular expression to match a sequence of whitespace chars.
140   ;;This applies to regular expression incremental search."
141   "\e$B6uGrJ8;z$NO"B3$H$7$F%^%C%A$5$;$k$Y$-@55,I=8=!#\e(B
142 regexp isearch \e$B$N:]!"$3$N@55,I=8=$K%^%C%A$9$kJ8;z$,8!:wJ8;zNs$N4V$K4^$^$l$F$$$F\e(B
143 \e$B$b%^%C%A$9$k!#\e(B"
144   :type 'regexp
145   :group 'skk-isearch )
146
147 ;; internal constants and variables.
148 (defconst skk-isearch-mode-canonical-alist
149   '((hiragana . 0) (katakana . 1) (jisx0208-latin . 2) (latin . 3))
150   "Alist of \(SYMBOL . NUMBER\).
151 The SYMBOL is canonical skk mode, and NUMBER is its numerical representation.")
152
153 (defconst skk-isearch-mode-alias-alist
154   '((hirakana . hiragana) (kana . hiragana) (eiji . jisx0208-latin)
155     (ascii . latin))
156   "Alist of \(ALIAS . CANONICAL\).
157 The both ALIAS and CANONICAL should be symbol.
158 ALIAS can be used as an alias of CANONICAL.
159 CANONICAL should be found in `skk-isearch-mode-canonical-alist'. ")
160
161 (defconst skk-isearch-breakable-character-p-function
162   (cond ((fboundp 'char-category-set)
163          (function (lambda (char)
164                      ;; see emacs/lisp/fill.el how the category `|' is
165                      ;; treated.
166                      (aref (char-category-set char) ?|))))
167         ((boundp 'word-across-newline)
168          (function (lambda (char)
169                      ;; (let ((lc (char-leading-char char)))
170                      ;;   (or (= lc lc-jp) (= lc lc-cn)))
171                      (string-match word-across-newline
172                                    (char-to-string char)))))
173         (t (error "No appropriate function as: %s"
174                   'skk-isearch-breakable-character-p-function)))
175   "Function to test if we can insert a newline around CHAR when filling.")
176
177 (defconst skk-isearch-working-buffer " *skk-isearch*"
178   "Work buffer for skk isearch." )
179
180 (defvar skk-isearch-mode nil
181   "Current search mode.
182 0 means hira kana search.
183 1 means kana search.
184 2 means zenkaku eiji (i.e. JIS X0208 alphabet) search.
185 3 means ascii search." )
186
187 (defvar skk-isearch-incomplete-message ""
188   "Incomplete isearch message" )
189
190 (defvar skk-isearch-mode-map nil
191   "Keymap for skk isearch mode.
192 This map should be derived from isearch-mode-map." )
193
194 (defvar skk-isearch-overriding-local-map
195   (cond ((eq skk-emacs-type 'xemacs)
196          (cond
197           ((or (> emacs-major-version 21)
198                (and (= emacs-major-version 21)
199                     (or (> emacs-minor-version 2)
200                         (and (= emacs-minor-version 2)
201                              (boundp 'emacs-beta-version) emacs-beta-version
202                              (>= emacs-beta-version 2)))))
203            'overriding-local-map )
204           (t 'overriding-terminal-local-map)))
205         ;; for Mule/GNU Emacs.
206         ((or (> emacs-major-version 19)
207              (and (= emacs-major-version 19) (> emacs-minor-version 28)))
208          ;; GNU Emacs version 19.29, 19.30 and 19.31 uses this in isearch.el.
209          'overriding-terminal-local-map )
210         ;; GNU Emacs version 19.22 .. 19.28 uses this in isearch.el.
211         (t 'overriding-local-map))
212   "Variable holding overrinding local map used in isearch-mode.")
213
214 (defvar skk-isearch-last-mode-string "")
215 (defvar skk-isearch-last-mode-regexp "")
216 \f
217 ;;
218 ;; interface to skk.el
219 ;;
220 (defsubst skk-isearch-turn-off-skk-mode ()
221   "Turn off skk mode."
222   (skk-mode 0))
223
224 (defsubst skk-isearch-turn-on-skk-mode ()
225   "Turn on skk mode."
226   (skk-mode 1))
227
228 (defsubst skk-isearch-conversion-active-p ()
229   "Non-nil if skk conversion is active."
230   skk-henkan-on )
231
232 (defsubst skk-isearch-conversion-start ()
233   "Point where conversion is start.  Includes skk marker."
234   (- skk-henkan-start-point skk-kanji-len))
235
236 (defsubst skk-isearch-skk-kakutei ()
237   "Perform kakutei."
238   (skk-kakutei))
239
240 (defsubst skk-isearch-skk-hiragana-mode-p ()
241   "Non-nil if skk is hiragana input mode."
242   (and (not skk-katakana) skk-j-mode))
243
244 (defsubst skk-isearch-skk-turn-on-hiragana-mode ()
245   "Set current skk mode to hiragana input mode."
246   (skk-j-mode-on))
247
248 (defsubst skk-isearch-skk-katakana-mode-p ()
249   "Non-nil if skk is katakana input mode."
250   (and skk-j-mode skk-katakana))
251
252 (defsubst skk-isearch-skk-turn-on-katakana-mode ()
253   "Set current skk mode to katakana input mode."
254   (skk-j-mode-on 'katakana))
255
256 (defsubst skk-isearch-skk-jisx0208-latin-mode-p ()
257   "Non-nil if skk is jisx0208 latin (zenkaku) input mode."
258   skk-jisx0208-latin-mode )
259
260 (defsubst skk-isearch-skk-turn-on-jix0208-latin-mode ()
261   "Set current skk mode to jisx0208 latin (zenkaku) input mode."
262   (skk-jisx0208-latin-mode-on))
263
264 (defsubst skk-isearch-skk-turn-on-latin-mode ()
265   "Set current skk mode to normal latin input mode."
266   (skk-latin-mode-on))
267
268 (defun skk-isearch-message ()
269   "Show isearch message."
270   (skk-isearch-incomplete-message
271    (if (string= skk-prefix "") (char-to-string last-command-char) skk-prefix)))
272
273 (defun skk-isearch-current-mode ()
274   "Return the symbolic current mode of skk for skk-isearch."
275   (cond ((not skk-mode) nil)
276         ((skk-isearch-skk-katakana-mode-p) 'katakana)
277         ((skk-isearch-skk-hiragana-mode-p) 'hiragana)
278         ((skk-isearch-skk-jisx0208-latin-mode-p) 'jisx0208-latin)
279         (t 'latin)))
280
281 (defun skk-isearch-set-initial-mode (mode)
282   "Set up the initial condition according to given symbolic MODE.
283 The MODE should be canonical."
284   ;; following code is highly depends on internal of skk.
285   ;; (skk-isearch-turn-on-skk-mode)
286   ;; (skk-isearch-skk-kakutei)
287   (cond ((eq mode 'hiragana) (skk-isearch-skk-turn-on-hiragana-mode))
288         ((eq mode 'katakana) (skk-isearch-skk-turn-on-katakana-mode))
289         ((eq mode 'jisx0208-latin)
290          (skk-isearch-skk-turn-on-jix0208-latin-mode))
291         ((eq mode 'latin) (skk-isearch-skk-turn-on-latin-mode))
292         ((not mode) (skk-isearch-turn-off-skk-mode))
293         ;; shouldn't happen.
294         (t (error "unknown skk-isearch-mode %s" mode))))
295 \f
296 (defun skk-isearch-symbolic-mode (mode)
297   "Return symbolic skk isearch mode for given numerical MODE."
298   (car (rassq mode skk-isearch-mode-canonical-alist)))
299
300 (defun skk-isearch-numerical-mode (mode)
301   "Return numerical skk isearch mode for given symbolic MODE."
302   (cdr (assq mode skk-isearch-mode-canonical-alist)))
303
304 (defun skk-isearch-mode-string ()
305   "Return the current skk mode string for prompting."
306   (with-current-buffer (get-buffer-create skk-isearch-working-buffer)
307     (cdr (assq (skk-isearch-current-mode) skk-isearch-mode-string-alist))))
308
309 (defun skk-isearch-current-numerical-mode ()
310   "Return the symbolic skk isearch mode according to the current skk
311 internal condition."
312   (skk-isearch-numerical-mode (or (skk-isearch-current-mode) 'latin)))
313
314 (defun skk-isearch-canonical-start-mode (mode)
315   "Canonicalize the symbolic skk isearch MODE."
316   ;; alias, canonical, or error.
317   (cond ((cdr (rassq mode skk-isearch-mode-alias-alist)))
318         ((cdr (assq mode skk-isearch-mode-alias-alist)))
319         ((skk-isearch-numerical-mode mode) mode)
320         (t (error "Unknown skk-isearch-start-mode: %s" mode))))
321
322 (defun skk-isearch-initial-mode ()
323   "Return the symbolic mode name of skk-isearch used to initialize working
324 buffer."
325   (cond ((and skk-isearch-use-previous-mode skk-isearch-mode)
326          ;; use the mode when last isearch is done.  note that the
327          ;; `skk-isearch-mode' is numerical, so convert it to symbolic
328          ;; mode.
329          (skk-isearch-symbolic-mode skk-isearch-mode))
330         (skk-isearch-start-mode
331          ;; always start with the specified mode.
332          ;; `skk-isearch-start-mode' is symbolic.
333          (skk-isearch-canonical-start-mode skk-isearch-start-mode))
334         ;; guess the current buffer.  note that if skk-mode is off,
335         ;; skk-isearch-current-mode returns symbol `nil' and control
336         ;; falls through to next cond clause.
337         ((skk-isearch-current-mode))
338         ;; skk-mode is off in this buffer.
339         (t skk-isearch-initial-mode-when-skk-mode-disabled)))
340
341 (defun skk-isearch-initialize-working-buffer ()
342   "Initialize the current buffer as working buffer for skk isearch.
343 More precicely, turn on skk-mode, put into kana mode, make sure
344 kakutei'ed and erase the buffer contents."
345   (skk-isearch-turn-on-skk-mode)
346   (skk-isearch-skk-kakutei)
347   (erase-buffer))
348
349 ;;;###autoload
350 (defun skk-isearch-mode-setup ()
351   "hook function called when skk isearch begin."
352   ;; setup working buffer.  initial skk mode for isearch should be
353   ;; determined in the original buffer and set in working buffer.
354   (let ((initial (skk-isearch-initial-mode)))
355     (with-current-buffer (get-buffer-create skk-isearch-working-buffer)
356       (skk-erase-prefix 'clean)
357       (skk-isearch-initialize-working-buffer)
358       (skk-isearch-set-initial-mode initial)))
359   ;; setup variables and keymap
360   (set skk-isearch-overriding-local-map skk-isearch-mode-map)
361   (setq skk-isearch-incomplete-message ""
362         ;; set skk-isearch-message non-nil to call skk-isearch-message.
363         skk-isearch-message "")
364   (skk-isearch-mode-message)
365   (skk-isearch-incomplete-message))
366
367 ;;;###autoload
368 (defun skk-isearch-mode-cleanup ()
369   "Hook function called when skk isearch is done."
370   ;; remember the current skk mode for next use.
371   (let ((mode (skk-current-insert-mode)))
372     (and skk-isearch-use-previous-mode
373          (setq skk-isearch-mode
374                (with-current-buffer (get-buffer-create skk-isearch-working-buffer)
375                  (skk-isearch-current-numerical-mode))))
376     ;; reset the overrinding-local-map.
377     (set skk-isearch-overriding-local-map nil)
378     (setq skk-isearch-message nil
379           skk-isearch-last-mode-string ""
380           skk-isearch-last-mode-regexp "" )
381     ;; \e$B%5!<%ACf$KF~NO%b!<%I$rJQ99$7$?$i!"%b!<%I%i%$%s$NI=<($b$=$l$K=>$$\e(B
382     ;; \e$BJQ99$5$l$k$N$G!"%+%l%s%H%P%C%U%!$NF~NO%b!<%I$H%b!<%I%i%$%s$NI=<(\e(B
383     ;; \e$B$H$,\e(B sync \e$B$7$J$/$J$k!#=>$$!"%5!<%A$,=*N;$7$?:]!"%b!<%I%i%$%s$r%+\e(B
384     ;; \e$B%l%s%H%P%C%U%!$NF~NO%b!<%I$H\e(B sync \e$B$5$;$k!#\e(B
385     (cond ((eq mode 'hiragana) (skk-j-mode-on))
386           ((eq mode 'katakana) (skk-j-mode-on t))
387           ((eq mode 'abbrev) (skk-abbrev-mode-on))
388           ((eq mode 'latin) (skk-latin-mode-on))
389           ((eq mode 'jisx0208-latin) (skk-jisx0208-latin-mode-on))))
390   (remove-hook 'pre-command-hook 'skk-pre-command 'local)
391   (skk-remove-minibuffer-setup-hook
392    'skk-j-mode-on 'skk-setup-minibuffer
393    (function (lambda ()
394                (add-hook 'pre-command-hook 'skk-pre-command nil 'local)))))
395
396 (defun skk-isearch-incomplete-message (&optional prefix)
397   "Show message when kana kanji conversion is in progress.
398 Optional argument PREFIX is appended if given."
399   (let ((isearch-message (concat isearch-message
400                                  skk-isearch-incomplete-message prefix)))
401     (isearch-message)))
402 \f
403 ;;
404 ;; define keymap
405 ;;
406
407 ;; XXX should be more generic
408 (defun skk-isearch-setup-keymap (map)
409   ;; printable chars.
410   (let ((c ?\040))
411     (while (< c ?\177)
412       (define-key map (char-to-string c) 'skk-isearch-wrapper)
413       (setq c (1+ c))))
414
415   ;; control chars for skk.
416   (define-key map "\C-g" 'skk-isearch-keyboard-quit)
417   (define-key map "\C-j" 'skk-isearch-newline)
418   (define-key map "\C-m" 'skk-isearch-exit)
419   (define-key map "\177" 'skk-isearch-delete-char)
420
421   ;; C-x map for skk.
422   (define-key map "\C-x" (make-sparse-keymap))
423   (define-key map [?\C-x t] 'isearch-other-control-char)
424   (define-key map "\C-x\C-j" 'skk-isearch-skk-mode)
425   map)
426
427 (or skk-isearch-mode-map
428     (if (eq skk-emacs-type 'xemacs)
429         (progn
430           (setq skk-isearch-mode-map (skk-isearch-setup-keymap (make-keymap)))
431           (set-keymap-parents skk-isearch-mode-map isearch-mode-map))
432       (setq skk-isearch-mode-map
433             (skk-isearch-setup-keymap (cons 'keymap isearch-mode-map)))))
434
435 \f
436 ;;
437 ;; wrapper functions
438 ;;
439
440 (defun skk-isearch-redo-function ()
441   "Execute the command of given key sequence in skk environment."
442   ;; with saving value of old binding.
443   (let ((local-map (symbol-value skk-isearch-overriding-local-map)))
444     (unwind-protect
445         (progn
446           ;; temporarily disable the overriding-local-map.  this
447           ;; should be done in ther buffer isearch is performed, i.e.,
448           ;; before entering skk-isearch-working-buffer.
449           (set skk-isearch-overriding-local-map nil)
450           ;; don't change the current buffer during save/restore the
451           ;; overriding-local-map, because it is buffer local in some
452           ;; version of emacs.
453           (with-current-buffer (get-buffer-create skk-isearch-working-buffer)
454             ;; listify this-command-keys.  this works only if it is
455             ;; string.
456             (setq unread-command-events
457                   (append (if (= (length (this-command-keys)) 0)
458                               (list last-command-event)
459                             (this-command-keys))
460                           nil ))
461             (condition-case error
462                 ;; setup last-command-event and this-command because
463                 ;; some command refers them.
464                 (let* ((keys (read-key-sequence nil))
465                        (this-command (key-binding keys)))
466                   (setq last-command-event (aref keys (1- (length keys))))
467                   (command-execute this-command))
468               (quit (signal (car error) (cdr error)))
469               (error (signal (car error) (cdr error)))))
470           (skk-isearch-mode-message))
471       (set skk-isearch-overriding-local-map local-map))))
472
473 (defun skk-isearch-search-string ()
474   "Return the string to be searched.
475 If the conversion is in progress and no string is fixed, just return nil."
476     (with-current-buffer (get-buffer-create skk-isearch-working-buffer)
477       (prog1
478           (cond ((skk-isearch-conversion-active-p)
479                  (let ((start (skk-isearch-conversion-start)))
480                    ;; is there fixed string?
481                    (if (/= start 1)
482                        (prog1
483                            (buffer-substring 1 start)
484                          (delete-region 1 start)))))
485                 ;; a conversion is in progress
486                 ((not (string= skk-prefix "")) nil)
487                 ;;(skk-current-rule-tree nil)
488                 ;; whole string in the buffer is fixed.
489                 ((not (zerop (buffer-size)))
490                  (prog1
491                      (buffer-string)
492                    (erase-buffer))))
493         ;; update incomplete-message with contents of working buffer.
494         (setq skk-isearch-incomplete-message (buffer-string))
495         ;; update echo area.
496         (skk-isearch-incomplete-message))))
497
498 \f
499 ;;
500 ;; regexp search supports.
501 ;;
502 (defun skk-isearch-last-char (string)
503   (and (string-match ".\\'" string)
504        (string-to-char (substring string (match-beginning 0)))))
505
506 (defun skk-isearch-breakable-p (char)
507   (and char
508        (funcall skk-isearch-breakable-character-p-function char)))
509
510 (defun skk-isearch-search-string-regexp (string)
511   (if isearch-regexp
512       (let ((chars (string-to-list string))
513             (prev (skk-isearch-last-char isearch-string))
514             (result ""))
515         (while chars
516           (if (and (skk-isearch-breakable-p prev)
517                    (skk-isearch-breakable-p (car chars)))
518               (setq result (concat result skk-isearch-whitespace-regexp)))
519           (setq result (concat result (char-to-string (car chars)))
520                 prev (car chars)
521                 chars (cdr chars)))
522         result)
523     string))
524
525 (defun skk-isearch-mode-message ()
526   "Prepend the skk isearch mode string to `isearch-message'.  If the current
527 mode is different from previous, remove it first."
528   (let ((mode-string (skk-isearch-mode-string)))
529     (if (string= mode-string skk-isearch-last-mode-string)
530         nil
531       (if (string-match skk-isearch-last-mode-regexp isearch-message)
532           (setq isearch-message (substring isearch-message (match-end 0))))
533       (setq skk-isearch-last-mode-string mode-string
534             skk-isearch-last-mode-regexp (concat "^"
535                                                  (regexp-quote mode-string)))
536       (setq isearch-message (concat mode-string isearch-message)))))
537
538 (defun skk-isearch-process-search-string (string)
539   (isearch-process-search-string (skk-isearch-search-string-regexp string)
540                                  string))
541
542 \f
543 ;;
544 ;; interactive functions.
545 ;;
546 (defun skk-isearch-delete-char (&rest args)
547   (interactive "P")
548   (or (with-current-buffer (get-buffer-create skk-isearch-working-buffer)
549         ;; following code is highly depends on internal of skk.
550         (if (skk-isearch-conversion-active-p)
551             (prog1
552                 t
553               (if (string= skk-prefix "")
554                   ;; now, we can't pass the universal argument within the
555                   ;; isearch-mode.  so hard code the value `1'.
556                   (delete-backward-char 1)
557                 (skk-erase-prefix 'clean))
558               (setq skk-isearch-incomplete-message (buffer-string))
559               (skk-isearch-incomplete-message))))
560       (isearch-delete-char)))
561
562 (defun skk-isearch-kakutei (isearch-function)
563   "Special wrapper for skk-kakutei or newline."
564   (if (with-current-buffer (get-buffer-create skk-isearch-working-buffer)
565         ;; following code is highly depends on internal of skk.
566         (if (skk-isearch-conversion-active-p)
567             (prog1
568                 t
569               (skk-isearch-skk-kakutei))))
570       (skk-isearch-process-search-string (skk-isearch-search-string))
571     (funcall isearch-function)))
572
573 (defun skk-isearch-exit (&rest args)
574   (interactive "P")
575   (skk-isearch-kakutei (function isearch-exit)))
576
577 (defun skk-isearch-newline (&rest args)
578   (interactive "P")
579   ;; following code is highly depends on internal of skk.
580   (if (with-current-buffer (get-buffer-create skk-isearch-working-buffer)
581         (if (memq (skk-isearch-current-mode) '(latin jisx0208-latin))
582             (prog1
583                 t
584               ;; if the working buffer is latin or jisx0208-latin
585               ;; mode, default behaviour of C-j is set current mode
586               ;; to kana mode.
587               (skk-isearch-turn-on-skk-mode)
588               (skk-isearch-mode-message))))
589       (isearch-message)
590     (skk-isearch-kakutei (function isearch-printing-char))))
591
592 (defun skk-isearch-skk-mode (&rest args)
593   (interactive "P")
594   (skk-isearch-redo-function)
595   (isearch-message))
596
597 (defun skk-isearch-keyboard-quit (&rest args)
598   (interactive "P")
599   (condition-case ()
600       (progn
601         (skk-isearch-redo-function)
602         ;; update echo area message.
603         (skk-isearch-search-string))
604     (quit (isearch-abort))))
605
606 (defun skk-isearch-wrapper (&rest args)
607   (interactive "P")
608   (skk-isearch-redo-function)
609   (let ((string (skk-isearch-search-string)))
610     (if (null string)
611         ;; on the way to converting to kanji.
612         nil
613       ;; with saving value of old binding...
614       (let ((local-map (symbol-value skk-isearch-overriding-local-map))
615             (current-buffer (current-buffer)))
616         ;; because the overrinding local map may be buffer local, keep the
617         ;; current buffer, but we can't use save-excursion. ...
618         (unwind-protect
619             (progn
620               (set skk-isearch-overriding-local-map isearch-mode-map)
621               (let ((command (key-binding string)))
622                 (cond ((not (commandp command))
623                        ;; just search literally.
624                        (skk-isearch-process-search-string string))
625                       ;; internationalized isearch.el
626                       ((fboundp 'isearch-process-search-multibyte-characters)
627                        ;; internationalized isearch.el binds all
628                        ;; multibyte characters to `isearch-printing-char'.
629                        (cond (
630                               ;; STRING is not a multibyte character.
631                               (> skk-kanji-len (length string))
632                               ;; process a special character, such as *, |, ...
633                               (command-execute command))
634                              (t (skk-isearch-process-search-string string))))
635                       ;; non internationalized isearch.el
636                       (t (command-execute command)))))
637           ;; restore the overriding local map.
638           (set-buffer current-buffer)
639           (set skk-isearch-overriding-local-map local-map))))))
640
641 (put 'skk-isearch-wrapper 'isearch-command t)
642 (put 'skk-isearch-keyboard-quit 'isearch-command t)
643 (put 'skk-isearch-newline 'isearch-command t)
644 (put 'skk-isearch-exit 'isearch-command t)
645 (put 'skk-isearch-delete-char 'isearch-command t)
646 (put 'isearch-other-control-char 'isearch-command t)
647 (put 'skk-isearch-skk-mode 'isearch-command t)
648 \f
649 (provide 'skk-isearch)
650
651 ;;; skk-isearch.el ends here