Show ancestor buffer in 3way merges
[emacs.git] / lisp / vc / ediff-wind.el
blob8516c11d136d6f5db204dd1df35cfc57d619ce00
1 ;;; ediff-wind.el --- window manipulation utilities
3 ;; Copyright (C) 1994-1997, 2000-2017 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 (require 'ediff-init)
46 (require 'ediff-help)
47 ;; end pacifier
50 ;; be careful with ediff-tbar
51 (eval-and-compile
52 (if (featurep 'xemacs)
53 (require 'ediff-tbar)
54 (defun ediff-compute-toolbar-width () 0)))
56 (defgroup ediff-window nil
57 "Ediff window manipulation."
58 :prefix "ediff-"
59 :group 'ediff
60 :group 'frames)
63 ;; Determine which window setup function to use based on current window system.
64 (defun ediff-choose-window-setup-function-automatically ()
65 (declare (obsolete ediff-setup-windows-default "24.3"))
66 (if (ediff-window-display-p)
67 'ediff-setup-windows-multiframe
68 'ediff-setup-windows-plain))
70 (defcustom ediff-window-setup-function 'ediff-setup-windows-default
71 "Function called to set up windows.
72 Ediff provides a choice of three functions:
73 (1) `ediff-setup-windows-multiframe', which sets the control panel
74 in a separate frame.
75 (2) `ediff-setup-windows-plain', which does everything in one frame
76 (3) `ediff-setup-windows-default' (the default), which does (1)
77 on a graphical display and (2) on a text terminal.
79 The command \\[ediff-toggle-multiframe] can be used to toggle
80 between the multiframe display and the single frame display. If
81 the multiframe function detects that one of the buffers A/B is
82 seen in some other frame, it will try to keep that buffer in that
83 frame.
85 If you don't like any of the two provided functions, write your own one.
86 The basic guidelines:
87 1. It should leave the control buffer current and the control window
88 selected.
89 2. It should set `ediff-window-A', `ediff-window-B', `ediff-window-C',
90 and `ediff-control-window' to contain window objects that display
91 the corresponding buffers.
92 3. It should accept the following arguments:
93 buffer-A, buffer-B, buffer-C, control-buffer
94 Buffer C may not be used in jobs that compare only two buffers.
95 If you plan to do something fancy, take a close look at how the two
96 provided functions are written."
97 :type '(choice (const :tag "Choose Automatically" ediff-setup-windows-default)
98 (const :tag "Multi Frame" ediff-setup-windows-multiframe)
99 (const :tag "Single Frame" ediff-setup-windows-plain)
100 (function :tag "Other function"))
101 :group 'ediff-window
102 :version "24.3")
104 ;; indicates if we are in a multiframe setup
105 (ediff-defvar-local ediff-multiframe nil "")
107 ;; Share of the frame occupied by the merge window (buffer C)
108 (ediff-defvar-local ediff-merge-window-share 0.45 "")
110 ;; The control window.
111 (ediff-defvar-local ediff-control-window nil "")
112 ;; Official window for buffer A
113 (ediff-defvar-local ediff-window-A nil "")
114 ;; Official window for buffer B
115 (ediff-defvar-local ediff-window-B nil "")
116 ;; Official window for buffer C
117 (ediff-defvar-local ediff-window-C nil "")
118 ;; Official window for buffer Ancestor
119 (ediff-defvar-local ediff-window-Ancestor nil "")
120 ;; Ediff's window configuration.
121 ;; Used to minimize the need to rearrange windows.
122 (ediff-defvar-local ediff-window-config-saved "" "")
124 ;; Association between buff-type and ediff-window-*
125 (defconst ediff-window-alist
126 '((A . ediff-window-A)
127 (?A . ediff-window-A)
128 (B . ediff-window-B)
129 (?B . ediff-window-B)
130 (C . ediff-window-C)
131 (?C . ediff-window-C)
132 (Ancestor . ediff-window-Ancestor)))
135 (defcustom ediff-split-window-function 'split-window-vertically
136 "The function used to split the main window between buffer-A and buffer-B.
137 You can set it to a horizontal split instead of the default vertical split
138 by setting this variable to `split-window-horizontally'.
139 You can also have your own function to do fancy splits.
140 This variable has no effect when buffer-A/B are shown in different frames.
141 In this case, Ediff will use those frames to display these buffers."
142 :type '(choice
143 (const :tag "Split vertically" split-window-vertically)
144 (const :tag "Split horizontally" split-window-horizontally)
145 function)
146 :group 'ediff-window)
148 (defcustom ediff-merge-split-window-function 'split-window-horizontally
149 "The function used to split the main window between buffer-A and buffer-B.
150 You can set it to a vertical split instead of the default horizontal split
151 by setting this variable to `split-window-vertically'.
152 You can also have your own function to do fancy splits.
153 This variable has no effect when buffer-A/B/C are shown in different frames.
154 In this case, Ediff will use those frames to display these buffers."
155 :type '(choice
156 (const :tag "Split vertically" split-window-vertically)
157 (const :tag "Split horizontally" split-window-horizontally)
158 function)
159 :group 'ediff-window)
161 ;; Definitions hidden from the compiler by compat wrappers.
162 (declare-function ediff-display-pixel-width "ediff-init")
163 (declare-function ediff-display-pixel-height "ediff-init")
165 (defconst ediff-control-frame-parameters
166 (list
167 '(name . "Ediff")
168 ;;'(unsplittable . t)
169 '(minibuffer . nil)
170 '(user-position . t) ; Emacs only
171 '(vertical-scroll-bars . nil) ; Emacs only
172 '(scrollbar-width . 0) ; XEmacs only
173 '(scrollbar-height . 0) ; XEmacs only
174 '(menu-bar-lines . 0) ; Emacs only
175 '(tool-bar-lines . 0) ; Emacs 21+ only
176 '(left-fringe . 0)
177 '(right-fringe . 0)
178 ;; don't lower but auto-raise
179 '(auto-lower . nil)
180 '(auto-raise . t)
181 '(visibility . nil)
182 ;; make initial frame small to avoid distraction
183 '(width . 1) '(height . 1)
184 ;; this blocks queries from window manager as to where to put
185 ;; ediff's control frame. we put the frame outside the display,
186 ;; so the initial frame won't jump all over the screen
187 (cons 'top (if (fboundp 'ediff-display-pixel-height)
188 (1+ (ediff-display-pixel-height))
189 3000))
190 (cons 'left (if (fboundp 'ediff-display-pixel-width)
191 (1+ (ediff-display-pixel-width))
192 3000))
194 "Frame parameters for displaying Ediff Control Panel.
195 Used internally---not a user option.")
197 ;; position of the mouse; used to decide whether to warp the mouse into ctl
198 ;; frame
199 (ediff-defvar-local ediff-mouse-pixel-position nil "")
201 ;; not used for now
202 (defvar ediff-mouse-pixel-threshold 30
203 "If the user moves mouse more than this many pixels, Ediff won't warp mouse into control window.")
205 (defcustom ediff-grab-mouse t
206 "If t, Ediff will always grab the mouse and put it in the control frame.
207 If `maybe', Ediff will do it sometimes, but not after operations that require
208 relatively long time. If nil, the mouse will be entirely user's
209 responsibility."
210 :type 'boolean
211 :group 'ediff-window)
213 (defcustom ediff-control-frame-position-function 'ediff-make-frame-position
214 "Function to call to determine the desired location for the control panel.
215 Expects three parameters: the control buffer, the desired width and height
216 of the control frame. It returns an association list
217 of the form \((top . <position>) \(left . <position>))"
218 :type 'function
219 :group 'ediff-window)
221 (defcustom ediff-control-frame-upward-shift 42
222 "The upward shift of control frame from the top of buffer A's frame.
223 Measured in pixels.
224 This is used by the default control frame positioning function,
225 `ediff-make-frame-position'. This variable is provided for easy
226 customization of the default control frame positioning."
227 :type 'integer
228 :group 'ediff-window)
230 (defcustom ediff-narrow-control-frame-leftward-shift (if (featurep 'xemacs) 7 3)
231 "The leftward shift of control frame from the right edge of buf A's frame.
232 Measured in characters.
233 This is used by the default control frame positioning function,
234 `ediff-make-frame-position' to adjust the position of the control frame
235 when it shows the short menu. This variable is provided for easy
236 customization of the default."
237 :type 'integer
238 :group 'ediff-window)
240 (defcustom ediff-wide-control-frame-rightward-shift 7
241 "The rightward shift of control frame from the left edge of buf A's frame.
242 Measured in characters.
243 This is used by the default control frame positioning function,
244 `ediff-make-frame-position' to adjust the position of the control frame
245 when it shows the full menu. This variable is provided for easy
246 customization of the default."
247 :type 'integer
248 :group 'ediff-window)
251 ;; Wide frame display
253 ;; t means Ediff is using wide display
254 (ediff-defvar-local ediff-wide-display-p nil "")
255 ;; keeps frame config for toggling wide display
256 (ediff-defvar-local ediff-wide-display-orig-parameters nil
257 "Frame parameters to be restored when the user wants to toggle the wide
258 display off.")
259 (ediff-defvar-local ediff-wide-display-frame nil
260 "Frame to be used for wide display.")
261 (ediff-defvar-local ediff-make-wide-display-function 'ediff-make-wide-display
262 "The value is a function that is called to create a wide display.
263 The function is called without arguments. It should resize the frame in
264 which buffers A, B, and C are to be displayed, and it should save the old
265 frame parameters in `ediff-wide-display-orig-parameters'.
266 The variable `ediff-wide-display-frame' should be set to contain
267 the frame used for the wide display.")
269 ;; Frame used for the control panel in a windowing system.
270 (ediff-defvar-local ediff-control-frame nil "")
272 (defcustom ediff-prefer-iconified-control-frame nil
273 "If t, keep control panel iconified when help message is off.
274 This has effect only on a windowing system.
275 If t, hitting `?' to toggle control panel off iconifies it.
277 This is only useful in Emacs and only for certain kinds of window managers,
278 such as TWM and its derivatives, since the window manager must permit
279 keyboard input to go into icons. XEmacs completely ignores keyboard input
280 into icons, regardless of the window manager."
281 :type 'boolean
282 :group 'ediff-window)
284 ;;; Functions
286 (defun ediff-get-window-by-clicking (_wind _prev-wind wind-number)
287 (let (event)
288 (message
289 "Select windows by clicking. Please click on Window %d " wind-number)
290 (while (not (ediff-mouse-event-p (setq event (ediff-read-event))))
291 (if (sit-for 1) ; if sequence of events, wait till the final word
292 (beep 1))
293 (message "Please click on Window %d " wind-number))
294 (ediff-read-event) ; discard event
295 (if (featurep 'xemacs)
296 (event-window event)
297 (posn-window (event-start event)))))
300 ;; Select the lowest window on the frame.
301 (defun ediff-select-lowest-window ()
302 (if (featurep 'xemacs)
303 (select-window (frame-lowest-window))
304 (let* ((lowest-window (selected-window))
305 (bottom-edge (car (cdr (cdr (cdr (window-edges))))))
306 (last-window (save-excursion
307 (other-window -1) (selected-window)))
308 (window-search t))
309 (while window-search
310 (let* ((this-window (next-window))
311 (next-bottom-edge
312 (car (cdr (cdr (cdr (window-edges this-window)))))))
313 (if (< bottom-edge next-bottom-edge)
314 (setq bottom-edge next-bottom-edge
315 lowest-window this-window))
316 (select-window this-window)
317 (when (eq last-window this-window)
318 (select-window lowest-window)
319 (setq window-search nil)))))))
322 ;;; Common window setup routines
324 ;; Set up the window configuration. If POS is given, set the points to
325 ;; the beginnings of the buffers.
326 ;; When 3way comparison is added, this will have to choose the appropriate
327 ;; setup function based on ediff-job-name
328 (defun ediff-setup-windows (buffer-A buffer-B buffer-C control-buffer)
329 ;; Make sure we are not in the minibuffer window when we try to delete
330 ;; all other windows.
331 (run-hooks 'ediff-before-setup-windows-hook)
332 (if (eq (selected-window) (minibuffer-window))
333 (other-window 1))
335 ;; in case user did a no-no on a tty
336 (or (ediff-window-display-p)
337 (setq ediff-window-setup-function 'ediff-setup-windows-plain))
339 (or (ediff-keep-window-config control-buffer)
340 (funcall
341 (ediff-with-current-buffer control-buffer ediff-window-setup-function)
342 buffer-A buffer-B buffer-C control-buffer))
343 (run-hooks 'ediff-after-setup-windows-hook))
345 (defun ediff-setup-windows-default (buffer-A buffer-B buffer-C control-buffer)
346 (funcall (if (display-graphic-p)
347 'ediff-setup-windows-multiframe
348 'ediff-setup-windows-plain)
349 buffer-A buffer-B buffer-C control-buffer))
351 ;; Just set up 3 windows.
352 ;; Usually used without windowing systems
353 ;; With windowing, we want to use dedicated frames.
354 (defun ediff-setup-windows-plain (buffer-A buffer-B buffer-C control-buffer)
355 (ediff-with-current-buffer control-buffer
356 (setq ediff-multiframe nil))
357 (if ediff-merge-job
358 (ediff-setup-windows-plain-merge
359 buffer-A buffer-B buffer-C control-buffer)
360 (ediff-setup-windows-plain-compare
361 buffer-A buffer-B buffer-C control-buffer)))
363 (autoload 'ediff-setup-control-buffer "ediff-util")
365 (defun ediff-setup-windows-plain-merge (buf-A buf-B buf-C control-buffer)
366 ;; skip dedicated and unsplittable frames
367 (ediff-destroy-control-frame control-buffer)
368 (let ((window-min-height 1)
369 (with-Ancestor-p (ediff-with-current-buffer control-buffer
370 ediff-merge-with-ancestor-job))
371 split-window-function
372 merge-window-share merge-window-lines
373 (buf-Ancestor (ediff-with-current-buffer control-buffer
374 ediff-ancestor-buffer))
375 wind-A wind-B wind-C wind-Ancestor)
376 (ediff-with-current-buffer control-buffer
377 (setq merge-window-share ediff-merge-window-share
378 ;; this lets us have local versions of ediff-split-window-function
379 split-window-function ediff-split-window-function))
380 (delete-other-windows)
381 (set-window-dedicated-p (selected-window) nil)
382 (split-window-vertically)
383 (ediff-select-lowest-window)
384 (ediff-setup-control-buffer control-buffer)
386 ;; go to the upper window and split it betw A, B, and possibly C
387 (other-window 1)
388 (setq merge-window-lines
389 (max 2 (round (* (window-height) merge-window-share))))
390 (switch-to-buffer buf-A)
391 (setq wind-A (selected-window))
393 ;; XEmacs used to have a lot of trouble with display
394 ;; It did't set things right unless we tell it to sit still
395 ;; 19.12 seems ok.
396 ;;(if (featurep 'xemacs) (sit-for 0))
398 (split-window-vertically (max 2 (- (window-height) merge-window-lines)))
399 (if (eq (selected-window) wind-A)
400 (other-window 1))
401 (setq wind-C (selected-window))
402 (switch-to-buffer buf-C)
404 (when (and ediff-show-ancestor with-Ancestor-p)
405 (select-window wind-C)
406 (funcall split-window-function)
407 (when (eq (selected-window) wind-C)
408 (other-window 1))
409 (switch-to-buffer buf-Ancestor)
410 (setq wind-Ancestor (selected-window)))
412 (select-window wind-A)
413 (funcall split-window-function)
415 (if (eq (selected-window) wind-A)
416 (other-window 1))
417 (switch-to-buffer buf-B)
418 (setq wind-B (selected-window))
420 (ediff-with-current-buffer control-buffer
421 (setq ediff-window-A wind-A
422 ediff-window-B wind-B
423 ediff-window-C wind-C
424 ediff-window-Ancestor wind-Ancestor))
426 (ediff-select-lowest-window)
427 (ediff-setup-control-buffer control-buffer)
431 ;; This function handles all comparison jobs, including 3way jobs
432 (defun ediff-setup-windows-plain-compare (buf-A buf-B buf-C control-buffer)
433 ;; skip dedicated and unsplittable frames
434 (ediff-destroy-control-frame control-buffer)
435 (let ((window-min-height 1)
436 split-window-function wind-width-or-height
437 three-way-comparison
438 wind-A-start wind-B-start wind-A wind-B wind-C)
439 (ediff-with-current-buffer control-buffer
440 (setq wind-A-start (ediff-overlay-start
441 (ediff-get-value-according-to-buffer-type
442 'A ediff-narrow-bounds))
443 wind-B-start (ediff-overlay-start
444 (ediff-get-value-according-to-buffer-type
445 'B ediff-narrow-bounds))
446 ;; this lets us have local versions of ediff-split-window-function
447 split-window-function ediff-split-window-function
448 three-way-comparison ediff-3way-comparison-job))
449 ;; if in minibuffer go somewhere else
450 (if (save-match-data
451 (string-match "\\*Minibuf-" (buffer-name (window-buffer))))
452 (select-window (next-window nil 'ignore-minibuf)))
453 (delete-other-windows)
454 (set-window-dedicated-p (selected-window) nil)
455 (split-window-vertically)
456 (ediff-select-lowest-window)
457 (ediff-setup-control-buffer control-buffer)
459 ;; go to the upper window and split it betw A, B, and possibly C
460 (other-window 1)
461 (switch-to-buffer buf-A)
462 (setq wind-A (selected-window))
463 (if three-way-comparison
464 (setq wind-width-or-height
465 (/ (if (eq split-window-function 'split-window-vertically)
466 (window-height wind-A)
467 (window-width wind-A))
468 3)))
470 ;; XEmacs used to have a lot of trouble with display
471 ;; It did't set things right unless we told it to sit still
472 ;; 19.12 seems ok.
473 ;;(if (featurep 'xemacs) (sit-for 0))
475 (funcall split-window-function wind-width-or-height)
477 (if (eq (selected-window) wind-A)
478 (other-window 1))
479 (switch-to-buffer buf-B)
480 (setq wind-B (selected-window))
482 (if three-way-comparison
483 (progn
484 (funcall split-window-function) ; equally
485 (if (eq (selected-window) wind-B)
486 (other-window 1))
487 (switch-to-buffer buf-C)
488 (setq wind-C (selected-window))))
490 (ediff-with-current-buffer control-buffer
491 (setq ediff-window-A wind-A
492 ediff-window-B wind-B
493 ediff-window-C wind-C))
495 ;; It is unlikely that we will want to implement 3way window comparison.
496 ;; So, only buffers A and B are used here.
497 (if ediff-windows-job
498 (progn
499 (set-window-start wind-A wind-A-start)
500 (set-window-start wind-B wind-B-start)))
502 (ediff-select-lowest-window)
503 (ediff-setup-control-buffer control-buffer)
507 ;; dispatch an appropriate window setup function
508 (defun ediff-setup-windows-multiframe (buf-A buf-B buf-C control-buf)
509 (ediff-with-current-buffer control-buf
510 (setq ediff-multiframe t))
511 (if ediff-merge-job
512 (ediff-setup-windows-multiframe-merge buf-A buf-B buf-C control-buf)
513 (ediff-setup-windows-multiframe-compare buf-A buf-B buf-C control-buf)))
515 (defun ediff-setup-windows-multiframe-merge (buf-A buf-B buf-C control-buf)
516 ;;; Algorithm:
517 ;;; 1. Never use frames that have dedicated windows in them---it is bad to
518 ;;; destroy dedicated windows.
519 ;;; 2. If A and B are in the same frame but C's frame is different--- use one
520 ;;; frame for A and B and use a separate frame for C.
521 ;;; 3. If C's frame is non-existent, then: if the first suitable
522 ;;; non-dedicated frame is different from A&B's, then use it for C.
523 ;;; Otherwise, put A,B, and C in one frame.
524 ;;; 4. If buffers A, B, C are is separate frames, use them to display these
525 ;;; buffers.
527 ;; Skip dedicated or iconified frames.
528 ;; Unsplittable frames are taken care of later.
529 (ediff-skip-unsuitable-frames 'ok-unsplittable)
531 (let* ((window-min-height 1)
532 (wind-A (ediff-get-visible-buffer-window buf-A))
533 (wind-B (ediff-get-visible-buffer-window buf-B))
534 (wind-C (ediff-get-visible-buffer-window buf-C))
535 (buf-Ancestor (ediff-with-current-buffer control-buf
536 ediff-ancestor-buffer))
537 (wind-Ancestor (ediff-get-visible-buffer-window buf-Ancestor))
538 (frame-A (if wind-A (window-frame wind-A)))
539 (frame-B (if wind-B (window-frame wind-B)))
540 (frame-C (if wind-C (window-frame wind-C)))
541 (frame-Ancestor (if wind-Ancestor (window-frame wind-Ancestor)))
542 ;; on wide display, do things in one frame
543 (force-one-frame
544 (ediff-with-current-buffer control-buf ediff-wide-display-p))
545 ;; this lets us have local versions of ediff-split-window-function
546 (split-window-function
547 (ediff-with-current-buffer control-buf ediff-split-window-function))
548 (orig-wind (selected-window))
549 (orig-frame (selected-frame))
550 (use-same-frame (or force-one-frame
551 ;; A and C must be in one frame
552 (eq frame-A (or frame-C orig-frame))
553 ;; B and C must be in one frame
554 (eq frame-B (or frame-C orig-frame))
555 ;; A or B is not visible
556 (not (frame-live-p frame-A))
557 (not (frame-live-p frame-B))
558 ;; A or B is not suitable for display
559 (not (ediff-window-ok-for-display wind-A))
560 (not (ediff-window-ok-for-display wind-B))
561 ;; A and B in the same frame, and no good frame
562 ;; for C
563 (and (eq frame-A frame-B)
564 (not (frame-live-p frame-C)))
566 ;; use-same-frame-for-AB implies wind A and B are ok for display
567 (use-same-frame-for-AB (and (not use-same-frame)
568 (eq frame-A frame-B)))
569 (merge-window-share (ediff-with-current-buffer control-buf
570 ediff-merge-window-share))
571 merge-window-lines
572 designated-minibuffer-frame ; ediff-merge-with-ancestor-job
573 (with-Ancestor-p (ediff-with-current-buffer control-buf
574 ediff-merge-with-ancestor-job))
575 (done-Ancestor (not with-Ancestor-p))
576 done-A done-B done-C)
578 ;; buf-A on its own
579 (if (and (window-live-p wind-A)
580 (null use-same-frame) ; implies wind-A is suitable
581 (null use-same-frame-for-AB))
582 (progn ; bug A on its own
583 ;; buffer buf-A is seen in live wind-A
584 (select-window wind-A)
585 (delete-other-windows)
586 (setq wind-A (selected-window))
587 (setq done-A t)))
589 ;; buf-B on its own
590 (if (and (window-live-p wind-B)
591 (null use-same-frame) ; implies wind-B is suitable
592 (null use-same-frame-for-AB))
593 (progn ; buf B on its own
594 ;; buffer buf-B is seen in live wind-B
595 (select-window wind-B)
596 (delete-other-windows)
597 (setq wind-B (selected-window))
598 (setq done-B t)))
600 ;; buf-C on its own
601 (if (and (window-live-p wind-C)
602 (ediff-window-ok-for-display wind-C)
603 (null use-same-frame)) ; buf C on its own
604 (progn
605 ;; buffer buf-C is seen in live wind-C
606 (select-window wind-C)
607 (delete-other-windows)
608 (setq wind-C (selected-window))
609 (setq done-C t)))
611 ;; buf-Ancestor on its own
612 (if (and ediff-show-ancestor
613 with-Ancestor-p
614 (window-live-p wind-Ancestor)
615 (ediff-window-ok-for-display wind-Ancestor)
616 (null use-same-frame)) ; buf Ancestor on its own
617 (progn
618 ;; buffer buf-Ancestor is seen in live wind-Ancestor
619 (select-window wind-Ancestor)
620 (delete-other-windows)
621 (setq wind-Ancestor (selected-window))
622 (setq done-Ancestor t)))
624 (if (and use-same-frame-for-AB ; implies wind A and B are suitable
625 (window-live-p wind-A))
626 (progn
627 ;; wind-A must already be displaying buf-A
628 (select-window wind-A)
629 (delete-other-windows)
630 (setq wind-A (selected-window))
632 (funcall split-window-function)
633 (if (eq (selected-window) wind-A)
634 (other-window 1))
635 (switch-to-buffer buf-B)
636 (setq wind-B (selected-window))
638 (setq done-A t
639 done-B t)))
641 (if use-same-frame
642 (let ((window-min-height 1))
643 (if (and (eq frame-A frame-B)
644 (eq frame-B frame-C)
645 (eq frame-C frame-Ancestor)
646 (frame-live-p frame-A))
647 (select-frame frame-A)
648 ;; avoid dedicated and non-splittable windows
649 (ediff-skip-unsuitable-frames))
650 (delete-other-windows)
651 (setq merge-window-lines
652 (max 2 (round (* (window-height) merge-window-share))))
653 (switch-to-buffer buf-A)
654 (setq wind-A (selected-window))
656 (split-window-vertically
657 (max 2 (- (window-height) merge-window-lines)))
658 (if (eq (selected-window) wind-A)
659 (other-window 1))
660 (setq wind-C (selected-window))
661 (switch-to-buffer buf-C)
663 (when (and ediff-show-ancestor with-Ancestor-p)
664 (select-window wind-C)
665 (funcall split-window-function)
666 (if (eq (selected-window) wind-C)
667 (other-window 1))
668 (switch-to-buffer buf-Ancestor)
669 (setq wind-Ancestor (selected-window)))
671 (select-window wind-A)
673 (funcall split-window-function)
674 (if (eq (selected-window) wind-A)
675 (other-window 1))
676 (switch-to-buffer buf-B)
677 (setq wind-B (selected-window))
679 (setq done-A t
680 done-B t
681 done-C t
682 done-Ancestor t)))
684 (or done-A ; Buf A to be set in its own frame,
685 ;;; or it was set before because use-same-frame = 1
686 (progn
687 ;; Buf-A was not set up yet as it wasn't visible,
688 ;; and use-same-frame = nil, use-same-frame-for-AB = nil
689 (select-window orig-wind)
690 (delete-other-windows)
691 (switch-to-buffer buf-A)
692 (setq wind-A (selected-window))
694 (or done-B ; Buf B to be set in its own frame,
695 ;;; or it was set before because use-same-frame = 1
696 (progn
697 ;; Buf-B was not set up yet as it wasn't visible
698 ;; and use-same-frame = nil, use-same-frame-for-AB = nil
699 (select-window orig-wind)
700 (delete-other-windows)
701 (switch-to-buffer buf-B)
702 (setq wind-B (selected-window))
705 (or done-C ; Buf C to be set in its own frame,
706 ;;; or it was set before because use-same-frame = 1
707 (progn
708 ;; Buf-C was not set up yet as it wasn't visible
709 ;; and use-same-frame = nil
710 (select-window orig-wind)
711 (delete-other-windows)
712 (switch-to-buffer buf-C)
713 (setq wind-C (selected-window))
716 (or done-Ancestor ; Buf Ancestor to be set in its own frame,
717 (not ediff-show-ancestor)
718 ;;; or it was set before because use-same-frame = 1
719 (progn
720 ;; Buf-Ancestor was not set up yet as it wasn't visible
721 ;; and use-same-frame = nil
722 (select-window orig-wind)
723 (delete-other-windows)
724 (switch-to-buffer buf-Ancestor)
725 (setq wind-Ancestor (selected-window))))
727 (ediff-with-current-buffer control-buf
728 (setq ediff-window-A wind-A
729 ediff-window-B wind-B
730 ediff-window-C wind-C
731 ediff-window-Ancestor wind-Ancestor)
732 (setq frame-A (window-frame ediff-window-A)
733 designated-minibuffer-frame
734 (window-frame (minibuffer-window frame-A))))
736 (ediff-setup-control-frame control-buf designated-minibuffer-frame)
739 ;; Window setup for all comparison jobs, including 3way comparisons
740 (defun ediff-setup-windows-multiframe-compare (buf-A buf-B buf-C control-buf)
741 ;;; Algorithm:
742 ;;; If a buffer is seen in a frame, use that frame for that buffer.
743 ;;; If it is not seen, use the current frame.
744 ;;; If both buffers are not seen, they share the current frame. If one
745 ;;; of the buffers is not seen, it is placed in the current frame (where
746 ;;; ediff started). If that frame is displaying the other buffer, it is
747 ;;; shared between the two buffers.
748 ;;; However, if we decide to put both buffers in one frame
749 ;;; and the selected frame isn't splittable, we create a new frame and
750 ;;; put both buffers there, event if one of this buffers is visible in
751 ;;; another frame.
753 ;; Skip dedicated or iconified frames.
754 ;; Unsplittable frames are taken care of later.
755 (ediff-skip-unsuitable-frames 'ok-unsplittable)
757 (let* ((window-min-height 1)
758 (wind-A (ediff-get-visible-buffer-window buf-A))
759 (wind-B (ediff-get-visible-buffer-window buf-B))
760 (wind-C (ediff-get-visible-buffer-window buf-C))
761 (frame-A (if wind-A (window-frame wind-A)))
762 (frame-B (if wind-B (window-frame wind-B)))
763 (frame-C (if wind-C (window-frame wind-C)))
764 (ctl-frame-exists-p (ediff-with-current-buffer control-buf
765 (frame-live-p ediff-control-frame)))
766 ;; on wide display, do things in one frame
767 (force-one-frame
768 (ediff-with-current-buffer control-buf ediff-wide-display-p))
769 ;; this lets us have local versions of ediff-split-window-function
770 (split-window-function
771 (ediff-with-current-buffer control-buf ediff-split-window-function))
772 (three-way-comparison
773 (ediff-with-current-buffer control-buf ediff-3way-comparison-job))
774 (orig-wind (selected-window))
775 (use-same-frame (or force-one-frame
776 (eq frame-A frame-B)
777 (not (ediff-window-ok-for-display wind-A))
778 (not (ediff-window-ok-for-display wind-B))
779 (if three-way-comparison
780 (or (eq frame-A frame-C)
781 (eq frame-B frame-C)
782 (not (ediff-window-ok-for-display wind-C))
783 (not (frame-live-p frame-A))
784 (not (frame-live-p frame-B))
785 (not (frame-live-p frame-C))))
786 (and (not (frame-live-p frame-B))
787 (or ctl-frame-exists-p
788 (eq frame-A (selected-frame))))
789 (and (not (frame-live-p frame-A))
790 (or ctl-frame-exists-p
791 (eq frame-B (selected-frame))))))
792 wind-A-start wind-B-start
793 designated-minibuffer-frame
794 done-A done-B done-C)
796 (ediff-with-current-buffer control-buf
797 (setq wind-A-start (ediff-overlay-start
798 (ediff-get-value-according-to-buffer-type
799 'A ediff-narrow-bounds))
800 wind-B-start (ediff-overlay-start
801 (ediff-get-value-according-to-buffer-type
802 'B ediff-narrow-bounds))))
804 (if (and (window-live-p wind-A) (null use-same-frame)) ; buf-A on its own
805 (progn
806 ;; buffer buf-A is seen in live wind-A
807 (select-window wind-A) ; must be displaying buf-A
808 (delete-other-windows)
809 (setq wind-A (selected-window))
810 (setq done-A t)))
812 (if (and (window-live-p wind-B) (null use-same-frame)) ; buf B on its own
813 (progn
814 ;; buffer buf-B is seen in live wind-B
815 (select-window wind-B) ; must be displaying buf-B
816 (delete-other-windows)
817 (setq wind-B (selected-window))
818 (setq done-B t)))
820 (if (and (window-live-p wind-C) (null use-same-frame)) ; buf C on its own
821 (progn
822 ;; buffer buf-C is seen in live wind-C
823 (select-window wind-C) ; must be displaying buf-C
824 (delete-other-windows)
825 (setq wind-C (selected-window))
826 (setq done-C t)))
828 (if use-same-frame
829 (let (wind-width-or-height) ; this affects 3way setups only
830 (if (and (eq frame-A frame-B) (frame-live-p frame-A))
831 (select-frame frame-A)
832 ;; avoid dedicated and non-splittable windows
833 (ediff-skip-unsuitable-frames))
834 (delete-other-windows)
835 (switch-to-buffer buf-A)
836 (setq wind-A (selected-window))
838 (if three-way-comparison
839 (setq wind-width-or-height
841 (if (eq split-window-function 'split-window-vertically)
842 (window-height wind-A)
843 (window-width wind-A))
844 3)))
846 (funcall split-window-function wind-width-or-height)
847 (if (eq (selected-window) wind-A)
848 (other-window 1))
849 (switch-to-buffer buf-B)
850 (setq wind-B (selected-window))
852 (if three-way-comparison
853 (progn
854 (funcall split-window-function) ; equally
855 (if (memq (selected-window) (list wind-A wind-B))
856 (other-window 1))
857 (switch-to-buffer buf-C)
858 (setq wind-C (selected-window))))
859 (setq done-A t
860 done-B t
861 done-C t)
864 (or done-A ; Buf A to be set in its own frame
865 ;;; or it was set before because use-same-frame = 1
866 (progn
867 ;; Buf-A was not set up yet as it wasn't visible,
868 ;; and use-same-frame = nil
869 (select-window orig-wind)
870 (delete-other-windows)
871 (switch-to-buffer buf-A)
872 (setq wind-A (selected-window))
874 (or done-B ; Buf B to be set in its own frame
875 ;;; or it was set before because use-same-frame = 1
876 (progn
877 ;; Buf-B was not set up yet as it wasn't visible,
878 ;; and use-same-frame = nil
879 (select-window orig-wind)
880 (delete-other-windows)
881 (switch-to-buffer buf-B)
882 (setq wind-B (selected-window))
885 (if three-way-comparison
886 (or done-C ; Buf C to be set in its own frame
887 ;;; or it was set before because use-same-frame = 1
888 (progn
889 ;; Buf-C was not set up yet as it wasn't visible,
890 ;; and use-same-frame = nil
891 (select-window orig-wind)
892 (delete-other-windows)
893 (switch-to-buffer buf-C)
894 (setq wind-C (selected-window))
897 (ediff-with-current-buffer control-buf
898 (setq ediff-window-A wind-A
899 ediff-window-B wind-B
900 ediff-window-C wind-C)
902 (setq frame-A (window-frame ediff-window-A)
903 designated-minibuffer-frame
904 (window-frame (minibuffer-window frame-A))))
906 ;; It is unlikely that we'll implement a version of ediff-windows that
907 ;; would compare 3 windows at once. So, we don't use buffer C here.
908 (if ediff-windows-job
909 (progn
910 (set-window-start wind-A wind-A-start)
911 (set-window-start wind-B wind-B-start)))
913 (ediff-setup-control-frame control-buf designated-minibuffer-frame)
916 ;; skip unsplittable frames and frames that have dedicated windows.
917 ;; create a new splittable frame if none is found
918 (defun ediff-skip-unsuitable-frames (&optional ok-unsplittable)
919 (if (ediff-window-display-p)
920 (let ((wind-frame (window-frame))
921 seen-windows)
922 (while (and (not (memq (selected-window) seen-windows))
924 (ediff-frame-has-dedicated-windows wind-frame)
925 (ediff-frame-iconified-p wind-frame)
926 ;; skip small windows
927 (< (frame-height wind-frame)
928 (* 3 window-min-height))
929 (if ok-unsplittable
931 (ediff-frame-unsplittable-p wind-frame))))
932 ;; remember history
933 (setq seen-windows (cons (selected-window) seen-windows))
934 ;; try new window
935 (other-window 1 t)
936 (setq wind-frame (window-frame))
938 (if (memq (selected-window) seen-windows)
939 ;; fed up, no appropriate frames
940 (setq wind-frame (make-frame '((unsplittable)))))
942 (select-frame wind-frame)
945 (defun ediff-frame-has-dedicated-windows (frame)
946 (let (ans)
947 (walk-windows
948 (lambda (wind) (if (window-dedicated-p wind)
949 (setq ans t)))
950 'ignore-minibuffer
951 frame)
952 ans))
954 ;; window is ok, if it is only one window on the frame, not counting the
955 ;; minibuffer, or none of the frame's windows is dedicated.
956 ;; The idea is that it is bad to destroy dedicated windows while creating an
957 ;; ediff window setup
958 (defun ediff-window-ok-for-display (wind)
959 (and
960 (window-live-p wind)
962 ;; only one window
963 (eq wind (next-window wind 'ignore-minibuffer (window-frame wind)))
964 ;; none is dedicated (in multiframe setup)
965 (not (ediff-frame-has-dedicated-windows (window-frame wind)))
968 (declare-function ediff-make-bottom-toolbar "ediff-util" (&optional frame))
970 ;; Prepare or refresh control frame
971 (defun ediff-setup-control-frame (ctl-buffer designated-minibuffer-frame)
972 (let ((window-min-height 1)
973 ctl-frame-iconified-p dont-iconify-ctl-frame deiconify-ctl-frame
974 ctl-frame old-ctl-frame lines
975 ;; user-grabbed-mouse
976 fheight fwidth adjusted-parameters)
978 (ediff-with-current-buffer ctl-buffer
979 (if (and (featurep 'xemacs) (featurep 'menubar))
980 (set-buffer-menubar nil))
981 ;;(setq user-grabbed-mouse (ediff-user-grabbed-mouse))
982 (run-hooks 'ediff-before-setup-control-frame-hook))
984 (setq old-ctl-frame (ediff-with-current-buffer ctl-buffer ediff-control-frame))
985 (ediff-with-current-buffer ctl-buffer
986 (setq ctl-frame (if (frame-live-p old-ctl-frame)
987 old-ctl-frame
988 (make-frame ediff-control-frame-parameters))
989 ediff-control-frame ctl-frame)
990 ;; protect against undefined face-attribute
991 (condition-case nil
992 (if (and (featurep 'emacs) (face-attribute 'mode-line :box))
993 (set-face-attribute 'mode-line ctl-frame :box nil))
994 (error)))
996 (setq ctl-frame-iconified-p (ediff-frame-iconified-p ctl-frame))
997 (select-frame ctl-frame)
998 (if (window-dedicated-p)
1000 (delete-other-windows)
1001 (switch-to-buffer ctl-buffer))
1003 ;; must be before ediff-setup-control-buffer
1004 ;; just a precaution--we should be in ctl-buffer already
1005 (ediff-with-current-buffer ctl-buffer
1006 (make-local-variable 'frame-title-format)
1007 (make-local-variable 'frame-icon-title-format) ; XEmacs
1008 (make-local-variable 'icon-title-format)) ; Emacs
1010 (ediff-setup-control-buffer ctl-buffer)
1011 (setq dont-iconify-ctl-frame
1012 (not (string= ediff-help-message ediff-brief-help-message)))
1013 (setq deiconify-ctl-frame
1014 (and (eq this-command 'ediff-toggle-help)
1015 dont-iconify-ctl-frame))
1017 ;; 1 more line for the mode line
1018 (setq lines (1+ (count-lines (point-min) (point-max)))
1019 fheight lines
1020 fwidth (max (+ (ediff-help-message-line-length) 2)
1021 (ediff-compute-toolbar-width))
1022 adjusted-parameters
1023 (list
1024 ;; possibly change surrogate minibuffer
1025 (cons 'minibuffer
1026 (minibuffer-window
1027 designated-minibuffer-frame))
1028 (cons 'width fwidth)
1029 (cons 'height fheight)
1030 (cons 'user-position t)
1033 ;; adjust autoraise
1034 (setq adjusted-parameters
1035 (cons (if ediff-use-long-help-message
1036 '(auto-raise . nil)
1037 '(auto-raise . t))
1038 adjusted-parameters))
1040 ;; In XEmacs, buffer menubar needs to be killed before frame parameters
1041 ;; are changed.
1042 (if (ediff-has-toolbar-support-p)
1043 (when (featurep 'xemacs)
1044 (if (ediff-has-gutter-support-p)
1045 (set-specifier top-gutter (list ctl-frame nil)))
1046 (sit-for 0)
1047 (set-specifier top-toolbar-height (list ctl-frame 0))
1048 ;;(set-specifier bottom-toolbar-height (list ctl-frame 0))
1049 (set-specifier left-toolbar-width (list ctl-frame 0))
1050 (set-specifier right-toolbar-width (list ctl-frame 0))))
1052 ;; As a precaution, we call modify frame parameters twice, in
1053 ;; order to make sure that at least once we do it for
1054 ;; a non-iconified frame. (It appears that in the Windows port of
1055 ;; Emacs, one can't modify frame parameters of iconified frames.)
1056 (if (eq system-type 'windows-nt)
1057 (modify-frame-parameters ctl-frame adjusted-parameters))
1059 ;; make or zap toolbar (if not requested)
1060 (ediff-make-bottom-toolbar ctl-frame)
1062 (goto-char (point-min))
1064 (modify-frame-parameters ctl-frame adjusted-parameters)
1065 (make-frame-visible ctl-frame)
1067 ;; This works around a bug in 19.25 and earlier. There, if frame gets
1068 ;; iconified, the current buffer changes to that of the frame that
1069 ;; becomes exposed as a result of this iconification.
1070 ;; So, we make sure the current buffer doesn't change.
1071 (select-frame ctl-frame)
1072 (ediff-refresh-control-frame)
1074 (cond ((and ediff-prefer-iconified-control-frame
1075 (not ctl-frame-iconified-p) (not dont-iconify-ctl-frame))
1076 (iconify-frame ctl-frame))
1077 ((or deiconify-ctl-frame (not ctl-frame-iconified-p))
1078 (raise-frame ctl-frame)))
1080 (set-window-dedicated-p (selected-window) t)
1082 ;; Now move the frame. We must do it separately due to an obscure bug in
1083 ;; XEmacs
1084 (modify-frame-parameters
1085 ctl-frame
1086 (funcall ediff-control-frame-position-function ctl-buffer fwidth fheight))
1088 ;; synchronize so the cursor will move to control frame
1089 ;; per RMS suggestion
1090 (if (ediff-window-display-p)
1091 (let ((count 7))
1092 (sit-for .1)
1093 (while (and (not (frame-visible-p ctl-frame)) (> count 0))
1094 (setq count (1- count))
1095 (sit-for .3))))
1097 (or (ediff-frame-iconified-p ctl-frame)
1098 ;; don't warp the mouse, unless ediff-grab-mouse = t
1099 (ediff-reset-mouse ctl-frame
1100 (or (eq this-command 'ediff-quit)
1101 (not (eq ediff-grab-mouse t)))))
1103 (when (featurep 'xemacs)
1104 (ediff-with-current-buffer ctl-buffer
1105 (make-local-hook 'select-frame-hook)
1106 (add-hook 'select-frame-hook
1107 'ediff-xemacs-select-frame-hook nil 'local)))
1109 (ediff-with-current-buffer ctl-buffer
1110 (run-hooks 'ediff-after-setup-control-frame-hook))))
1113 (defun ediff-destroy-control-frame (ctl-buffer)
1114 (ediff-with-current-buffer ctl-buffer
1115 (if (and (ediff-window-display-p) (frame-live-p ediff-control-frame))
1116 (let ((ctl-frame ediff-control-frame))
1117 (if (and (featurep 'xemacs) (featurep 'menubar))
1118 (set-buffer-menubar default-menubar))
1119 (setq ediff-control-frame nil)
1120 (delete-frame ctl-frame))))
1121 (if ediff-multiframe
1122 (ediff-skip-unsuitable-frames))
1123 ;;(ediff-reset-mouse nil)
1127 ;; finds a good place to clip control frame
1128 (defun ediff-make-frame-position (ctl-buffer ctl-frame-width ctl-frame-height)
1129 (ediff-with-current-buffer ctl-buffer
1130 (let* ((frame-A (window-frame ediff-window-A))
1131 (frame-A-parameters (frame-parameters frame-A))
1132 (frame-A-top (eval (cdr (assoc 'top frame-A-parameters))))
1133 (frame-A-left (eval (cdr (assoc 'left frame-A-parameters))))
1134 (frame-A-width (frame-width frame-A))
1135 (ctl-frame ediff-control-frame)
1136 horizontal-adjustment upward-adjustment
1137 ctl-frame-top ctl-frame-left)
1139 ;; Multiple control frames are clipped based on the value of
1140 ;; ediff-control-buffer-number. This is done in order not to obscure
1141 ;; other active control panels.
1142 (setq horizontal-adjustment (* 2 ediff-control-buffer-number)
1143 upward-adjustment (* -14 ediff-control-buffer-number))
1145 (setq ctl-frame-top
1146 (- frame-A-top upward-adjustment ediff-control-frame-upward-shift)
1147 ctl-frame-left
1148 (+ frame-A-left
1149 (if ediff-use-long-help-message
1150 (* (ediff-frame-char-width ctl-frame)
1151 (+ ediff-wide-control-frame-rightward-shift
1152 horizontal-adjustment))
1153 (- (* frame-A-width (ediff-frame-char-width frame-A))
1154 (* (ediff-frame-char-width ctl-frame)
1155 (+ ctl-frame-width
1156 ediff-narrow-control-frame-leftward-shift
1157 horizontal-adjustment))))))
1158 (setq ctl-frame-top
1159 (min ctl-frame-top
1160 (- (ediff-display-pixel-height)
1161 (* 2 ctl-frame-height
1162 (ediff-frame-char-height ctl-frame))))
1163 ctl-frame-left
1164 (min ctl-frame-left
1165 (- (ediff-display-pixel-width)
1166 (* ctl-frame-width (ediff-frame-char-width ctl-frame)))))
1167 ;; keep ctl frame within the visible bounds
1168 (setq ctl-frame-top (max ctl-frame-top 1)
1169 ctl-frame-left (max ctl-frame-left 1))
1171 (list (cons 'top ctl-frame-top)
1172 (cons 'left ctl-frame-left))
1175 (defun ediff-xemacs-select-frame-hook ()
1176 (if (and (equal (selected-frame) ediff-control-frame)
1177 (not ediff-use-long-help-message))
1178 (raise-frame ediff-control-frame)))
1180 (defun ediff-make-wide-display ()
1181 "Construct an alist of parameters for the wide display.
1182 Saves the old frame parameters in `ediff-wide-display-orig-parameters'.
1183 The frame to be resized is kept in `ediff-wide-display-frame'.
1184 This function modifies only the left margin and the width of the display.
1185 It assumes that it is called from within the control buffer."
1186 (if (not (fboundp 'ediff-display-pixel-width))
1187 (error "Can't determine display width"))
1188 (let* ((frame-A (window-frame ediff-window-A))
1189 (frame-A-params (frame-parameters frame-A))
1190 (cw (ediff-frame-char-width frame-A))
1191 (wd (- (/ (ediff-display-pixel-width) cw) 5)))
1192 (setq ediff-wide-display-orig-parameters
1193 (list (cons 'left (max 0 (eval (cdr (assoc 'left frame-A-params)))))
1194 (cons 'width (cdr (assoc 'width frame-A-params))))
1195 ediff-wide-display-frame frame-A)
1196 (modify-frame-parameters
1197 frame-A `((left . ,cw) (width . ,wd) (user-position . t)))))
1200 ;; Revise the mode line to display which difference we have selected
1201 ;; Also resets mode lines of buffers A/B, since they may be clobbered by
1202 ;; other invocations of Ediff.
1203 (defun ediff-refresh-mode-lines ()
1204 (let (buf-A-state-diff buf-B-state-diff buf-C-state-diff buf-C-state-merge)
1206 (if (ediff-valid-difference-p)
1207 (setq
1208 buf-C-state-diff (ediff-get-state-of-diff ediff-current-difference 'C)
1209 buf-C-state-merge (ediff-get-state-of-merge ediff-current-difference)
1210 buf-A-state-diff (ediff-get-state-of-diff ediff-current-difference 'A)
1211 buf-B-state-diff (ediff-get-state-of-diff ediff-current-difference 'B)
1212 buf-A-state-diff (if buf-A-state-diff
1213 (format "[%s] " buf-A-state-diff)
1215 buf-B-state-diff (if buf-B-state-diff
1216 (format "[%s] " buf-B-state-diff)
1218 buf-C-state-diff (if (and (ediff-buffer-live-p ediff-buffer-C)
1219 (or buf-C-state-diff buf-C-state-merge))
1220 (format "[%s%s%s] "
1221 (or buf-C-state-diff "")
1222 (if buf-C-state-merge
1223 (concat " " buf-C-state-merge)
1225 (if (ediff-get-state-of-ancestor
1226 ediff-current-difference)
1227 " AncestorEmpty"
1230 ""))
1231 (setq buf-A-state-diff ""
1232 buf-B-state-diff ""
1233 buf-C-state-diff ""))
1235 ;; control buffer format
1236 (setq mode-line-format
1237 (if (ediff-narrow-control-frame-p)
1238 (list " " mode-line-buffer-identification)
1239 (list "-- " mode-line-buffer-identification " Quick Help")))
1240 ;; control buffer id
1241 (setq mode-line-buffer-identification
1242 (if (ediff-narrow-control-frame-p)
1243 (ediff-make-narrow-control-buffer-id 'skip-name)
1244 (ediff-make-wide-control-buffer-id)))
1245 ;; Force mode-line redisplay
1246 (force-mode-line-update)
1248 (if (and (ediff-window-display-p) (frame-live-p ediff-control-frame))
1249 (ediff-refresh-control-frame))
1251 (ediff-with-current-buffer ediff-buffer-A
1252 (setq ediff-diff-status buf-A-state-diff)
1253 (ediff-strip-mode-line-format)
1254 (setq mode-line-format
1255 (list " A: " 'ediff-diff-status mode-line-format))
1256 (force-mode-line-update))
1257 (ediff-with-current-buffer ediff-buffer-B
1258 (setq ediff-diff-status buf-B-state-diff)
1259 (ediff-strip-mode-line-format)
1260 (setq mode-line-format
1261 (list " B: " 'ediff-diff-status mode-line-format))
1262 (force-mode-line-update))
1263 (if ediff-3way-job
1264 (ediff-with-current-buffer ediff-buffer-C
1265 (setq ediff-diff-status buf-C-state-diff)
1266 (ediff-strip-mode-line-format)
1267 (setq mode-line-format
1268 (list " C: " 'ediff-diff-status mode-line-format))
1269 (force-mode-line-update)))
1270 (if (ediff-buffer-live-p ediff-ancestor-buffer)
1271 (ediff-with-current-buffer ediff-ancestor-buffer
1272 (ediff-strip-mode-line-format)
1273 ;; we keep the second dummy string in the mode line format of the
1274 ;; ancestor, since for other buffers Ediff prepends 2 strings and
1275 ;; ediff-strip-mode-line-format expects that.
1276 (setq mode-line-format
1277 (list " Ancestor: "
1278 (cond ((not (stringp buf-C-state-merge))
1280 ((string-match "prefer-A" buf-C-state-merge)
1281 "[=diff(B)] ")
1282 ((string-match "prefer-B" buf-C-state-merge)
1283 "[=diff(A)] ")
1284 (t ""))
1285 mode-line-format))))
1289 (defun ediff-refresh-control-frame ()
1290 (if (featurep 'emacs)
1291 ;; set frame/icon titles for Emacs
1292 (modify-frame-parameters
1293 ediff-control-frame
1294 (list (cons 'title (ediff-make-base-title))
1295 (cons 'icon-name (ediff-make-narrow-control-buffer-id))
1297 ;; set frame/icon titles for XEmacs
1298 (setq frame-title-format (ediff-make-base-title)
1299 frame-icon-title-format (ediff-make-narrow-control-buffer-id))
1300 ;; force an update of the frame title
1301 (modify-frame-parameters ediff-control-frame '(()))))
1304 (defun ediff-make-narrow-control-buffer-id (&optional skip-name)
1305 (concat
1306 (if skip-name
1308 (ediff-make-base-title))
1309 (cond ((< ediff-current-difference 0)
1310 (format " _/%d" ediff-number-of-differences))
1311 ((>= ediff-current-difference ediff-number-of-differences)
1312 (format " $/%d" ediff-number-of-differences))
1314 (format " %d/%d"
1315 (1+ ediff-current-difference)
1316 ediff-number-of-differences)))))
1318 (defun ediff-make-base-title ()
1319 (concat
1320 (cdr (assoc 'name ediff-control-frame-parameters))
1321 ediff-control-buffer-suffix))
1323 (defun ediff-make-wide-control-buffer-id ()
1324 (cond ((< ediff-current-difference 0)
1325 (list (format "%%b At start of %d diffs"
1326 ediff-number-of-differences)))
1327 ((>= ediff-current-difference ediff-number-of-differences)
1328 (list (format "%%b At end of %d diffs"
1329 ediff-number-of-differences)))
1331 (list (format "%%b diff %d of %d"
1332 (1+ ediff-current-difference)
1333 ediff-number-of-differences)))))
1337 ;; If buff is not live, return nil
1338 (defun ediff-get-visible-buffer-window (buff)
1339 (if (ediff-buffer-live-p buff)
1340 (if (featurep 'xemacs)
1341 (get-buffer-window buff t)
1342 (get-buffer-window buff 'visible))))
1345 ;;; Functions to decide when to redraw windows
1347 (defun ediff-keep-window-config (control-buf)
1348 (and (eq control-buf (current-buffer))
1349 (/= (buffer-size) 0)
1350 (ediff-with-current-buffer control-buf
1351 (let ((ctl-wind ediff-control-window)
1352 (A-wind ediff-window-A)
1353 (B-wind ediff-window-B)
1354 (C-wind ediff-window-C)
1355 (ancestor-job ediff-merge-with-ancestor-job)
1356 (Ancestor-wind ediff-window-Ancestor))
1358 (and
1359 (ediff-window-visible-p A-wind)
1360 (ediff-window-visible-p B-wind)
1361 ;; if buffer C is defined then take it into account
1362 (or (not ediff-3way-job)
1363 (ediff-window-visible-p C-wind))
1364 (or (not ancestor-job)
1365 (not ediff-show-ancestor)
1366 (ediff-window-visible-p Ancestor-wind))
1367 (eq (window-buffer A-wind) ediff-buffer-A)
1368 (eq (window-buffer B-wind) ediff-buffer-B)
1369 (or (not ediff-3way-job)
1370 (eq (window-buffer C-wind) ediff-buffer-C))
1371 (or (not ancestor-job)
1372 (not ediff-show-ancestor)
1373 (eq (window-buffer Ancestor-wind) ediff-ancestor-buffer))
1374 (string= ediff-window-config-saved
1375 (format "%S%S%S%S%S%S%S%S"
1376 ctl-wind A-wind B-wind C-wind Ancestor-wind
1377 ediff-split-window-function
1378 (ediff-multiframe-setup-p)
1379 ediff-wide-display-p)))))))
1382 (provide 'ediff-wind)
1385 ;; Local Variables:
1386 ;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
1387 ;; eval: (put 'ediff-with-current-buffer 'lisp-indent-hook 1)
1388 ;; eval: (put 'ediff-with-current-buffer 'edebug-form-spec '(form body))
1389 ;; End:
1391 ;;; ediff-wind.el ends here