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