Merge from emacs-24; up to 2012-12-10T20:27:33Z!eggert@cs.ucla.edu
[emacs.git] / lisp / vc / ediff-wind.el
blob81109906262d7e41c03882dd92a46c998673f201
1 ;;; ediff-wind.el --- window manipulation utilities
3 ;; Copyright (C) 1994-1997, 2000-2013 Free Software Foundation, Inc.
5 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
6 ;; Package: ediff
8 ;; This file is part of GNU Emacs.
10 ;; GNU Emacs is free software: you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation, either version 3 of the License, or
13 ;; (at your option) any later version.
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
23 ;;; Commentary:
25 ;;; Code:
28 ;; Compiler pacifier
29 (defvar icon-title-format)
30 (defvar top-toolbar-height)
31 (defvar bottom-toolbar-height)
32 (defvar left-toolbar-height)
33 (defvar right-toolbar-height)
34 (defvar left-toolbar-width)
35 (defvar right-toolbar-width)
36 (defvar default-menubar)
37 (defvar top-gutter)
38 (defvar frame-icon-title-format)
39 (defvar ediff-diff-status)
41 ;; declare-function does not exist in XEmacs
42 (eval-and-compile
43 (unless (fboundp 'declare-function) (defmacro declare-function (&rest r))))
45 (eval-when-compile
46 (require 'ediff-util)
47 (require 'ediff-help))
48 ;; end pacifier
50 (require 'ediff-init)
52 ;; be careful with ediff-tbar
53 (if (featurep 'xemacs)
54 (require 'ediff-tbar)
55 (defun ediff-compute-toolbar-width () 0))
57 (defgroup ediff-window nil
58 "Ediff window manipulation."
59 :prefix "ediff-"
60 :group 'ediff
61 :group 'frames)
64 ;; Determine which window setup function to use based on current window system.
65 (defun ediff-choose-window-setup-function-automatically ()
66 (declare (obsolete ediff-setup-windows-default "24.3"))
67 (if (ediff-window-display-p)
68 'ediff-setup-windows-multiframe
69 'ediff-setup-windows-plain))
71 (defcustom ediff-window-setup-function 'ediff-setup-windows-default
72 "Function called to set up windows.
73 Ediff provides a choice of three functions:
74 (1) `ediff-setup-windows-multiframe', which sets the control panel
75 in a separate frame.
76 (2) `ediff-setup-windows-plain', which does everything in one frame
77 (3) `ediff-setup-windows-default' (the default), which does (1)
78 on a graphical display and (2) on a text terminal.
80 The command \\[ediff-toggle-multiframe] can be used to toggle
81 between the multiframe display and the single frame display. If
82 the multiframe function detects that one of the buffers A/B is
83 seen in some other frame, it will try to keep that buffer in that
84 frame.
86 If you don't like any of the two provided functions, write your own one.
87 The basic guidelines:
88 1. It should leave the control buffer current and the control window
89 selected.
90 2. It should set `ediff-window-A', `ediff-window-B', `ediff-window-C',
91 and `ediff-control-window' to contain window objects that display
92 the corresponding buffers.
93 3. It should accept the following arguments:
94 buffer-A, buffer-B, buffer-C, control-buffer
95 Buffer C may not be used in jobs that compare only two buffers.
96 If you plan to do something fancy, take a close look at how the two
97 provided functions are written."
98 :type '(choice (const :tag "Choose Automatically" ediff-setup-windows-default)
99 (const :tag "Multi Frame" ediff-setup-windows-multiframe)
100 (const :tag "Single Frame" ediff-setup-windows-plain)
101 (function :tag "Other function"))
102 :group 'ediff-window
103 :version "24.3")
105 ;; indicates if we are in a multiframe setup
106 (ediff-defvar-local ediff-multiframe nil "")
108 ;; Share of the frame occupied by the merge window (buffer C)
109 (ediff-defvar-local ediff-merge-window-share 0.45 "")
111 ;; The control window.
112 (ediff-defvar-local ediff-control-window nil "")
113 ;; Official window for buffer A
114 (ediff-defvar-local ediff-window-A nil "")
115 ;; Official window for buffer B
116 (ediff-defvar-local ediff-window-B nil "")
117 ;; Official window for buffer C
118 (ediff-defvar-local ediff-window-C nil "")
119 ;; Ediff's window configuration.
120 ;; Used to minimize the need to rearrange windows.
121 (ediff-defvar-local ediff-window-config-saved "" "")
123 ;; Association between buff-type and ediff-window-*
124 (defconst ediff-window-alist
125 '((A . ediff-window-A)
126 (?A . ediff-window-A)
127 (B . ediff-window-B)
128 (?B . ediff-window-B)
129 (C . ediff-window-C)
130 (?C . ediff-window-C)))
133 (defcustom ediff-split-window-function 'split-window-vertically
134 "The function used to split the main window between buffer-A and buffer-B.
135 You can set it to a horizontal split instead of the default vertical split
136 by setting this variable to `split-window-horizontally'.
137 You can also have your own function to do fancy splits.
138 This variable has no effect when buffer-A/B are shown in different frames.
139 In this case, Ediff will use those frames to display these buffers."
140 :type '(choice
141 (const :tag "Split vertically" split-window-vertically)
142 (const :tag "Split horizontally" split-window-horizontally)
143 function)
144 :group 'ediff-window)
146 (defcustom ediff-merge-split-window-function 'split-window-horizontally
147 "The function used to split the main window between buffer-A and buffer-B.
148 You can set it to a vertical split instead of the default horizontal split
149 by setting this variable to `split-window-vertically'.
150 You can also have your own function to do fancy splits.
151 This variable has no effect when buffer-A/B/C are shown in different frames.
152 In this case, Ediff will use those frames to display these buffers."
153 :type '(choice
154 (const :tag "Split vertically" split-window-vertically)
155 (const :tag "Split horizontally" split-window-horizontally)
156 function)
157 :group 'ediff-window)
159 ;; Definitions hidden from the compiler by compat wrappers.
160 (declare-function ediff-display-pixel-width "ediff-init")
161 (declare-function ediff-display-pixel-height "ediff-init")
163 (defconst ediff-control-frame-parameters
164 (list
165 '(name . "Ediff")
166 ;;'(unsplittable . t)
167 '(minibuffer . nil)
168 '(user-position . t) ; Emacs only
169 '(vertical-scroll-bars . nil) ; Emacs only
170 '(scrollbar-width . 0) ; XEmacs only
171 '(scrollbar-height . 0) ; XEmacs only
172 '(menu-bar-lines . 0) ; Emacs only
173 '(tool-bar-lines . 0) ; Emacs 21+ only
174 '(left-fringe . 0)
175 '(right-fringe . 0)
176 ;; don't lower but auto-raise
177 '(auto-lower . nil)
178 '(auto-raise . t)
179 '(visibility . nil)
180 ;; make initial frame small to avoid distraction
181 '(width . 1) '(height . 1)
182 ;; this blocks queries from window manager as to where to put
183 ;; ediff's control frame. we put the frame outside the display,
184 ;; so the initial frame won't jump all over the screen
185 (cons 'top (if (fboundp 'ediff-display-pixel-height)
186 (1+ (ediff-display-pixel-height))
187 3000))
188 (cons 'left (if (fboundp 'ediff-display-pixel-width)
189 (1+ (ediff-display-pixel-width))
190 3000))
192 "Frame parameters for displaying Ediff Control Panel.
193 Used internally---not a user option.")
195 ;; position of the mouse; used to decide whether to warp the mouse into ctl
196 ;; frame
197 (ediff-defvar-local ediff-mouse-pixel-position nil "")
199 ;; not used for now
200 (defvar ediff-mouse-pixel-threshold 30
201 "If the user moves mouse more than this many pixels, Ediff won't warp mouse into control window.")
203 (defcustom ediff-grab-mouse t
204 "If t, Ediff will always grab the mouse and put it in the control frame.
205 If 'maybe, Ediff will do it sometimes, but not after operations that require
206 relatively long time. If nil, the mouse will be entirely user's
207 responsibility."
208 :type 'boolean
209 :group 'ediff-window)
211 (defcustom ediff-control-frame-position-function 'ediff-make-frame-position
212 "Function to call to determine the desired location for the control panel.
213 Expects three parameters: the control buffer, the desired width and height
214 of the control frame. It returns an association list
215 of the form \(\(top . <position>\) \(left . <position>\)\)"
216 :type 'function
217 :group 'ediff-window)
219 (defcustom ediff-control-frame-upward-shift 42
220 "The upward shift of control frame from the top of buffer A's frame.
221 Measured in pixels.
222 This is used by the default control frame positioning function,
223 `ediff-make-frame-position'. This variable is provided for easy
224 customization of the default control frame positioning."
225 :type 'integer
226 :group 'ediff-window)
228 (defcustom ediff-narrow-control-frame-leftward-shift (if (featurep 'xemacs) 7 3)
229 "The leftward shift of control frame from the right edge of buf A's frame.
230 Measured in characters.
231 This is used by the default control frame positioning function,
232 `ediff-make-frame-position' to adjust the position of the control frame
233 when it shows the short menu. This variable is provided for easy
234 customization of the default."
235 :type 'integer
236 :group 'ediff-window)
238 (defcustom ediff-wide-control-frame-rightward-shift 7
239 "The rightward shift of control frame from the left edge of buf A's frame.
240 Measured in characters.
241 This is used by the default control frame positioning function,
242 `ediff-make-frame-position' to adjust the position of the control frame
243 when it shows the full menu. This variable is provided for easy
244 customization of the default."
245 :type 'integer
246 :group 'ediff-window)
249 ;; Wide frame display
251 ;; t means Ediff is using wide display
252 (ediff-defvar-local ediff-wide-display-p nil "")
253 ;; keeps frame config for toggling wide display
254 (ediff-defvar-local ediff-wide-display-orig-parameters nil
255 "Frame parameters to be restored when the user wants to toggle the wide
256 display off.")
257 (ediff-defvar-local ediff-wide-display-frame nil
258 "Frame to be used for wide display.")
259 (ediff-defvar-local ediff-make-wide-display-function 'ediff-make-wide-display
260 "The value is a function that is called to create a wide display.
261 The function is called without arguments. It should resize the frame in
262 which buffers A, B, and C are to be displayed, and it should save the old
263 frame parameters in `ediff-wide-display-orig-parameters'.
264 The variable `ediff-wide-display-frame' should be set to contain
265 the frame used for the wide display.")
267 ;; Frame used for the control panel in a windowing system.
268 (ediff-defvar-local ediff-control-frame nil "")
270 (defcustom ediff-prefer-iconified-control-frame nil
271 "If t, keep control panel iconified when help message is off.
272 This has effect only on a windowing system.
273 If t, hitting `?' to toggle control panel off iconifies it.
275 This is only useful in Emacs and only for certain kinds of window managers,
276 such as TWM and its derivatives, since the window manager must permit
277 keyboard input to go into icons. XEmacs completely ignores keyboard input
278 into icons, regardless of the window manager."
279 :type 'boolean
280 :group 'ediff-window)
282 ;;; Functions
284 (defun ediff-get-window-by-clicking (wind prev-wind wind-number)
285 (let (event)
286 (message
287 "Select windows by clicking. Please click on Window %d " wind-number)
288 (while (not (ediff-mouse-event-p (setq event (ediff-read-event))))
289 (if (sit-for 1) ; if sequence of events, wait till the final word
290 (beep 1))
291 (message "Please click on Window %d " wind-number))
292 (ediff-read-event) ; discard event
293 (setq wind (if (featurep 'xemacs)
294 (event-window event)
295 (posn-window (event-start event))))))
298 ;; Select the lowest window on the frame.
299 (defun ediff-select-lowest-window ()
300 (if (featurep 'xemacs)
301 (select-window (frame-lowest-window))
302 (let* ((lowest-window (selected-window))
303 (bottom-edge (car (cdr (cdr (cdr (window-edges))))))
304 (last-window (save-excursion
305 (other-window -1) (selected-window)))
306 (window-search t))
307 (while window-search
308 (let* ((this-window (next-window))
309 (next-bottom-edge
310 (car (cdr (cdr (cdr (window-edges this-window)))))))
311 (if (< bottom-edge next-bottom-edge)
312 (setq bottom-edge next-bottom-edge
313 lowest-window this-window))
314 (select-window this-window)
315 (when (eq last-window this-window)
316 (select-window lowest-window)
317 (setq window-search nil)))))))
320 ;;; Common window setup routines
322 ;; Set up the window configuration. If POS is given, set the points to
323 ;; the beginnings of the buffers.
324 ;; When 3way comparison is added, this will have to choose the appropriate
325 ;; setup function based on ediff-job-name
326 (defun ediff-setup-windows (buffer-A buffer-B buffer-C control-buffer)
327 ;; Make sure we are not in the minibuffer window when we try to delete
328 ;; all other windows.
329 (run-hooks 'ediff-before-setup-windows-hook)
330 (if (eq (selected-window) (minibuffer-window))
331 (other-window 1))
333 ;; in case user did a no-no on a tty
334 (or (ediff-window-display-p)
335 (setq ediff-window-setup-function 'ediff-setup-windows-plain))
337 (or (ediff-keep-window-config control-buffer)
338 (funcall
339 (ediff-with-current-buffer control-buffer ediff-window-setup-function)
340 buffer-A buffer-B buffer-C control-buffer))
341 (run-hooks 'ediff-after-setup-windows-hook))
343 (defun ediff-setup-windows-default (buffer-A buffer-B buffer-C control-buffer)
344 (funcall (if (display-graphic-p)
345 'ediff-setup-windows-multiframe
346 'ediff-setup-windows-plain)
347 buffer-A buffer-B buffer-C control-buffer))
349 ;; Just set up 3 windows.
350 ;; Usually used without windowing systems
351 ;; With windowing, we want to use dedicated frames.
352 (defun ediff-setup-windows-plain (buffer-A buffer-B buffer-C control-buffer)
353 (ediff-with-current-buffer control-buffer
354 (setq ediff-multiframe nil))
355 (if ediff-merge-job
356 (ediff-setup-windows-plain-merge
357 buffer-A buffer-B buffer-C control-buffer)
358 (ediff-setup-windows-plain-compare
359 buffer-A buffer-B buffer-C control-buffer)))
361 (defun ediff-setup-windows-plain-merge (buf-A buf-B buf-C control-buffer)
362 ;; skip dedicated and unsplittable frames
363 (ediff-destroy-control-frame control-buffer)
364 (let ((window-min-height 1)
365 split-window-function
366 merge-window-share merge-window-lines
367 wind-A wind-B wind-C)
368 (ediff-with-current-buffer control-buffer
369 (setq merge-window-share ediff-merge-window-share
370 ;; this lets us have local versions of ediff-split-window-function
371 split-window-function ediff-split-window-function))
372 (delete-other-windows)
373 (set-window-dedicated-p (selected-window) nil)
374 (split-window-vertically)
375 (ediff-select-lowest-window)
376 (ediff-setup-control-buffer control-buffer)
378 ;; go to the upper window and split it betw A, B, and possibly C
379 (other-window 1)
380 (setq merge-window-lines
381 (max 2 (round (* (window-height) merge-window-share))))
382 (switch-to-buffer buf-A)
383 (setq wind-A (selected-window))
385 ;; XEmacs used to have a lot of trouble with display
386 ;; It did't set things right unless we tell it to sit still
387 ;; 19.12 seems ok.
388 ;;(if (featurep 'xemacs) (sit-for 0))
390 (split-window-vertically (max 2 (- (window-height) merge-window-lines)))
391 (if (eq (selected-window) wind-A)
392 (other-window 1))
393 (setq wind-C (selected-window))
394 (switch-to-buffer buf-C)
396 (select-window wind-A)
397 (funcall split-window-function)
399 (if (eq (selected-window) wind-A)
400 (other-window 1))
401 (switch-to-buffer buf-B)
402 (setq wind-B (selected-window))
404 (ediff-with-current-buffer control-buffer
405 (setq ediff-window-A wind-A
406 ediff-window-B wind-B
407 ediff-window-C wind-C))
409 (ediff-select-lowest-window)
410 (ediff-setup-control-buffer control-buffer)
414 ;; This function handles all comparison jobs, including 3way jobs
415 (defun ediff-setup-windows-plain-compare (buf-A buf-B buf-C control-buffer)
416 ;; skip dedicated and unsplittable frames
417 (ediff-destroy-control-frame control-buffer)
418 (let ((window-min-height 1)
419 split-window-function wind-width-or-height
420 three-way-comparison
421 wind-A-start wind-B-start wind-A wind-B wind-C)
422 (ediff-with-current-buffer control-buffer
423 (setq wind-A-start (ediff-overlay-start
424 (ediff-get-value-according-to-buffer-type
425 'A ediff-narrow-bounds))
426 wind-B-start (ediff-overlay-start
427 (ediff-get-value-according-to-buffer-type
428 'B ediff-narrow-bounds))
429 ;; this lets us have local versions of ediff-split-window-function
430 split-window-function ediff-split-window-function
431 three-way-comparison ediff-3way-comparison-job))
432 ;; if in minibuffer go somewhere else
433 (if (save-match-data
434 (string-match "\*Minibuf-" (buffer-name (window-buffer))))
435 (select-window (next-window nil 'ignore-minibuf)))
436 (delete-other-windows)
437 (set-window-dedicated-p (selected-window) nil)
438 (split-window-vertically)
439 (ediff-select-lowest-window)
440 (ediff-setup-control-buffer control-buffer)
442 ;; go to the upper window and split it betw A, B, and possibly C
443 (other-window 1)
444 (switch-to-buffer buf-A)
445 (setq wind-A (selected-window))
446 (if three-way-comparison
447 (setq wind-width-or-height
448 (/ (if (eq split-window-function 'split-window-vertically)
449 (window-height wind-A)
450 (window-width wind-A))
451 3)))
453 ;; XEmacs used to have a lot of trouble with display
454 ;; It did't set things right unless we told it to sit still
455 ;; 19.12 seems ok.
456 ;;(if (featurep 'xemacs) (sit-for 0))
458 (funcall split-window-function wind-width-or-height)
460 (if (eq (selected-window) wind-A)
461 (other-window 1))
462 (switch-to-buffer buf-B)
463 (setq wind-B (selected-window))
465 (if three-way-comparison
466 (progn
467 (funcall split-window-function) ; equally
468 (if (eq (selected-window) wind-B)
469 (other-window 1))
470 (switch-to-buffer buf-C)
471 (setq wind-C (selected-window))))
473 (ediff-with-current-buffer control-buffer
474 (setq ediff-window-A wind-A
475 ediff-window-B wind-B
476 ediff-window-C wind-C))
478 ;; It is unlikely that we will want to implement 3way window comparison.
479 ;; So, only buffers A and B are used here.
480 (if ediff-windows-job
481 (progn
482 (set-window-start wind-A wind-A-start)
483 (set-window-start wind-B wind-B-start)))
485 (ediff-select-lowest-window)
486 (ediff-setup-control-buffer control-buffer)
490 ;; dispatch an appropriate window setup function
491 (defun ediff-setup-windows-multiframe (buf-A buf-B buf-C control-buf)
492 (ediff-with-current-buffer control-buf
493 (setq ediff-multiframe t))
494 (if ediff-merge-job
495 (ediff-setup-windows-multiframe-merge buf-A buf-B buf-C control-buf)
496 (ediff-setup-windows-multiframe-compare buf-A buf-B buf-C control-buf)))
498 (defun ediff-setup-windows-multiframe-merge (buf-A buf-B buf-C control-buf)
499 ;;; Algorithm:
500 ;;; 1. Never use frames that have dedicated windows in them---it is bad to
501 ;;; destroy dedicated windows.
502 ;;; 2. If A and B are in the same frame but C's frame is different--- use one
503 ;;; frame for A and B and use a separate frame for C.
504 ;;; 3. If C's frame is non-existent, then: if the first suitable
505 ;;; non-dedicated frame is different from A&B's, then use it for C.
506 ;;; Otherwise, put A,B, and C in one frame.
507 ;;; 4. If buffers A, B, C are is separate frames, use them to display these
508 ;;; buffers.
510 ;; Skip dedicated or iconified frames.
511 ;; Unsplittable frames are taken care of later.
512 (ediff-skip-unsuitable-frames 'ok-unsplittable)
514 (let* ((window-min-height 1)
515 (wind-A (ediff-get-visible-buffer-window buf-A))
516 (wind-B (ediff-get-visible-buffer-window buf-B))
517 (wind-C (ediff-get-visible-buffer-window buf-C))
518 (frame-A (if wind-A (window-frame wind-A)))
519 (frame-B (if wind-B (window-frame wind-B)))
520 (frame-C (if wind-C (window-frame wind-C)))
521 ;; on wide display, do things in one frame
522 (force-one-frame
523 (ediff-with-current-buffer control-buf ediff-wide-display-p))
524 ;; this lets us have local versions of ediff-split-window-function
525 (split-window-function
526 (ediff-with-current-buffer control-buf ediff-split-window-function))
527 (orig-wind (selected-window))
528 (orig-frame (selected-frame))
529 (use-same-frame (or force-one-frame
530 ;; A and C must be in one frame
531 (eq frame-A (or frame-C orig-frame))
532 ;; B and C must be in one frame
533 (eq frame-B (or frame-C orig-frame))
534 ;; A or B is not visible
535 (not (frame-live-p frame-A))
536 (not (frame-live-p frame-B))
537 ;; A or B is not suitable for display
538 (not (ediff-window-ok-for-display wind-A))
539 (not (ediff-window-ok-for-display wind-B))
540 ;; A and B in the same frame, and no good frame
541 ;; for C
542 (and (eq frame-A frame-B)
543 (not (frame-live-p frame-C)))
545 ;; use-same-frame-for-AB implies wind A and B are ok for display
546 (use-same-frame-for-AB (and (not use-same-frame)
547 (eq frame-A frame-B)))
548 (merge-window-share (ediff-with-current-buffer control-buf
549 ediff-merge-window-share))
550 merge-window-lines
551 designated-minibuffer-frame
552 done-A done-B done-C)
554 ;; buf-A on its own
555 (if (and (window-live-p wind-A)
556 (null use-same-frame) ; implies wind-A is suitable
557 (null use-same-frame-for-AB))
558 (progn ; bug A on its own
559 ;; buffer buf-A is seen in live wind-A
560 (select-window wind-A)
561 (delete-other-windows)
562 (setq wind-A (selected-window))
563 (setq done-A t)))
565 ;; buf-B on its own
566 (if (and (window-live-p wind-B)
567 (null use-same-frame) ; implies wind-B is suitable
568 (null use-same-frame-for-AB))
569 (progn ; buf B on its own
570 ;; buffer buf-B is seen in live wind-B
571 (select-window wind-B)
572 (delete-other-windows)
573 (setq wind-B (selected-window))
574 (setq done-B t)))
576 ;; buf-C on its own
577 (if (and (window-live-p wind-C)
578 (ediff-window-ok-for-display wind-C)
579 (null use-same-frame)) ; buf C on its own
580 (progn
581 ;; buffer buf-C is seen in live wind-C
582 (select-window wind-C)
583 (delete-other-windows)
584 (setq wind-C (selected-window))
585 (setq done-C t)))
587 (if (and use-same-frame-for-AB ; implies wind A and B are suitable
588 (window-live-p wind-A))
589 (progn
590 ;; wind-A must already be displaying buf-A
591 (select-window wind-A)
592 (delete-other-windows)
593 (setq wind-A (selected-window))
595 (funcall split-window-function)
596 (if (eq (selected-window) wind-A)
597 (other-window 1))
598 (switch-to-buffer buf-B)
599 (setq wind-B (selected-window))
601 (setq done-A t
602 done-B t)))
604 (if use-same-frame
605 (let ((window-min-height 1))
606 (if (and (eq frame-A frame-B)
607 (eq frame-B frame-C)
608 (frame-live-p frame-A))
609 (select-frame frame-A)
610 ;; avoid dedicated and non-splittable windows
611 (ediff-skip-unsuitable-frames))
612 (delete-other-windows)
613 (setq merge-window-lines
614 (max 2 (round (* (window-height) merge-window-share))))
615 (switch-to-buffer buf-A)
616 (setq wind-A (selected-window))
618 (split-window-vertically
619 (max 2 (- (window-height) merge-window-lines)))
620 (if (eq (selected-window) wind-A)
621 (other-window 1))
622 (setq wind-C (selected-window))
623 (switch-to-buffer buf-C)
625 (select-window wind-A)
627 (funcall split-window-function)
628 (if (eq (selected-window) wind-A)
629 (other-window 1))
630 (switch-to-buffer buf-B)
631 (setq wind-B (selected-window))
633 (setq done-A t
634 done-B t
635 done-C t)
638 (or done-A ; Buf A to be set in its own frame,
639 ;;; or it was set before because use-same-frame = 1
640 (progn
641 ;; Buf-A was not set up yet as it wasn't visible,
642 ;; and use-same-frame = nil, use-same-frame-for-AB = nil
643 (select-window orig-wind)
644 (delete-other-windows)
645 (switch-to-buffer buf-A)
646 (setq wind-A (selected-window))
648 (or done-B ; Buf B to be set in its own frame,
649 ;;; or it was set before because use-same-frame = 1
650 (progn
651 ;; Buf-B was not set up yet as it wasn't visible
652 ;; and use-same-frame = nil, use-same-frame-for-AB = nil
653 (select-window orig-wind)
654 (delete-other-windows)
655 (switch-to-buffer buf-B)
656 (setq wind-B (selected-window))
659 (or done-C ; Buf C to be set in its own frame,
660 ;;; or it was set before because use-same-frame = 1
661 (progn
662 ;; Buf-C was not set up yet as it wasn't visible
663 ;; and use-same-frame = nil
664 (select-window orig-wind)
665 (delete-other-windows)
666 (switch-to-buffer buf-C)
667 (setq wind-C (selected-window))
670 (ediff-with-current-buffer control-buf
671 (setq ediff-window-A wind-A
672 ediff-window-B wind-B
673 ediff-window-C wind-C)
674 (setq frame-A (window-frame ediff-window-A)
675 designated-minibuffer-frame
676 (window-frame (minibuffer-window frame-A))))
678 (ediff-setup-control-frame control-buf designated-minibuffer-frame)
682 ;; Window setup for all comparison jobs, including 3way comparisons
683 (defun ediff-setup-windows-multiframe-compare (buf-A buf-B buf-C control-buf)
684 ;;; Algorithm:
685 ;;; If a buffer is seen in a frame, use that frame for that buffer.
686 ;;; If it is not seen, use the current frame.
687 ;;; If both buffers are not seen, they share the current frame. If one
688 ;;; of the buffers is not seen, it is placed in the current frame (where
689 ;;; ediff started). If that frame is displaying the other buffer, it is
690 ;;; shared between the two buffers.
691 ;;; However, if we decide to put both buffers in one frame
692 ;;; and the selected frame isn't splittable, we create a new frame and
693 ;;; put both buffers there, event if one of this buffers is visible in
694 ;;; another frame.
696 ;; Skip dedicated or iconified frames.
697 ;; Unsplittable frames are taken care of later.
698 (ediff-skip-unsuitable-frames 'ok-unsplittable)
700 (let* ((window-min-height 1)
701 (wind-A (ediff-get-visible-buffer-window buf-A))
702 (wind-B (ediff-get-visible-buffer-window buf-B))
703 (wind-C (ediff-get-visible-buffer-window buf-C))
704 (frame-A (if wind-A (window-frame wind-A)))
705 (frame-B (if wind-B (window-frame wind-B)))
706 (frame-C (if wind-C (window-frame wind-C)))
707 (ctl-frame-exists-p (ediff-with-current-buffer control-buf
708 (frame-live-p ediff-control-frame)))
709 ;; on wide display, do things in one frame
710 (force-one-frame
711 (ediff-with-current-buffer control-buf ediff-wide-display-p))
712 ;; this lets us have local versions of ediff-split-window-function
713 (split-window-function
714 (ediff-with-current-buffer control-buf ediff-split-window-function))
715 (three-way-comparison
716 (ediff-with-current-buffer control-buf ediff-3way-comparison-job))
717 (orig-wind (selected-window))
718 (use-same-frame (or force-one-frame
719 (eq frame-A frame-B)
720 (not (ediff-window-ok-for-display wind-A))
721 (not (ediff-window-ok-for-display wind-B))
722 (if three-way-comparison
723 (or (eq frame-A frame-C)
724 (eq frame-B frame-C)
725 (not (ediff-window-ok-for-display wind-C))
726 (not (frame-live-p frame-A))
727 (not (frame-live-p frame-B))
728 (not (frame-live-p frame-C))))
729 (and (not (frame-live-p frame-B))
730 (or ctl-frame-exists-p
731 (eq frame-A (selected-frame))))
732 (and (not (frame-live-p frame-A))
733 (or ctl-frame-exists-p
734 (eq frame-B (selected-frame))))))
735 wind-A-start wind-B-start
736 designated-minibuffer-frame
737 done-A done-B done-C)
739 (ediff-with-current-buffer control-buf
740 (setq wind-A-start (ediff-overlay-start
741 (ediff-get-value-according-to-buffer-type
742 'A ediff-narrow-bounds))
743 wind-B-start (ediff-overlay-start
744 (ediff-get-value-according-to-buffer-type
745 'B ediff-narrow-bounds))))
747 (if (and (window-live-p wind-A) (null use-same-frame)) ; buf-A on its own
748 (progn
749 ;; buffer buf-A is seen in live wind-A
750 (select-window wind-A) ; must be displaying buf-A
751 (delete-other-windows)
752 (setq wind-A (selected-window))
753 (setq done-A t)))
755 (if (and (window-live-p wind-B) (null use-same-frame)) ; buf B on its own
756 (progn
757 ;; buffer buf-B is seen in live wind-B
758 (select-window wind-B) ; must be displaying buf-B
759 (delete-other-windows)
760 (setq wind-B (selected-window))
761 (setq done-B t)))
763 (if (and (window-live-p wind-C) (null use-same-frame)) ; buf C on its own
764 (progn
765 ;; buffer buf-C is seen in live wind-C
766 (select-window wind-C) ; must be displaying buf-C
767 (delete-other-windows)
768 (setq wind-C (selected-window))
769 (setq done-C t)))
771 (if use-same-frame
772 (let (wind-width-or-height) ; this affects 3way setups only
773 (if (and (eq frame-A frame-B) (frame-live-p frame-A))
774 (select-frame frame-A)
775 ;; avoid dedicated and non-splittable windows
776 (ediff-skip-unsuitable-frames))
777 (delete-other-windows)
778 (switch-to-buffer buf-A)
779 (setq wind-A (selected-window))
781 (if three-way-comparison
782 (setq wind-width-or-height
784 (if (eq split-window-function 'split-window-vertically)
785 (window-height wind-A)
786 (window-width wind-A))
787 3)))
789 (funcall split-window-function wind-width-or-height)
790 (if (eq (selected-window) wind-A)
791 (other-window 1))
792 (switch-to-buffer buf-B)
793 (setq wind-B (selected-window))
795 (if three-way-comparison
796 (progn
797 (funcall split-window-function) ; equally
798 (if (memq (selected-window) (list wind-A wind-B))
799 (other-window 1))
800 (switch-to-buffer buf-C)
801 (setq wind-C (selected-window))))
802 (setq done-A t
803 done-B t
804 done-C t)
807 (or done-A ; Buf A to be set in its own frame
808 ;;; or it was set before because use-same-frame = 1
809 (progn
810 ;; Buf-A was not set up yet as it wasn't visible,
811 ;; and use-same-frame = nil
812 (select-window orig-wind)
813 (delete-other-windows)
814 (switch-to-buffer buf-A)
815 (setq wind-A (selected-window))
817 (or done-B ; Buf B to be set in its own frame
818 ;;; or it was set before because use-same-frame = 1
819 (progn
820 ;; Buf-B was not set up yet as it wasn't visible,
821 ;; and use-same-frame = nil
822 (select-window orig-wind)
823 (delete-other-windows)
824 (switch-to-buffer buf-B)
825 (setq wind-B (selected-window))
828 (if three-way-comparison
829 (or done-C ; Buf C to be set in its own frame
830 ;;; or it was set before because use-same-frame = 1
831 (progn
832 ;; Buf-C was not set up yet as it wasn't visible,
833 ;; and use-same-frame = nil
834 (select-window orig-wind)
835 (delete-other-windows)
836 (switch-to-buffer buf-C)
837 (setq wind-C (selected-window))
840 (ediff-with-current-buffer control-buf
841 (setq ediff-window-A wind-A
842 ediff-window-B wind-B
843 ediff-window-C wind-C)
845 (setq frame-A (window-frame ediff-window-A)
846 designated-minibuffer-frame
847 (window-frame (minibuffer-window frame-A))))
849 ;; It is unlikely that we'll implement a version of ediff-windows that
850 ;; would compare 3 windows at once. So, we don't use buffer C here.
851 (if ediff-windows-job
852 (progn
853 (set-window-start wind-A wind-A-start)
854 (set-window-start wind-B wind-B-start)))
856 (ediff-setup-control-frame control-buf designated-minibuffer-frame)
859 ;; skip unsplittable frames and frames that have dedicated windows.
860 ;; create a new splittable frame if none is found
861 (defun ediff-skip-unsuitable-frames (&optional ok-unsplittable)
862 (if (ediff-window-display-p)
863 (let ((wind-frame (window-frame (selected-window)))
864 seen-windows)
865 (while (and (not (memq (selected-window) seen-windows))
867 (ediff-frame-has-dedicated-windows wind-frame)
868 (ediff-frame-iconified-p wind-frame)
869 ;; skip small windows
870 (< (frame-height wind-frame)
871 (* 3 window-min-height))
872 (if ok-unsplittable
874 (ediff-frame-unsplittable-p wind-frame))))
875 ;; remember history
876 (setq seen-windows (cons (selected-window) seen-windows))
877 ;; try new window
878 (other-window 1 t)
879 (setq wind-frame (window-frame (selected-window)))
881 (if (memq (selected-window) seen-windows)
882 ;; fed up, no appropriate frames
883 (setq wind-frame (make-frame '((unsplittable)))))
885 (select-frame wind-frame)
888 (defun ediff-frame-has-dedicated-windows (frame)
889 (let (ans)
890 (walk-windows
891 (lambda (wind) (if (window-dedicated-p wind)
892 (setq ans t)))
893 'ignore-minibuffer
894 frame)
895 ans))
897 ;; window is ok, if it is only one window on the frame, not counting the
898 ;; minibuffer, or none of the frame's windows is dedicated.
899 ;; The idea is that it is bad to destroy dedicated windows while creating an
900 ;; ediff window setup
901 (defun ediff-window-ok-for-display (wind)
902 (and
903 (window-live-p wind)
905 ;; only one window
906 (eq wind (next-window wind 'ignore-minibuffer (window-frame wind)))
907 ;; none is dedicated (in multiframe setup)
908 (not (ediff-frame-has-dedicated-windows (window-frame wind)))
911 ;; Prepare or refresh control frame
912 (defun ediff-setup-control-frame (ctl-buffer designated-minibuffer-frame)
913 (let ((window-min-height 1)
914 ctl-frame-iconified-p dont-iconify-ctl-frame deiconify-ctl-frame
915 ctl-frame old-ctl-frame lines
916 ;; user-grabbed-mouse
917 fheight fwidth adjusted-parameters)
919 (ediff-with-current-buffer ctl-buffer
920 (if (and (featurep 'xemacs) (featurep 'menubar))
921 (set-buffer-menubar nil))
922 ;;(setq user-grabbed-mouse (ediff-user-grabbed-mouse))
923 (run-hooks 'ediff-before-setup-control-frame-hook))
925 (setq old-ctl-frame (ediff-with-current-buffer ctl-buffer ediff-control-frame))
926 (ediff-with-current-buffer ctl-buffer
927 (setq ctl-frame (if (frame-live-p old-ctl-frame)
928 old-ctl-frame
929 (make-frame ediff-control-frame-parameters))
930 ediff-control-frame ctl-frame)
931 ;; protect against undefined face-attribute
932 (condition-case nil
933 (if (and (featurep 'emacs) (face-attribute 'mode-line :box))
934 (set-face-attribute 'mode-line ctl-frame :box nil))
935 (error)))
937 (setq ctl-frame-iconified-p (ediff-frame-iconified-p ctl-frame))
938 (select-frame ctl-frame)
939 (if (window-dedicated-p (selected-window))
941 (delete-other-windows)
942 (switch-to-buffer ctl-buffer))
944 ;; must be before ediff-setup-control-buffer
945 ;; just a precaution--we should be in ctl-buffer already
946 (ediff-with-current-buffer ctl-buffer
947 (make-local-variable 'frame-title-format)
948 (make-local-variable 'frame-icon-title-format) ; XEmacs
949 (make-local-variable 'icon-title-format)) ; Emacs
951 (ediff-setup-control-buffer ctl-buffer)
952 (setq dont-iconify-ctl-frame
953 (not (string= ediff-help-message ediff-brief-help-message)))
954 (setq deiconify-ctl-frame
955 (and (eq this-command 'ediff-toggle-help)
956 dont-iconify-ctl-frame))
958 ;; 1 more line for the mode line
959 (setq lines (1+ (count-lines (point-min) (point-max)))
960 fheight lines
961 fwidth (max (+ (ediff-help-message-line-length) 2)
962 (ediff-compute-toolbar-width))
963 adjusted-parameters
964 (list
965 ;; possibly change surrogate minibuffer
966 (cons 'minibuffer
967 (minibuffer-window
968 designated-minibuffer-frame))
969 (cons 'width fwidth)
970 (cons 'height fheight)
971 (cons 'user-position t)
974 ;; adjust autoraise
975 (setq adjusted-parameters
976 (cons (if ediff-use-long-help-message
977 '(auto-raise . nil)
978 '(auto-raise . t))
979 adjusted-parameters))
981 ;; In XEmacs, buffer menubar needs to be killed before frame parameters
982 ;; are changed.
983 (if (ediff-has-toolbar-support-p)
984 (when (featurep 'xemacs)
985 (if (ediff-has-gutter-support-p)
986 (set-specifier top-gutter (list ctl-frame nil)))
987 (sit-for 0)
988 (set-specifier top-toolbar-height (list ctl-frame 0))
989 ;;(set-specifier bottom-toolbar-height (list ctl-frame 0))
990 (set-specifier left-toolbar-width (list ctl-frame 0))
991 (set-specifier right-toolbar-width (list ctl-frame 0))))
993 ;; As a precaution, we call modify frame parameters twice, in
994 ;; order to make sure that at least once we do it for
995 ;; a non-iconified frame. (It appears that in the Windows port of
996 ;; Emacs, one can't modify frame parameters of iconified frames.)
997 (if (eq system-type 'windows-nt)
998 (modify-frame-parameters ctl-frame adjusted-parameters))
1000 ;; make or zap toolbar (if not requested)
1001 (ediff-make-bottom-toolbar ctl-frame)
1003 (goto-char (point-min))
1005 (modify-frame-parameters ctl-frame adjusted-parameters)
1006 (make-frame-visible ctl-frame)
1008 ;; This works around a bug in 19.25 and earlier. There, if frame gets
1009 ;; iconified, the current buffer changes to that of the frame that
1010 ;; becomes exposed as a result of this iconification.
1011 ;; So, we make sure the current buffer doesn't change.
1012 (select-frame ctl-frame)
1013 (ediff-refresh-control-frame)
1015 (cond ((and ediff-prefer-iconified-control-frame
1016 (not ctl-frame-iconified-p) (not dont-iconify-ctl-frame))
1017 (iconify-frame ctl-frame))
1018 ((or deiconify-ctl-frame (not ctl-frame-iconified-p))
1019 (raise-frame ctl-frame)))
1021 (set-window-dedicated-p (selected-window) t)
1023 ;; Now move the frame. We must do it separately due to an obscure bug in
1024 ;; XEmacs
1025 (modify-frame-parameters
1026 ctl-frame
1027 (funcall ediff-control-frame-position-function ctl-buffer fwidth fheight))
1029 ;; synchronize so the cursor will move to control frame
1030 ;; per RMS suggestion
1031 (if (ediff-window-display-p)
1032 (let ((count 7))
1033 (sit-for .1)
1034 (while (and (not (frame-visible-p ctl-frame)) (> count 0))
1035 (setq count (1- count))
1036 (sit-for .3))))
1038 (or (ediff-frame-iconified-p ctl-frame)
1039 ;; don't warp the mouse, unless ediff-grab-mouse = t
1040 (ediff-reset-mouse ctl-frame
1041 (or (eq this-command 'ediff-quit)
1042 (not (eq ediff-grab-mouse t)))))
1044 (when (featurep 'xemacs)
1045 (ediff-with-current-buffer ctl-buffer
1046 (make-local-hook 'select-frame-hook)
1047 (add-hook 'select-frame-hook
1048 'ediff-xemacs-select-frame-hook nil 'local)))
1050 (ediff-with-current-buffer ctl-buffer
1051 (run-hooks 'ediff-after-setup-control-frame-hook))))
1054 (defun ediff-destroy-control-frame (ctl-buffer)
1055 (ediff-with-current-buffer ctl-buffer
1056 (if (and (ediff-window-display-p) (frame-live-p ediff-control-frame))
1057 (let ((ctl-frame ediff-control-frame))
1058 (if (and (featurep 'xemacs) (featurep 'menubar))
1059 (set-buffer-menubar default-menubar))
1060 (setq ediff-control-frame nil)
1061 (delete-frame ctl-frame))))
1062 (if ediff-multiframe
1063 (ediff-skip-unsuitable-frames))
1064 ;;(ediff-reset-mouse nil)
1068 ;; finds a good place to clip control frame
1069 (defun ediff-make-frame-position (ctl-buffer ctl-frame-width ctl-frame-height)
1070 (ediff-with-current-buffer ctl-buffer
1071 (let* ((frame-A (window-frame ediff-window-A))
1072 (frame-A-parameters (frame-parameters frame-A))
1073 (frame-A-top (eval (cdr (assoc 'top frame-A-parameters))))
1074 (frame-A-left (eval (cdr (assoc 'left frame-A-parameters))))
1075 (frame-A-width (frame-width frame-A))
1076 (ctl-frame ediff-control-frame)
1077 horizontal-adjustment upward-adjustment
1078 ctl-frame-top ctl-frame-left)
1080 ;; Multiple control frames are clipped based on the value of
1081 ;; ediff-control-buffer-number. This is done in order not to obscure
1082 ;; other active control panels.
1083 (setq horizontal-adjustment (* 2 ediff-control-buffer-number)
1084 upward-adjustment (* -14 ediff-control-buffer-number))
1086 (setq ctl-frame-top
1087 (- frame-A-top upward-adjustment ediff-control-frame-upward-shift)
1088 ctl-frame-left
1089 (+ frame-A-left
1090 (if ediff-use-long-help-message
1091 (* (ediff-frame-char-width ctl-frame)
1092 (+ ediff-wide-control-frame-rightward-shift
1093 horizontal-adjustment))
1094 (- (* frame-A-width (ediff-frame-char-width frame-A))
1095 (* (ediff-frame-char-width ctl-frame)
1096 (+ ctl-frame-width
1097 ediff-narrow-control-frame-leftward-shift
1098 horizontal-adjustment))))))
1099 (setq ctl-frame-top
1100 (min ctl-frame-top
1101 (- (ediff-display-pixel-height)
1102 (* 2 ctl-frame-height
1103 (ediff-frame-char-height ctl-frame))))
1104 ctl-frame-left
1105 (min ctl-frame-left
1106 (- (ediff-display-pixel-width)
1107 (* ctl-frame-width (ediff-frame-char-width ctl-frame)))))
1108 ;; keep ctl frame within the visible bounds
1109 (setq ctl-frame-top (max ctl-frame-top 1)
1110 ctl-frame-left (max ctl-frame-left 1))
1112 (list (cons 'top ctl-frame-top)
1113 (cons 'left ctl-frame-left))
1116 (defun ediff-xemacs-select-frame-hook ()
1117 (if (and (equal (selected-frame) ediff-control-frame)
1118 (not ediff-use-long-help-message))
1119 (raise-frame ediff-control-frame)))
1121 (defun ediff-make-wide-display ()
1122 "Construct an alist of parameters for the wide display.
1123 Saves the old frame parameters in `ediff-wide-display-orig-parameters'.
1124 The frame to be resized is kept in `ediff-wide-display-frame'.
1125 This function modifies only the left margin and the width of the display.
1126 It assumes that it is called from within the control buffer."
1127 (if (not (fboundp 'ediff-display-pixel-width))
1128 (error "Can't determine display width"))
1129 (let* ((frame-A (window-frame ediff-window-A))
1130 (frame-A-params (frame-parameters frame-A))
1131 (cw (ediff-frame-char-width frame-A))
1132 (wd (- (/ (ediff-display-pixel-width) cw) 5)))
1133 (setq ediff-wide-display-orig-parameters
1134 (list (cons 'left (max 0 (eval (cdr (assoc 'left frame-A-params)))))
1135 (cons 'width (cdr (assoc 'width frame-A-params))))
1136 ediff-wide-display-frame frame-A)
1137 (modify-frame-parameters
1138 frame-A `((left . ,cw) (width . ,wd) (user-position . t)))))
1141 ;; Revise the mode line to display which difference we have selected
1142 ;; Also resets mode lines of buffers A/B, since they may be clobbered by
1143 ;; other invocations of Ediff.
1144 (defun ediff-refresh-mode-lines ()
1145 (let (buf-A-state-diff buf-B-state-diff buf-C-state-diff buf-C-state-merge)
1147 (if (ediff-valid-difference-p)
1148 (setq
1149 buf-C-state-diff (ediff-get-state-of-diff ediff-current-difference 'C)
1150 buf-C-state-merge (ediff-get-state-of-merge ediff-current-difference)
1151 buf-A-state-diff (ediff-get-state-of-diff ediff-current-difference 'A)
1152 buf-B-state-diff (ediff-get-state-of-diff ediff-current-difference 'B)
1153 buf-A-state-diff (if buf-A-state-diff
1154 (format "[%s] " buf-A-state-diff)
1156 buf-B-state-diff (if buf-B-state-diff
1157 (format "[%s] " buf-B-state-diff)
1159 buf-C-state-diff (if (and (ediff-buffer-live-p ediff-buffer-C)
1160 (or buf-C-state-diff buf-C-state-merge))
1161 (format "[%s%s%s] "
1162 (or buf-C-state-diff "")
1163 (if buf-C-state-merge
1164 (concat " " buf-C-state-merge)
1166 (if (ediff-get-state-of-ancestor
1167 ediff-current-difference)
1168 " AncestorEmpty"
1171 ""))
1172 (setq buf-A-state-diff ""
1173 buf-B-state-diff ""
1174 buf-C-state-diff ""))
1176 ;; control buffer format
1177 (setq mode-line-format
1178 (if (ediff-narrow-control-frame-p)
1179 (list " " mode-line-buffer-identification)
1180 (list "-- " mode-line-buffer-identification " Quick Help")))
1181 ;; control buffer id
1182 (setq mode-line-buffer-identification
1183 (if (ediff-narrow-control-frame-p)
1184 (ediff-make-narrow-control-buffer-id 'skip-name)
1185 (ediff-make-wide-control-buffer-id)))
1186 ;; Force mode-line redisplay
1187 (force-mode-line-update)
1189 (if (and (ediff-window-display-p) (frame-live-p ediff-control-frame))
1190 (ediff-refresh-control-frame))
1192 (ediff-with-current-buffer ediff-buffer-A
1193 (setq ediff-diff-status buf-A-state-diff)
1194 (ediff-strip-mode-line-format)
1195 (setq mode-line-format
1196 (list " A: " 'ediff-diff-status mode-line-format))
1197 (force-mode-line-update))
1198 (ediff-with-current-buffer ediff-buffer-B
1199 (setq ediff-diff-status buf-B-state-diff)
1200 (ediff-strip-mode-line-format)
1201 (setq mode-line-format
1202 (list " B: " 'ediff-diff-status mode-line-format))
1203 (force-mode-line-update))
1204 (if ediff-3way-job
1205 (ediff-with-current-buffer ediff-buffer-C
1206 (setq ediff-diff-status buf-C-state-diff)
1207 (ediff-strip-mode-line-format)
1208 (setq mode-line-format
1209 (list " C: " 'ediff-diff-status mode-line-format))
1210 (force-mode-line-update)))
1211 (if (ediff-buffer-live-p ediff-ancestor-buffer)
1212 (ediff-with-current-buffer ediff-ancestor-buffer
1213 (ediff-strip-mode-line-format)
1214 ;; we keep the second dummy string in the mode line format of the
1215 ;; ancestor, since for other buffers Ediff prepends 2 strings and
1216 ;; ediff-strip-mode-line-format expects that.
1217 (setq mode-line-format
1218 (list " Ancestor: "
1219 (cond ((not (stringp buf-C-state-merge))
1221 ((string-match "prefer-A" buf-C-state-merge)
1222 "[=diff(B)] ")
1223 ((string-match "prefer-B" buf-C-state-merge)
1224 "[=diff(A)] ")
1225 (t ""))
1226 mode-line-format))))
1230 (defun ediff-refresh-control-frame ()
1231 (if (featurep 'emacs)
1232 ;; set frame/icon titles for Emacs
1233 (modify-frame-parameters
1234 ediff-control-frame
1235 (list (cons 'title (ediff-make-base-title))
1236 (cons 'icon-name (ediff-make-narrow-control-buffer-id))
1238 ;; set frame/icon titles for XEmacs
1239 (setq frame-title-format (ediff-make-base-title)
1240 frame-icon-title-format (ediff-make-narrow-control-buffer-id))
1241 ;; force an update of the frame title
1242 (modify-frame-parameters ediff-control-frame '(()))))
1245 (defun ediff-make-narrow-control-buffer-id (&optional skip-name)
1246 (concat
1247 (if skip-name
1249 (ediff-make-base-title))
1250 (cond ((< ediff-current-difference 0)
1251 (format " _/%d" ediff-number-of-differences))
1252 ((>= ediff-current-difference ediff-number-of-differences)
1253 (format " $/%d" ediff-number-of-differences))
1255 (format " %d/%d"
1256 (1+ ediff-current-difference)
1257 ediff-number-of-differences)))))
1259 (defun ediff-make-base-title ()
1260 (concat
1261 (cdr (assoc 'name ediff-control-frame-parameters))
1262 ediff-control-buffer-suffix))
1264 (defun ediff-make-wide-control-buffer-id ()
1265 (cond ((< ediff-current-difference 0)
1266 (list (format "%%b At start of %d diffs"
1267 ediff-number-of-differences)))
1268 ((>= ediff-current-difference ediff-number-of-differences)
1269 (list (format "%%b At end of %d diffs"
1270 ediff-number-of-differences)))
1272 (list (format "%%b diff %d of %d"
1273 (1+ ediff-current-difference)
1274 ediff-number-of-differences)))))
1278 ;; If buff is not live, return nil
1279 (defun ediff-get-visible-buffer-window (buff)
1280 (if (ediff-buffer-live-p buff)
1281 (if (featurep 'xemacs)
1282 (get-buffer-window buff t)
1283 (get-buffer-window buff 'visible))))
1286 ;;; Functions to decide when to redraw windows
1288 (defun ediff-keep-window-config (control-buf)
1289 (and (eq control-buf (current-buffer))
1290 (/= (buffer-size) 0)
1291 (ediff-with-current-buffer control-buf
1292 (let ((ctl-wind ediff-control-window)
1293 (A-wind ediff-window-A)
1294 (B-wind ediff-window-B)
1295 (C-wind ediff-window-C))
1297 (and
1298 (ediff-window-visible-p A-wind)
1299 (ediff-window-visible-p B-wind)
1300 ;; if buffer C is defined then take it into account
1301 (or (not ediff-3way-job)
1302 (ediff-window-visible-p C-wind))
1303 (eq (window-buffer A-wind) ediff-buffer-A)
1304 (eq (window-buffer B-wind) ediff-buffer-B)
1305 (or (not ediff-3way-job)
1306 (eq (window-buffer C-wind) ediff-buffer-C))
1307 (string= ediff-window-config-saved
1308 (format "%S%S%S%S%S%S%S"
1309 ctl-wind A-wind B-wind C-wind
1310 ediff-split-window-function
1311 (ediff-multiframe-setup-p)
1312 ediff-wide-display-p)))))))
1315 (provide 'ediff-wind)
1318 ;; Local Variables:
1319 ;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
1320 ;; eval: (put 'ediff-with-current-buffer 'lisp-indent-hook 1)
1321 ;; eval: (put 'ediff-with-current-buffer 'edebug-form-spec '(form body))
1322 ;; End:
1324 ;;; ediff-wind.el ends here