home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.006 / xemacs-1 / lib / xemacs-19.13 / lisp / ediff / ediff-wind.el < prev    next >
Encoding:
Text File  |  1995-08-31  |  40.5 KB  |  1,143 lines

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