2
;; Copyright (c) 2005-2006 uim Project http://uim.freedesktop.org/
4
;; All rights reserved.
6
;; Redistribution and use in source and binary forms, with or
7
;; without modification, are permitted provided that the
8
;; following conditions are met:
10
;; 1. Redistributions of source code must retain the above
11
;; copyright notice, this list of conditions and the
12
;; following disclaimer.
13
;; 2. Redistributions in binary form must reproduce the above
14
;; copyright notice, this list of conditions and the
15
;; following disclaimer in the documentation and/or other
16
;; materials provided with the distribution.
17
;; 3. Neither the name of authors nor the names of its
18
;; contributors may be used to endorse or promote products
19
;; derived from this software without specific prior written
22
;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23
;; CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
24
;; INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25
;; MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
;; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27
;; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28
;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29
;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30
;; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31
;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32
;; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
33
;; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34
;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
;; Checks that the candidate list can be displayed inlinely on current window.
40
(defun uim-check-candidate-space ()
41
;; don't show the candidate in mini-buffer
42
;; also thin window is not supported
43
(and (= (minibuffer-depth) 0)
44
(>= (window-width) uim-candidate-minimum-width)))
48
;; Merge formatted text into current buffer
50
(defun uim-merge-candidate ()
52
(let ((maxwidth (string-width (nth 1 (car uim-candidate-line-list))))
53
offset mark-base mark-cursor)
56
(setq uim-candidate-page-label
57
(concat (make-string (- maxwidth
58
(- (string-width uim-candidate-page-label) 1))
59
(if uim-candidate-display-frame ?- 32))
60
uim-candidate-page-label))
62
;; make mark for chasing
63
(setq mark-cursor (point-marker))
65
(goto-char uim-candidate-start)
68
(setq mark-base (point-marker))
69
;;(uim-debug (format "before: %s" (marker-position mark-base)))
71
;; save original string
72
(setq uim-candidate-original-str
73
(buffer-substring uim-candidate-original-start
74
uim-candidate-original-end))
77
(uim-tab-pad-space uim-candidate-original-start
78
uim-candidate-original-end)
81
;; update uim-candidate-start
83
(setq base-ofs (- (marker-position mark-base) uim-candidate-start))
84
(setq uim-candidate-start (+ uim-candidate-start base-ofs)))
86
;;(uim-debug (format "after: %s" (marker-position mark-base)))
88
(set-marker mark-base nil)
90
(goto-char uim-candidate-start)
93
(uim-vertical-motion 0)
95
(uim-string-width (buffer-substring (point) uim-candidate-start))))
97
;;(uim-debug (format "offset: %s" offset))
99
;; if offset + maxwidth >= window-width then reduce offset
100
(if (>= (+ offset maxwidth 2) (window-width))
101
(setq offset (- (- (window-width) 1)
106
(if uim-show-candidate-upward
107
(uim-vertical-motion (- (+ (length uim-candidate-line-list) 1)))
108
(uim-vertical-motion uim-candidate-vofs))
111
mergecount vhead linetmp padding overflow)
114
(setq mergecount (uim-vertical-motion
115
(+ (length uim-candidate-line-list) 1))))
119
(let (candidx candstr candsel)
120
(if uim-candidate-line-list
122
;; normal candidate line
123
(setq candidx (nth 0 (car uim-candidate-line-list)))
125
(uim-format-string (nth 1 (car uim-candidate-line-list))
127
(setq candsel (nth 2 (car uim-candidate-line-list)))
130
(if uim-candidate-display-frame
132
(concat ">" candstr "<")
133
(concat "|" candstr "|"))
135
(concat "[" candstr "]")
136
(concat " " candstr " "))))
142
(if uim-candidate-display-frame
143
(concat "+" uim-candidate-page-label )
144
(concat " " uim-candidate-page-label )))
150
;; go virtual head of the next line
151
(if (not uim-show-candidate-upward)
152
(uim-vertical-motion 1))
161
;; |ABCDEFGH\ + |___aaa__|
164
;; get region from vhead to physical end
166
;; linetmp = ABCDEFGH
169
(truncate-string-to-width (buffer-substring vhead (point))
172
;; make padding by truncating linetmp to offset size
173
;; (add space as padding if shortage)
174
;; witdth of padding is equal to offset
179
(truncate-string-to-width linetmp offset nil 32))
183
(let ((candwidth (+ maxwidth 2)))
185
(if (>= (uim-string-width linetmp) (+ offset candwidth))
187
(truncate-string-to-width linetmp
188
(uim-string-width linetmp)
189
(+ offset candwidth) 32))
192
;; index string selected appendix
195
(delete-region vhead (+ vhead (length linetmp)))
199
(remove-text-properties (- (point) 1) (point)
201
(goto-char (- (point) 1)))
203
(insert (concat padding
212
(uim-set-candidate-face candidx candsel
213
(+ vhead (length padding))
220
(setq uim-candidate-end (point)))
222
(setq mergecount (- mergecount 1))
225
(if uim-show-candidate-upward
226
(uim-vertical-motion 1))
232
(goto-char (point-max))
234
(setq vhead (+ (point) 1))
237
(make-string offset 32)
240
(uim-set-candidate-face candidx candsel
246
(setq uim-candidate-end (point))))))
248
(if uim-candidate-line-list
249
(setq uim-candidate-line-list
250
(cdr uim-candidate-line-list))
255
;; move to end of preedit
256
(if uim-show-candidate-upward
259
(setq uim-candidate-end (point))))
261
(force-mode-line-update)
263
;; update cursor position
266
(goto-char (marker-position mark-cursor))
267
(setq uim-candidate-cursor (point))
269
(set-marker mark-cursor nil)
276
(defun uim-echo-candidate (cand)
278
;; display candidate in minibuffer
283
(page-current (format "%d" (caar cand)))
284
(page-total (format "%d" (cdar cand)))
287
(setq cand (cdr cand))
292
(let ((selected (nth 0 x))
293
(candlabel (nth 1 x))
297
(setq selstart (length cands)))
301
(concat cands "[" candlabel "." candstr "]")
302
(concat cands " " candlabel "." candstr " ")))
305
(setq selend (length cands)))
312
(>= emacs-major-version 21))
313
;; Emcas-21 or Emacs-22
314
(let ((page-space (- (string-width page-total)
315
(string-width page-current)))
318
(concat (if (> page-space 0) (make-string page-space 32))
319
page-current "/" page-total " " cands))
322
;; Emacs-20 or XEmacs
323
(let* ((page-space (- (string-width page-total)
324
(string-width page-current)))
325
(page-label (concat (if (> page-space 0)
326
(make-string page-space 32))
327
page-current "/" page-total " "))
328
(page-width (string-width page-label))
329
(cands-width (string-width cands))
330
(echoreg-width (- (- (window-width) 1) page-width)))
332
(cond ((>= echoreg-width cands-width)
334
(concat page-label cands)))
337
;; | 10/134 [1.xxxxx] 2.yyyyy 3.zzzzz ...|
339
(truncate-string-to-width cands
340
(if (> echoreg-width 3)
346
(make-string (- echoreg-width
347
(string-width cands))
351
((> (string-width (substring cands 0 selstart))
352
(+ (- cands-width echoreg-width) 3))
353
;; | 10/134 ...yyy [3.zzzzz]
355
(truncate-string-to-width cands
357
(+ (- cands-width echoreg-width) 3)))
360
(make-string (- echoreg-width
361
(string-width cands))
365
;; | 10/134 ...[3.zzzzz] ---- ...|
368
(truncate-string-to-width (substring cands selstart)
369
(if (> echoreg-width 6)
376
(make-string (- echoreg-width
377
(string-width cands))
380
(let (message-log-max)
389
;; Make candidate list to be displayed
390
(defun uim-make-candlist (cand)
391
;; cand: (( <nil|t> "candlabel" "candstr" ) ... )
394
(truncwidth (min (- (window-width) 3)
395
(max (+ uim-max-candlabel uim-max-candstr 1)
396
(- (string-width uim-candidate-page-label) 1))))
401
(let ((selected (nth 0 x))
402
(candlabel (nth 1 x))
406
(concat (make-string (- uim-max-candlabel
407
(string-width candlabel)) 32)
410
(setq candstr (concat candlabel "." candstr))
412
(catch 'truncate-loop
415
(let* ((trunc (truncate-string-to-width candstr
417
(width-truncated (string-width trunc))
423
(list i (concat trunc
424
(make-string (- truncwidth
429
(if (= width-truncated (string-width candstr))
430
(throw 'truncate-loop t))
432
(if (not candlabelpad)
434
(make-string (+ (string-width candlabel) 1) 32)))
438
(truncate-string-to-width candstr
439
(string-width candstr)
446
(setq uim-candidate-line-list candlist)
455
(defun uim-set-candidate-face (index selected begin length)
459
(setq face 'uim-candidate-selected-face))
461
(setq face 'uim-candidate-nth-face))
463
(setq face 'uim-candidate-odd-face))
465
(setq face 'uim-candidate-even-face)))
467
(put-text-property begin (+ begin length) 'face face)
474
(defun uim-check-overlay (head tail)
475
(if (> head (point-min))
476
(setq head (- head 1)))
478
(if (< tail (point-max))
479
(setq tail (+ tail 1)))
481
(overlays-in head tail))
485
;; Insert candidate string
487
(defun uim-show-candidate (candidate)
490
;; separate appendix (for prime...)
492
(cons (car candidate)
495
(let ((selected (nth 0 x))
496
(candlabel (nth 1 x))
499
;; separate appendix (for prime...)
500
(if (string-match "\t" candstr)
501
(setq candstr (substring candstr 0 (match-beginning 0))))
502
(list selected candlabel candstr)
506
(setq uim-max-candlabel
508
(mapcar '(lambda (x) (string-width (nth 1 x)))
512
(setq uim-max-candstr
514
(mapcar '(lambda (x) (string-width (nth 2 x)))
517
(setq uim-candidate-page-label
518
(format "%d/%d" (caar candidate) (cdar candidate)))
520
(setq uim-candidate-original-start nil)
521
(setq uim-candidate-original-end nil)
523
(let ((display-inline uim-candidate-display-inline))
525
(if (>= (max (+ uim-max-candlabel 6)
526
(+ (string-width uim-candidate-page-label) 2))
529
(setq display-inline nil)
530
(uim-debug "disable inline: window is too thin")
535
(uim-make-candlist (cdr candidate)))
540
(goto-char uim-candidate-start)
542
(let ((winofs (uim-get-window-offset))
543
(candlines (+ 1 (length uim-candidate-line-list)))
544
ol-down dhead dtail uhead utail)
546
(if (and (not (setq ol-down (uim-check-overlay
549
(setq dhead (point)))
552
(+ uim-candidate-vofs
555
(setq dtail(point))))))
556
(>= (- (- (window-height) 1) (+ winofs 1))
560
(setq uim-show-candidate-upward nil)
561
(setq uim-candidate-original-start dhead)
562
(setq uim-candidate-original-end dtail)
565
(if (and (>= winofs candlines)
566
(not (uim-check-overlay
568
(uim-vertical-motion (- candlines))
570
(setq uhead (point)))
573
(setq utail (point)))))
576
(setq uim-show-candidate-upward t)
577
(setq uim-candidate-original-start uhead)
578
(setq uim-candidate-original-end utail)
583
(let* ((fspace (- (- (- (window-height) 1) winofs) 1))
584
(vshift (- candlines fspace)))
585
(setq uim-show-candidate-upward nil)
586
(setq uim-window-force-scrolled t)
588
(setq uim-candidate-original-start dhead)
589
(setq uim-candidate-original-end dtail)
591
(if (> vshift winofs)
594
;;(uim-debug (format "vshift %s" vshift))
595
(uim-vertical-motion (- (- (window-height)
598
;; disable inline display
599
(setq display-inline nil)
601
;;(uim-debug (format "ol-down %s" ol-down))
605
(if (not display-inline)
606
(uim-debug "disable inline"))
610
;; inline candidate display mode
611
(let ((inhibit-read-only t))
612
(uim-merge-candidate))
613
;; display in echo region
614
(uim-echo-candidate candidate)
622
(defun uim-remove-candidate ()
623
(if (and uim-candidate-display-inline
624
uim-candidate-original-start)
625
(let ((inhibit-read-only t))
627
;; delete region which includes candidate
628
(delete-region uim-candidate-original-start
631
;; restore original region
633
(goto-char uim-candidate-original-start)
634
(insert uim-candidate-original-str))
639
(let (message-log-max)
647
(provide 'uim-candidate)