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