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