all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Making the width of three windows equal
@ 2005-08-03  0:47 Samuel
  2005-08-03  1:01 ` Pascal Bourguignon
  0 siblings, 1 reply; 31+ messages in thread
From: Samuel @ 2005-08-03  0:47 UTC (permalink / raw)


Hello,

When opening multiple (three) vertically split windows by pressing C-x 3
twice, one of the windows takes up 50% of the screen width and the other
two 25% each. I am looking for an equivalent to what C-x + does for
horizontally split windows, that is, making each of them take up 33% of
the terminal width. Is there a shortcut to do this?

(I am aware of M-33 C-x 3, C-x { and C-x }, but I am looking for an
automated way to do this.)

Any help appreciated.

Thanks,
-Samuel
-- 
 ------------------------------------------------------
|      Samuel Abels       |   http://www.debain.org    |
| spam ad debain dod org  | knipknap ad jabber dod org |
 ------------------------------------------------------

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Making the width of three windows equal
  2005-08-03  0:47 Making the width of three windows equal Samuel
@ 2005-08-03  1:01 ` Pascal Bourguignon
  2005-08-03  2:13   ` Samuel
  0 siblings, 1 reply; 31+ messages in thread
From: Pascal Bourguignon @ 2005-08-03  1:01 UTC (permalink / raw)


Samuel <newsgroups@debain.org> writes:

> Hello,
>
> When opening multiple (three) vertically split windows by pressing C-x 3
> twice, one of the windows takes up 50% of the screen width and the other
> two 25% each. I am looking for an equivalent to what C-x + does for
> horizontally split windows, that is, making each of them take up 33% of
> the terminal width. Is there a shortcut to do this?
>
> (I am aware of M-33 C-x 3, C-x { and C-x }, but I am looking for an
> automated way to do this.)
>
> Any help appreciated.

Since balance-windows doesn't work vertically (or is it
horizontally?), your best bet is to fetch its sources and to edit them
to implement horizontal (or is it vertical?) window balancing.


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Wanna go outside.
Oh, no! Help! I got outside!
Let me back inside!

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Making the width of three windows equal
  2005-08-03  1:01 ` Pascal Bourguignon
@ 2005-08-03  2:13   ` Samuel
  2005-08-03  3:11     ` Pascal Bourguignon
  0 siblings, 1 reply; 31+ messages in thread
From: Samuel @ 2005-08-03  2:13 UTC (permalink / raw)


Pascal Bourguignon wrote:
> > When opening multiple (three) vertically split windows by pressing C-x 3
> > twice, one of the windows takes up 50% of the screen width and the other
> > two 25% each. I am looking for an equivalent to what C-x + does for
> > horizontally split windows, that is, making each of them take up 33% of
> > the terminal width. Is there a shortcut to do this?
>
> Since balance-windows doesn't work vertically (or is it
> horizontally?), your best bet is to fetch its sources and to edit them
> to implement horizontal (or is it vertical?) window balancing.

Thanks, Pascal.
(I had a look at the balance-windows source now, but geesh, this
language is just out of my range.)

-Samuel

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: Making the width of three windows equal
  2005-08-03  2:13   ` Samuel
@ 2005-08-03  3:11     ` Pascal Bourguignon
  2005-08-06 11:59       ` New balance-windows (Was Re: Making the width of three windows equal) Ehud Karni
       [not found]       ` <mailman.2754.1123329756.20277.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 31+ messages in thread
From: Pascal Bourguignon @ 2005-08-03  3:11 UTC (permalink / raw)


"Samuel" <knipknap@gmail.com> writes:

> Pascal Bourguignon wrote:
>> > When opening multiple (three) vertically split windows by pressing C-x 3
>> > twice, one of the windows takes up 50% of the screen width and the other
>> > two 25% each. I am looking for an equivalent to what C-x + does for
>> > horizontally split windows, that is, making each of them take up 33% of
>> > the terminal width. Is there a shortcut to do this?
>>
>> Since balance-windows doesn't work vertically (or is it
>> horizontally?), your best bet is to fetch its sources and to edit them
>> to implement horizontal (or is it vertical?) window balancing.
>
> Thanks, Pascal.
> (I had a look at the balance-windows source now, but geesh, this
> language is just out of my range.)

Well, even if you don't understand anything to lisp, it's quite easy
to substitute width for height, left for bottom and right for top,
isn't it?


(defun horizontal-offset ()
  "Number of columns taken by the fringe and vertical scroll bar"
  ;; TODO: Implement in function of the effective fringe and vertical scroll bar.
  5)

(defun balance-windows-vertically ()
  "Make all visible windows the same width (approximately)."
  (interactive)
  (let ((count -1) levels newsizes level-size
        (last-window (previous-window (frame-first-window (selected-frame))))
        ;; Don't count the columns that are past the lowest main window.
        total)
    ;; Rightmost edge of last window determines what size we have to work with.
    (setq total
          (+ (window-width last-window) (horizontal-offset)
             (nth 0 (window-edges last-window))))
    ;; Find all the different hpos's at which windows start,
    ;; then count them.  But ignore levels that differ by only 1.
    (let (lefts (prev-left -2))
      (walk-windows (function (lambda (w)
                      (setq lefts (cons (nth 0 (window-edges w))
                                        lefts))))
                    'nomini)
      (setq lefts (sort lefts '<))
      (while lefts
        (if (> (car lefts) (1+ prev-left))
            (setq prev-left (car lefts)
                  count (1+ count)))
        (setq levels (cons (cons (car lefts) count) levels))
        (setq lefts (cdr lefts)))
      (setq count (1+ count)))
    ;; Subdivide the frame into desired number of vertical levels.
    (setq level-size (/ total count))
      (message "levels=%S" levels)
      (message "level-size=%S" level-size)
    (save-selected-window
      ;; Set up NEWSIZES to map windows to their desired sizes.
      ;; If a window ends at the rightmost level, don't include
      ;; it in NEWSIZES.  Those windows get the right sizes
      ;; by adjusting the ones above them.
      (walk-windows (function
                     (lambda (w)
                      (let ((newleft (cdr (assq (nth 0 (window-edges w))
                                                levels)))
                            (newright (cdr (assq (+ (window-width w)
                                                    (horizontal-offset)
                                                    (nth 0 (window-edges w)))
                                                 levels))))
                        (message "newleft=%S newright=%S" newleft newright)
                        (if newright
                            (setq newsizes
                                  (cons (cons w (* level-size (- newright newleft)))
                                        newsizes))))))
                    'nomini)
      (message "newsizes=%S" newsizes)
      ;; Make walk-windows start with the leftmost window.
      (select-window (previous-window (frame-first-window (selected-frame))))
      (let (done (count 0))
        ;; Give each window its precomputed size, or at least try.
        ;; Keep trying until they all get the intended sizes,
        ;; but not more than 3 times (to prevent infinite loop).
        (while (and (not done) (< count 3))
          (setq done t)
          (setq count (1+ count))
          (walk-windows (function (lambda (w)
                          (select-window w)
                          (let ((newsize (cdr (assq w newsizes))))
                            (when newsize
                              (enlarge-window (- newsize
                                                 (horizontal-offset)
                                                 (window-width))
                                              t t)
                              (unless (= (window-width)
                                         (- newsize (horizontal-offset)))
                                (setq done nil))))))
                        'nomini))))))

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Cats meow out of angst
"Thumbs! If only we had thumbs!
We could break so much!"

^ permalink raw reply	[flat|nested] 31+ messages in thread

* New balance-windows (Was Re: Making the width of three windows equal)
  2005-08-03  3:11     ` Pascal Bourguignon
@ 2005-08-06 11:59       ` Ehud Karni
  2005-08-06 13:27         ` New balance-windows Ehud Karni
                           ` (3 more replies)
       [not found]       ` <mailman.2754.1123329756.20277.help-gnu-emacs@gnu.org>
  1 sibling, 4 replies; 31+ messages in thread
From: Ehud Karni @ 2005-08-06 11:59 UTC (permalink / raw)
  Cc: knipknap, help-gnu-emacs, spam

Following the recent discussion of `balance-windows' on help-gnu-emacs
I looked into it and wrote a replacement (new) function based on
somewhat different logic to achieve the balancing.

The logic is this: group all windows that has the same "left" (or "top"
for horizontal) edge, and balance their height (width).

The actual resizing is dependent on the window structure.
e.g. the two symmetrical window structures below will be balanced
differently (the diagrams are after vertical balancing):

       +-------+--------+             +-------+--------+
       |       |        |             |       |        |
       | 1 / 3 |        |             |       | 1 / 4  |
       |       |        |             | 1 / 2 +--------+
       +-------|  2 / 3 |             |       |        |
       |       |        |             |       | 1 / 4  |
       | 1 / 3 |        |             +-------+--------+
       |       |        |             |                |
       +-------+--------+             |                |
       |                |             |     1 / 2      |
       |     1 / 3      |             |                |
       |                |             |                |
       +-------+--------+             +-------+--------+

On the other hand if the windows are more "normally" built it works
fine (diagrams after horizontal balancing):

    +-----+-----+------+----+    +-------+-------+-------+
    | 1/4 | 1/4 | 1/4 | 1/4 |    | 1 / 3 | 1 / 3 | 1 / 3 |
    |     |     |     |     |    |       |       |       |
    +-----+-+---+---+-+-----+    +-----+-+---+---+-+-----+
    |       |       |       |    |     |     |     |     |
    | 1 / 3 | 1 / 3 | 1 / 3 |    | 1/4 | 1/4 | 1/4 | 1/4 |
    +-------+-------+-------+    +-----+-----+------+----+

To balance horizontally just add a prefix argument (i.e. C-u).

Note. I don't have CVS write permission, so if some of the developers
find this as adequate replacement to `balance-windows' please add it.


Ehud.


(defun balance-windows (&optional horizontally)
  "Make all visible windows on the current frame the same size (approximately).
If optional prefix arg is not given, \"same size\" is same height.
When prefix arg is given,  \"same size\" is same width."
  (interactive "P")
  (let* (count size w cmjr resize max rpt
         (edge (if horizontally 0 1))  ;; Minor field to sort by 0=LEFT, 1=TOP
         (mjr (- 1 edge))              ;; Major field to sort
         (far (+ 2 edge))              ;; far edge (right/bottom)
         (windows nil)                 ;; list of windows
         (ix 0)
         nwin                          ;; number of windows
         (pass 1)                      ;; pass number
         (curw (selected-window))      ;; selected window (to return to)
         )
    ;; Build and sort list of all windows on frame
       (save-window-excursion
           (walk-windows (function (lambda (w)
                               (let ((ltrb (window-edges w)))
                                   (setq windows (cons (list
                                       (nth mjr  ltrb)
                                       (nth edge ltrb)
                                       (nth far  ltrb)
                                       w) windows)))))
                         'nomini)
           (setq windows (sort windows (lambda (e1 e2)
                                         (if (< (nth 0 e1) (nth 0 e2))
                                               t
                                           (if (= (nth 0 e1) (nth 0 e2))
                                               (if (< (nth 1 e1) (nth 2 e2))
                                                   t)))))))
       (setq nwin (length windows))
       ;; add 1 extra entry (for while check)
       (setq windows (append windows '((-1 -1 -1 nil))))

       (while (< ix nwin)                      ; walk on all (sorted) windows
           (setq count 0)                      ; number of windows in 1 column (or row)
           (setq cmjr (car (nth ix windows)))  ; column / raw identification
           (while (= cmjr (car (nth (+ count ix) windows)))    ; same
               (setq count (1+ count)))        ; count them
           (if (= count 1)                     ; only one window in this column/row
               (setq ix (1+ ix))               ; skip it
             ; compute and resize windows
             (setq size (if (= pass 1)         ; on pass 1 the saved edges have not changed
                          (- (nth 2 (nth (1- (+ count ix)) windows))
                             (nth 1 (nth ix windows)))
                        ;; previous changes may changed the window edges
                        (- (nth far (window-edges (nth 3 (nth (1- (+ count ix)) windows))))
                           (nth edge (window-edges (nth 3 (nth ix windows)))))))
             (setq size (/ (+ size count -1) count)) ; average window size

             (setq max (+ ix count))           ; index of next column/row
             ;; the resizing loop must be done twice
             ;; because later change may resize previous window
             (setq rpt 2)
             (while (> rpt 0)
               (setq rpt (1- rpt))
               (while (< ix max)
                 (setq w (nth 3 (nth ix windows)))
                 (setq resize (- size (- (nth far (window-edges w))
                                         (nth edge (window-edges w)))))
                 ; don't resize by 1 character
                 (if (or (> resize 1)
                         (< resize -1))
                     (progn
                       (select-window w)       ; window to work on
                       (enlarge-window resize horizontally)))
                 (setq ix (1+ ix)))
               (setq ix (- max count)))
             (setq ix max)
             (setq pass 2)))
           (select-window curw)))



--
 Ehud Karni           Tel: +972-3-7966-561  /"\
 Mivtach - Simon      Fax: +972-3-7966-667  \ /  ASCII Ribbon Campaign
 Insurance agencies   (USA) voice mail and   X   Against   HTML   Mail
 http://www.mvs.co.il  FAX:  1-815-5509341  / \
 GnuPG: 98EA398D <http://www.keyserver.net/>    Better Safe Than Sorry

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
  2005-08-06 11:59       ` New balance-windows (Was Re: Making the width of three windows equal) Ehud Karni
@ 2005-08-06 13:27         ` Ehud Karni
       [not found]         ` <mailman.2758.1123335041.20277.help-gnu-emacs@gnu.org>
                           ` (2 subsequent siblings)
  3 siblings, 0 replies; 31+ messages in thread
From: Ehud Karni @ 2005-08-06 13:27 UTC (permalink / raw)
  Cc: help-gnu-emacs, knipknap, spam

There was an error on my last post of the new `balance-windows'.
Thanks to Lennart Borgman <lennart.borgman.073@student.lu.se>
who spotted the small typo that is a big bug.

Bellow is the corrected code.

Ehud.


(defun balance-windows (&optional horizontally)
  "Make all visible windows on the current frame the same size (approximately).
If optional prefix arg is not given, \"same size\" is same height.
When prefix arg is given,  \"same size\" is same width."
  (interactive "P")
  (let* (count size w cmjr resize max rpt
         (edge (if horizontally 0 1))  ;; Minor field to sort by 0=LEFT, 1=TOP
         (mjr (- 1 edge))              ;; Major field to sort
         (far (+ 2 edge))              ;; far edge (right/bottom)
         (windows nil)                 ;; list of windows
         (ix 0)
         nwin                          ;; number of windows
         (pass 1)                      ;; pass number
         (curw (selected-window))      ;; selected window (to return to)
         )
    ;; Build and sort list of all windows on frame
       (save-window-excursion
           (walk-windows (function (lambda (w)
                               (let ((ltrb (window-edges w)))
                                   (setq windows (cons (list
                                       (nth mjr  ltrb)
                                       (nth edge ltrb)
                                       (nth far  ltrb)
                                       w) windows)))))
                         'nomini)
           (setq windows (sort windows (lambda (e1 e2)
                                         (if (< (nth 0 e1) (nth 0 e2))
                                               t
                                           (if (= (nth 0 e1) (nth 0 e2))
                                               (if (< (nth 1 e1) (nth 1 e2))
                                                   t)))))))
       (setq nwin (length windows))
       ;; add 1 extra entry (for while check)
       (setq windows (append windows '((-1 -1 -1 nil))))

       (while (< ix nwin)                      ; walk on all (sorted) windows
           (setq count 0)                      ; number of windows in 1 column (or row)
           (setq cmjr (car (nth ix windows)))  ; column / raw identification
           (while (= cmjr (car (nth (+ count ix) windows)))    ; same
               (setq count (1+ count)))        ; count them
           (if (= count 1)                     ; only one window in this column/row
               (setq ix (1+ ix))               ; skip it
             ; compute and resize windows
             (setq size (if (= pass 1)         ; on pass 1 the saved edges have not changed
                          (- (nth 2 (nth (1- (+ count ix)) windows))
                             (nth 1 (nth ix windows)))
                        ;; previous changes may changed the window edges
                        (- (nth far (window-edges (nth 3 (nth (1- (+ count ix)) windows))))
                           (nth edge (window-edges (nth 3 (nth ix windows)))))))
             (setq size (/ (+ size count -1) count)) ; average window size

             (setq max (+ ix count))           ; index of next column/row
             ;; the resizing loop must be done twice
             ;; because later change may resize previous window
             (setq rpt 2)
             (while (> rpt 0)
               (setq rpt (1- rpt))
               (while (< ix max)
                 (setq w (nth 3 (nth ix windows)))
                 (setq resize (- size (- (nth far (window-edges w))
                                         (nth edge (window-edges w)))))
                 ; don't resize by 1 character
                 (if (or (> resize 1)
                         (< resize -1))
                     (progn
                       (select-window w)       ; window to work on
                       (enlarge-window resize horizontally)))
                 (setq ix (1+ ix)))
               (setq ix (- max count)))
             (setq ix max)
             (setq pass 2)))
           (select-window curw)))



--
 Ehud Karni           Tel: +972-3-7966-561  /"\
 Mivtach - Simon      Fax: +972-3-7966-667  \ /  ASCII Ribbon Campaign
 Insurance agencies   (USA) voice mail and   X   Against   HTML   Mail
 http://www.mvs.co.il  FAX:  1-815-5509341  / \
 GnuPG: 98EA398D <http://www.keyserver.net/>    Better Safe Than Sorry

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
       [not found]       ` <mailman.2754.1123329756.20277.help-gnu-emacs@gnu.org>
@ 2005-08-06 16:39         ` Pascal Bourguignon
  2005-08-06 16:58           ` Lennart Borgman
                             ` (3 more replies)
  0 siblings, 4 replies; 31+ messages in thread
From: Pascal Bourguignon @ 2005-08-06 16:39 UTC (permalink / raw)


"Ehud Karni" <ehud@unix.mvs.co.il> writes:

> Following the recent discussion of `balance-windows' on help-gnu-emacs
> I looked into it and wrote a replacement (new) function based on
> somewhat different logic to achieve the balancing.

Thanks very much.  It's nice.  But it's not perfect, see at the end.

> The logic is this: group all windows that has the same "left" (or "top"
> for horizontal) edge, and balance their height (width).
>
> The actual resizing is dependent on the window structure.
> e.g. the two symmetrical window structures below will be balanced
> differently (the diagrams are after vertical balancing):
>
>        +-------+--------+             +-------+--------+
>        |       |        |             |       |        |
>        | 1 / 3 |        |             |       | 1 / 4  |
>        |       |        |             | 1 / 2 +--------+
>        +-------|  2 / 3 |             |       |        |
>        |       |        |             |       | 1 / 4  |
>        | 1 / 3 |        |             +-------+--------+
>        |       |        |             |                |
>        +-------+--------+             |                |
>        |                |             |     1 / 2      |
>        |     1 / 3      |             |                |
>        |                |             |                |
>        +-------+--------+             +-------+--------+

I'm not sure it's justified.

Note that:

        +------+------+
        |      |      |
        |      |      |
        +------+------+
        |      |      |
        |      |      |
        +------+------+

may represent two different structures: C-x 2 C-x 3 C-x o C-x 3
or C-x 3 C-x 2 C-x o C-x 2


But in both these cases:

        +-------+--------+             +-------+--------+
        |       |        |             |       |        |
        | 1 / 3 |        |             |       | 1 / 4  |
        |       |        |             | 1 / 2 +--------+
        +-------|  2 / 3 |             |       |        |
        |       |        |             |       | 1 / 4  |
        | 1 / 3 |        |             +-------+--------+
        |       |        |             |                |
        +-------+--------+             |                |
        |                |             |     1 / 2      |
        |     1 / 3      |             |                |
        |                |             |                |
        +-------+--------+             +-------+--------+

the hierarchy of splits is the same, so I don't see why it should
balance differently.

I think a correct algorithm should recover the split tree, then make
the balancing depending on the window counts in subtrees.




C-x 2 C-x 3 C-x 2 C-x 2 M-x balance-window RET  is OK:

        +-------+-------+
        |       |       |
        |       |       |
        +-------+       |
        |       |       |
        |       |       |
        +-------+       |
        |       |       |
        |       |       |
        +-------+-------+
        |               |
        |               |
        +---------------+

but then: C-X o C-X o C-X o C-X o C-x 2, giving:

        +-------+-------+
        |       |       |
        |       |       |
        +-------+       |
        |       |       |
        |       |       |
        +-------+       |
        |       |       |
        |       |       |
        +-------+-------+
        |               |
        +---------------+
        |               |
        +---------------+

and M-x balance-window RET doesn't balance at all:

        +-------+-------+
        |       |       |
        |       |       |
        +-------+       |
        |       |       |
        |       |       |
        +-------+       |
        |       |       |
        |       |       |
        +-------+-------+
        +---------------+
        |               |
        |               |
        +---------------+



I'd expect:

        +-------+-------+
        |       |       |
        +-------+       |
        |       |       |
        +-------+       |
        |       |       |
        +-------+-------+
        |               |
        +---------------+
        |               |
        +---------------+



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

The world will now reboot.  don't bother saving your artefacts.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
       [not found]         ` <mailman.2758.1123335041.20277.help-gnu-emacs@gnu.org>
@ 2005-08-06 16:42           ` Pascal Bourguignon
  0 siblings, 0 replies; 31+ messages in thread
From: Pascal Bourguignon @ 2005-08-06 16:42 UTC (permalink / raw)


"Ehud Karni" <ehud@unix.mvs.co.il> writes:

> There was an error on my last post of the new `balance-windows'.
> Thanks to Lennart Borgman <lennart.borgman.073@student.lu.se>
> who spotted the small typo that is a big bug.
>
> Bellow is the corrected code.

Why did you create another thread?

The problem described in the other thread still exists with this version.


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Nobody can fix the economy.  Nobody can be trusted with their finger
on the button.  Nobody's perfect.  VOTE FOR NOBODY.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
  2005-08-06 16:39         ` Pascal Bourguignon
@ 2005-08-06 16:58           ` Lennart Borgman
       [not found]           ` <mailman.2773.1123347813.20277.help-gnu-emacs@gnu.org>
                             ` (2 subsequent siblings)
  3 siblings, 0 replies; 31+ messages in thread
From: Lennart Borgman @ 2005-08-06 16:58 UTC (permalink / raw)
  Cc: help-gnu-emacs

Pascal Bourguignon wrote:

>Note that:
>
>        +------+------+
>        |      |      |
>        |      |      |
>        +------+------+
>        |      |      |
>        |      |      |
>        +------+------+
>
>may represent two different structures: C-x 2 C-x 3 C-x o C-x 3
>or C-x 3 C-x 2 C-x o C-x 2
>
>
>But in both these cases:
>
>        +-------+--------+             +-------+--------+
>        |       |        |             |       |        |
>        | 1 / 3 |        |             |       | 1 / 4  |
>        |       |        |             | 1 / 2 +--------+
>        +-------|  2 / 3 |             |       |        |
>        |       |        |             |       | 1 / 4  |
>        | 1 / 3 |        |             +-------+--------+
>        |       |        |             |                |
>        +-------+--------+             |                |
>        |                |             |     1 / 2      |
>        |     1 / 3      |             |                |
>        |                |             |                |
>        +-------+--------+             +-------+--------+
>
>the hierarchy of splits is the same, so I don't see why it should
>balance differently.
>
>I think a correct algorithm should recover the split tree, then make
>the balancing depending on the window counts in subtrees.
>  
>
Is the problem really that welldefined in Emacs? Do you know how the 
windows have been splitted? The difference above may perhaps be seen as 
emerging from that difficulty?

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
       [not found]           ` <mailman.2773.1123347813.20277.help-gnu-emacs@gnu.org>
@ 2005-08-06 20:45             ` Pascal Bourguignon
  2005-08-06 21:14               ` Lennart Borgman
       [not found]               ` <mailman.2796.1123363907.20277.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 31+ messages in thread
From: Pascal Bourguignon @ 2005-08-06 20:45 UTC (permalink / raw)


Lennart Borgman <lennart.borgman.073@student.lu.se> writes:
>>
>>I think a correct algorithm should recover the split tree, then make
>>the balancing depending on the window counts in subtrees.
>>  
>>
> Is the problem really that welldefined in Emacs? Do you know how the
> windows have been splitted? The difference above may perhaps be seen
> as emerging from that difficulty?

Indeed, but the data is available at least internally, so it should be
easy to patch emacs to publish window parameters like it's done for
frame parameters for example.

File: elisp,  Node: Window Internals

Window Internals
----------------

   Windows have the following accessible fields:

`frame'
     The frame that this window is on.

`mini_p'
     Non-`nil' if this window is a minibuffer window.

`parent'
     Internally, Emacs arranges windows in a tree; each group of
     siblings has a parent window whose area includes all the siblings.
     This field points to a window's parent.

     Parent windows do not display buffers, and play little role in
     display except to shape their child windows.  Emacs Lisp programs
     usually have no access to the parent windows; they operate on the
     windows at the leaves of the tree, which actually display buffers.

     The following four fields also describe the window tree structure.

`hchild'
     In a window subdivided horizontally by child windows, the leftmost
     child.  Otherwise, `nil'.

`vchild'
     In a window subdivided vertically by child windows, the topmost
     child.  Otherwise, `nil'.

`next'
     The next sibling of this window.  It is `nil' in a window that is
     the rightmost or bottommost of a group of siblings.

`prev'
     The previous sibling of this window.  It is `nil' in a window that
     is the leftmost or topmost of a group of siblings.


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
-----BEGIN GEEK CODE BLOCK-----
Version: 3.12
GCS d? s++:++ a+ C+++ UL++++ P--- L+++ E+++ W++ N+++ o-- K- w--- 
O- M++ V PS PE++ Y++ PGP t+ 5+ X++ R !tv b+++ DI++++ D++ 
G e+++ h+ r-- z? 
------END GEEK CODE BLOCK------

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
  2005-08-06 16:39         ` Pascal Bourguignon
  2005-08-06 16:58           ` Lennart Borgman
       [not found]           ` <mailman.2773.1123347813.20277.help-gnu-emacs@gnu.org>
@ 2005-08-06 21:05           ` Ehud Karni
  2005-08-06 23:22             ` Lennart Borgman
  2005-08-07  2:17           ` Lennart Borgman
  3 siblings, 1 reply; 31+ messages in thread
From: Ehud Karni @ 2005-08-06 21:05 UTC (permalink / raw)
  Cc: help-gnu-emacs

On Sat, 06 Aug 2005 18:39:14 +0200, Pascal Bourguignon wrote:
>
> "Ehud Karni" <ehud@unix.mvs.co.il> writes:
>
> > Following the recent discussion of `balance-windows' on help-gnu-emacs
> > I looked into it and wrote a replacement (new) function based on
> > somewhat different logic to achieve the balancing.
>

I think it is good as it can get until Emacs resizing is changed.

In Emacs 22.0.50 a 3rd argument was add to enlarge window:
    Optional third arg PRESERVE-BEFORE, if non-nil, means do not
    change the size of the siblings above or to the left of the
    selected window. Only siblings to the right or below are changed.

I tried using this argument but I found a problem (bug ?).
When you have a configuration like:

    +----------+----------+
    +   lw1    +   rw1    +
    +----------+          +
    +   lw2    +----------+
    +----------+   rw2    +
    +   lw3    +          +
    +----------+----------+
    +         fw6         +
    +----------+----------+

You can move the border between windows lw3/rw2 and fw6 with
enlarge-window command in lw3/rw2. i.e. the command
(enlarge-window 5 nil t) in lw3/rw2 does nothing.

Because the preserving is regarding only windows to the left and
above the current window (and there is no other way to specify the
size of a window) the "enlarging/shrinking" must be done from top
to bottom or left to right (which my function does).

Below is my latest version (using PRESERVE-BEFORE - available only
in 22.0) which is failing in such situation.

NOTE. This discussion really should be done in emacs-devel@gnu.org
list and not in help-gnu-emacs@gnu.org.

Ehud.


The lines with "^ ;; (" are for debugging, just drop the ";;" and
you'll see animation of the resizing with messages in the echo area.


(defun balance-windows (&optional horizontally)
  "Make all visible windows on the current frame the same size (approximately).
If optional prefix arg is not given, \"same size\" is same height.
When prefix arg is given,  \"same size\" is same width."
  (interactive "P")
  (let* (count size w cmjr resize
         (edge (if horizontally 0 1))  ;; Minor field to sort by 0=LEFT, 1=TOP
         (mjr (- 1 edge))              ;; Major field to sort
         (far (+ 2 edge))              ;; far edge (right/bottom) - for current size
         (windows nil)                 ;; list of windows
         (ix 0)
         nwin                          ;; number of windows
         (curw (selected-window))      ;; selected window (to return to)
         )
    ;; Build and sort list of all windows on frame
       (save-window-excursion
           (walk-windows (function (lambda (w)
                               (let ((ltrb (window-edges w)))
                                   (setq windows (cons (list
                                       (nth mjr  ltrb)
                                       (nth edge ltrb)
                                       (nth far  ltrb)
                                       w) windows)))))
                         'nomini)
           (setq windows (sort windows (lambda (e1 e2)
                                         (if (< (nth 0 e1) (nth 0 e2))
                                               t
                                           (if (= (nth 0 e1) (nth 0 e2))
                                               (if (< (nth 1 e1) (nth 1 e2))
                                                   t)))))))
       (setq nwin (length windows))
       ;; add 1 extra entry (for while check)
       (setq windows (append windows '((-1 -1 -1 nil))))

       (while (< ix nwin)                      ; walk on all (sorted) windows
           (setq count ix)                     ; count the windows in 1 column (or row)
           (setq cmjr (car (nth ix windows)))  ; column / raw identification
           (while (= cmjr (car (nth ix windows)))  ; same column / row
               (setq ix (1+ ix)))              ; next window
           (setq count (- ix count))
           (if (/= count 1)                    ; do only if more than one window in this column/row
               (let ((gix (- ix count)))
                 (setq size (- (nth far (window-edges (nth 3 (nth (1- ix) windows))))
                               (nth edge (window-edges (nth 3 (nth (- ix count) windows))))))
                 (setq size (/ (+ size count -1) count)) ; average window size

 ;; (message "Size=%d" size)

                 (while (< gix ix)
                   (setq w (nth 3 (nth gix windows)))
                   (setq resize (- size (- (nth far (window-edges w))
                                           (nth edge (window-edges w)))))

 ;; (message "Window=%s  resize=%d" w resize)
                   ; don't resize by 1 character/line
                   (if (or (> resize 1)
                           (< resize -1))
                       (progn

 ;; (sit-for 2)

                         (select-window w)       ; window to work on
                         (enlarge-window resize horizontally 'preserve)
 ;; (sit-for 2)
                         ))
                   (setq gix (1+ gix))))))

 ;; (message "")
       (select-window curw)))



--
 Ehud Karni           Tel: +972-3-7966-561  /"\
 Mivtach - Simon      Fax: +972-3-7966-667  \ /  ASCII Ribbon Campaign
 Insurance agencies   (USA) voice mail and   X   Against   HTML   Mail
 http://www.mvs.co.il  FAX:  1-815-5509341  / \
 GnuPG: 98EA398D <http://www.keyserver.net/>    Better Safe Than Sorry

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
  2005-08-06 20:45             ` Pascal Bourguignon
@ 2005-08-06 21:14               ` Lennart Borgman
       [not found]               ` <mailman.2796.1123363907.20277.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 31+ messages in thread
From: Lennart Borgman @ 2005-08-06 21:14 UTC (permalink / raw)
  Cc: help-gnu-emacs

Pascal Bourguignon wrote:

>>Is the problem really that welldefined in Emacs? Do you know how the
>>windows have been splitted? The difference above may perhaps be seen
>>as emerging from that difficulty?
>>    
>>
>
>Indeed, but the data is available at least internally, so it should be
>easy to patch emacs to publish window parameters like it's done for
>frame parameters for example.
>
>File: elisp,  Node: Window Internals
>  
>
Thanks, I did not know this was available. Then the windows in each 
frame can be seen as a tree using those fields you mentioned. But what 
should then be done with this? What should the mapping between this tree 
and the visual view be? It looks to me that the level in the tree alone 
will not give any useful hint. The topology (ie whether the splitting 
was horizontal or vertical) must be taken into account, but maybe the 
level in the tree can be used too? It actually looks a bit difficult...

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
  2005-08-06 21:05           ` Ehud Karni
@ 2005-08-06 23:22             ` Lennart Borgman
  0 siblings, 0 replies; 31+ messages in thread
From: Lennart Borgman @ 2005-08-06 23:22 UTC (permalink / raw)
  Cc: emacs-devel

Ehud Karni wrote:

>I tried using this argument but I found a problem (bug ?).
>When you have a configuration like:
>
>    +----------+----------+
>    +   lw1    +   rw1    +
>    +----------+          +
>    +   lw2    +----------+
>    +----------+   rw2    +
>    +   lw3    +          +
>    +----------+----------+
>    +         fw6         +
>    +----------+----------+
>
>You can move the border between windows lw3/rw2 and fw6 with
>enlarge-window command in lw3/rw2. i.e. the command
>(enlarge-window 5 nil t) in lw3/rw2 does nothing.
>  
>
Seems like a bug to me too. I can see the same problem.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
  2005-08-06 16:39         ` Pascal Bourguignon
                             ` (2 preceding siblings ...)
  2005-08-06 21:05           ` Ehud Karni
@ 2005-08-07  2:17           ` Lennart Borgman
  2005-08-08  9:36             ` Ehud Karni
       [not found]             ` <mailman.2988.1123495783.20277.help-gnu-emacs@gnu.org>
  3 siblings, 2 replies; 31+ messages in thread
From: Lennart Borgman @ 2005-08-07  2:17 UTC (permalink / raw)
  Cc: help-gnu-emacs, Emacs Devel

Pascal Bourguignon wrote:

>"Ehud Karni" <ehud@unix.mvs.co.il> writes:
>
>  
>
>>Following the recent discussion of `balance-windows' on help-gnu-emacs
>>I looked into it and wrote a replacement (new) function based on
>>somewhat different logic to achieve the balancing.
>>    
>>
>
>Thanks very much.  It's nice.  But it's not perfect, see at the end.
>
>  
>
>...
>I think a correct algorithm should recover the split tree, then make
>the balancing depending on the window counts in subtrees.
>  
>
I think Pascal is right. Though I think Ehud has made a very nice try I 
believe the split tree must be used. There is not enough information to 
solve the problem otherwise.

Could it perhaps be done like this?:

1) Walk the tree of windows and compute and remember a weight for the 
childs in the subtree of each window and store that.

2) Walk the tree of windows once again and resize according to the 
weights from the top of the tree towards the bottom in each branch 
(recursively of course)!

The weight could be computed as just the sum of childs but I think that 
should look odd and not be useful. Therefore I suggest that for each 
level in the subtree the weight is reduced by some factor. Naturally, in 
the usual mind of Emacs, this could be either a fixed fraction, say 0.7, 
or a list of fractions.

I believe this should be easy to implement but I might have forgotten 
something?

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows (Was Re: Making the width of three windows equal)
  2005-08-06 11:59       ` New balance-windows (Was Re: Making the width of three windows equal) Ehud Karni
  2005-08-06 13:27         ` New balance-windows Ehud Karni
       [not found]         ` <mailman.2758.1123335041.20277.help-gnu-emacs@gnu.org>
@ 2005-08-07 17:15         ` Richard M. Stallman
  2005-08-08  9:27           ` Ehud Karni
       [not found]           ` <mailman.2979.1123493766.20277.help-gnu-emacs@gnu.org>
       [not found]         ` <mailman.2888.1123436059.20277.help-gnu-emacs@gnu.org>
  3 siblings, 2 replies; 31+ messages in thread
From: Richard M. Stallman @ 2005-08-07 17:15 UTC (permalink / raw)
  Cc: knipknap, help-gnu-emacs, spam, emacs-devel

Why do you think this is better than the current balance-windows function?

(I would rather we focus attention on the steps needed to make a
release.)

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
       [not found]               ` <mailman.2796.1123363907.20277.help-gnu-emacs@gnu.org>
@ 2005-08-07 18:23                 ` Pascal Bourguignon
  2005-08-07 18:59                   ` Lennart Borgman
       [not found]                   ` <mailman.2899.1123441421.20277.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 31+ messages in thread
From: Pascal Bourguignon @ 2005-08-07 18:23 UTC (permalink / raw)


Lennart Borgman <lennart.borgman.073@student.lu.se> writes:

> Pascal Bourguignon wrote:
>
>>>Is the problem really that welldefined in Emacs? Do you know how the
>>>windows have been splitted? The difference above may perhaps be seen
>>>as emerging from that difficulty?
>>>    
>>>
>>
>>Indeed, but the data is available at least internally, so it should be
>>easy to patch emacs to publish window parameters like it's done for
>>frame parameters for example.
>>
>>File: elisp,  Node: Window Internals
>>  
>>
> Thanks, I did not know this was available. Then the windows in each
> frame can be seen as a tree using those fields you mentioned. But what
> should then be done with this? What should the mapping between this
> tree and the visual view be? It looks to me that the level in the tree
> alone will not give any useful hint. The topology (ie whether the
> splitting was horizontal or vertical) must be taken into account, but
> maybe the level in the tree can be used too? It actually looks a bit
> difficult...

Well, it's only available to the C programmer...

Since window parents are not normal emacs lisp windows, I assume we'd
export the window internals as a new data type. Let's call it "split".

(frame-split-root [frame])           --> split or nil
(window-configuration-split winconf) --> split or nil
(splitp object)                      --> boolean
(split-direction split)              --> :vertical | :horizontal
;; (window-split-vertically) produces a :vertical split-direction.
(split-edges sow)                    --> (left top right bottom)
;; Perhaps (defalias split-edges window-edges)
(split-cuts split)                   --> (BReak  BReak  ...)
;; The bottom or right of the correponding child.
(split-children split)               --> (child  child  ...)
;; A split child may be a window or a split.
(split-parent sow) --> split
(enlarge-split sow increment preserve-before)


;; The parent is null for root splits or windows,
;; othewise it's always a split.
(or (null   (split-parent sow))
    (splitp (split-parent sow)))

;; the edges of the split are the same as the edge of an alone window:
(equal (split-edges split) (progn (delete-other-windows) (window-edges)))

;; the length is the number of collapsed windows or splits:
(= (length (split-cuts split)) (length (split-children split)))

;; child splits are perpendicular:
(every (lambda (child-split)
         (not (eq (split-direction split) (split-direction child-split))))
       (delete-if-not (function splitp) (split-children split)))

;; split cuts are sorted (hence the order of the corresponding split-children
;; list):
(dotimes (i (1- (length (split-cuts split))))
  (< (nth i (split-cuts split)) (nth (1+ i) (split-cuts split))))


(dotimes (i (length (split-cuts split)))
  (and
   ;; all children are either a split or a window:
   (or (windowp  (nth i (split-children split)))
       (splitp   (nth i (split-children split))))
   ;; the parent of each children of split is the split itself:
   (eq split (split-parent (nth i (split-children split))))
   ;; the cuts are the bottom or right of the corresponding child:
   (= (nth i (split-cuts split))
      (funcall (if (eq (split-direction split) :vertical)
                   (function bottom)
                   (function right))
               (split-edges (nth i (split-children split)))))
   ;; the sides are the same for all children:
   (every (lambda (side)
            (= (funcall side (split-edges split))
               (funcall side (split-edges (nth i (split-children split))))))
          (if (eq (split-direction split) :vertical)
              (list (function left) (function right))
              (list (function top)  (function bottom))))
   ))

Several parallel cuts are collapsed into one split.

(progn (delete-other-windows)
       (split-window-vertically)
       (split-window-vertically))

and:

(progn (delete-other-windows)
       (split-window-vertically)
       (other-window 1)
       (split-window-vertically))

would both give (= 3 (length (split-cuts (frame-split-root)))).
And:

(equal (progn (delete-other-windows)
              (split-window-vertically)
              (split-window-vertically)
              (frame-split-root))
       (progn (delete-other-windows)
              (split-window-vertically)
              (other-window 1)
              (split-window-vertically)
              (frame-split-root)))




Then the balancing algorithm could be as simple as:


(require 'cl)
(defun plusp  (x) (< 0 x))
(defun left   (x) (first  x))
(defun top    (x) (second x))
(defun right  (x) (third  x))
(defun bottom (x) (fourth x))

(defun split-height (split)
  (- (bottom (split-edges split)) (top  (split-edges split))))

(defun split-width  (split)
  (- (right  (split-edges split)) (left (split-edges split))))
   
(defun balance-split (split)
  (labels ((count-children (sow direction)
             ;; This could be cached into the split-or-window structure
             (if (splitp sow)
                 (reduce (if (eq (split-direction sow) direction)
                             (function +)
                             (function max))
                         (mapcar (lambda (child) 
                                    (count-children child direction))
                                 (split-children sow)))
                 1)))
    (let* ((relative-sizes
            (mapcar (lambda (child) 
                       (count-children child (split-direction split)))
                    (split-children split)))
           (total (reduce (function +) relative-sizes))
           (split-size (if (eq (split-direction split) :vertical)
                           (split-height split)
                           (split-width  split))))
      (loop
         for child-size in relative-sizes
         for child in (butlast (split-children split))
         for new-size = (truncate (* split-size child-size) total)
         do (enlarge-split child
                           (- new-size
                              (if (eq (split-direction split) :vertical)
                                  (split-height child)
                                  (split-width  child)))
                           (split-direction split)
                           t))
      (dolist (child (split-children split))
        (when (splitp child)
          (balance-split child))))))

(defun balance-windows ()
  (interactive)
  (when (splitp (frame-split-root))
    (balance-split (frame-split-root))))


And give excelent results, see at the end for an example.


;; The following is a simulator for the above specified split data structure.

(defstruct sow direction parent children right bottom)

(defun split-or-window-previous (sow)
  (let ((parent  (split-or-window-parent sow)))
    (when parent
      (let* ((children (split-or-window-children parent))
             (i (position sow children)))
        (and i (plusp i) (nth (1- i) children))))))
    
(defun split-or-window-left (sow)
  (let ((parent (split-or-window-parent sow)))
    (if parent
        (if (eq (split-or-window-direction parent) :horizontal)
            (let ((previous (split-or-window-previous sow)))
              (if previous
                  (split-or-window-right previous)
                  (split-or-window-left  parent)))
            (split-or-window-left  parent))
        0)))

(defun split-or-window-top (sow)
  (let ((parent (split-or-window-parent sow)))
    (if parent
        (if (eq (split-or-window-direction parent) :vertical)
            (let ((previous (split-or-window-previous sow)))
              (if previous
                  (split-or-window-bottom previous)
                  (split-or-window-top   parent)))
            (split-or-window-top   parent))
        0)))

(defun splitp (sow)
  (and (split-or-window-p sow)
       (split-or-window-children sow)))

(defun split-edges (sow)
  (list (split-or-window-left sow)
        (split-or-window-top sow)
        (split-or-window-right sow)
        (split-or-window-bottom sow)))

(defvar *current-window*   (make-split-or-window  :right 42 :bottom 42))
(defvar *frame-split-root* *current-window*)
(defun frame-split-root    (&optional frame)  *frame-split-root*)
(defvar *window-list*      (list *current-window*))
(defun window-list*        () *window-list*)
(defun current-window      () *current-window*)

(defun initialize (width height)
  (setf *current-window*    (make-split-or-window  :right width :bottom height)
        *frame-split-root*  *current-window*
        *window-list* (list *current-window*)))

(defun split-direction (split)
  (assert (splitp split))
  (split-or-window-direction split))

(defun split-cuts (split)
  (assert (splitp split))
  (mapcar (if (eq (split-direction split) :vertical)
              (function bottom)
              (function right)) (split-children split)))

(defun split-children (split)
  (assert (splitp split))
  (split-or-window-children split))

(defun split-parent (sow)
  (split-or-window-parent sow))

(defun enlarge-split (sow increment direction preserve-before)
  (unless (zerop increment)
    (if (eq direction :vertical)
        (incf (split-or-window-bottom sow) increment)
        (incf (split-or-window-right  sow) increment))
    (when (splitp sow)
      (if (eq (split-direction sow) direction)
          ;; change the size in same direction
          ;; TODO: check increment vs. last size and preserve-before
          (let ((last-child  (first (last (split-or-window-children
                                           sow)))))
            (enlarge-split last-child increment direction preserve-before))
          ;; change the size orthogonally
          (dolist (child (split-or-window-children sow))
            (enlarge-split child increment direction preserve-before))))
    (let ((parent (split-or-window-parent sow)))
      (when (and parent (eq (split-direction parent) direction))
        (let ((next (second (memq sow (split-or-window-children parent)))))
          (when next
            (if (eq direction :vertical)
                (incf (split-or-window-top  next) increment)
                (incf (split-or-window-left next) increment))))))))

(defun insert-after (new old list) (push new (cdr (memq old list))))

(defun split (direction &optional size)
  (flet ((split-size (split) (if (eq direction :vertical)
                                 (split-height split)
                                 (split-width  split)))
         (make-split (direction window parent)
           (let* ((edges (split-edges window))
                  (result (make-split-or-window
                           :parent parent
                           :children (list window)
                           :direction direction
                           :right  (right  edges)
                           :bottom (bottom edges))))
             (setf (split-or-window-parent window) result))))
    (setf size (or size (/ (split-size (current-window)) 2)))
    (unless (< 1 size)
      (error  "split: Window too small."))
    (when (<= (split-size (current-window)) size)
      (error "split: Too big size asked."))
    (let ((split (split-parent (current-window))))
      (cond
        ((null split)
         ;; make a new root split:
         (setf split (make-split direction (current-window) nil))
         (setf *frame-split-root* split))
        ((not (eq direction (split-direction split)))
         ;; make a new perpendicular split
         (let ((perpendicular (make-split direction (current-window) split)))
           (setf (split-or-window-children split)
                 (nsubstitute perpendicular (current-window)
                              (split-or-window-children split)))
           (assert (memq perpendicular (split-or-window-children split)))
           (setf split perpendicular))))
      (assert (eq split (split-parent (current-window))))
      (assert (memq (current-window) (split-children split)))
      (assert (eq direction (split-direction split)))
      (let* ((dx (if (eq direction :vertical) 0 size))
             (dy (if (eq direction :vertical) size 0))
             (edges (split-edges (current-window)))
             ;; make a new window:
             (other (make-split-or-window
                     :parent split
                     :right  (right  edges)
                     :bottom (bottom edges))))
        (if (eq direction :vertical)
            (setf (split-or-window-bottom (current-window)) (+ (top  edges) dy))
            (setf (split-or-window-right (current-window))  (+ (left edges) dx)))
        (insert-after other (current-window) (split-or-window-children split))
        (insert-after other (current-window) *window-list*)
        (assert (memq (current-window) *window-list*))
        (assert (memq other            *window-list*))
        (assert (memq (current-window) (split-or-window-children split)))
        (assert (memq other            (split-or-window-children split)))))))

(defun other-window* (n &optional all-frames)
  (let ((i (mod (+ (position (current-window) (window-list*)) n)
                (length (window-list*)))))
    (setf *current-window* (nth i (window-list*)))))

(defun windowp* (window) (memq window (window-list*)))

(defun delete-other-windows* (&optional window)
  (when (windowp* window)
    (setf *current-window* window))
  (setf window (current-window))
  (when (split-parent window)
    (let ((root  (frame-split-root)))
      (setf (split-or-window-left   window) (split-or-window-left   root)
            (split-or-window-top    window) (split-or-window-top    root)
            (split-or-window-right  window) (split-or-window-right  root)
            (split-or-window-bottom window) (split-or-window-bottom root)))
    (setf (split-or-window-parent window) nil)
    (setf *frame-split-root* window
          *window-list* (list window))))
     
(defun split-describe (split &optional level)
  (setf level (or level ""))
  (if (splitp split)
      (progn
        (insert (format "%s#<split %s %s %s %s>\n"
                  level
                  (format ":direction %S" (split-direction split))
                  (format ":parent %S" (not (null (split-parent split))))
                  (format ":edges %S" (split-edges split))
                  (format ":children %S" (length (split-children split)))))
        (dolist (child (split-children split))
          (split-describe child (concat "  " level))))
      (insert (format "%s#<window %s %s>\n"
                level
                (format ":parent %S" (not (null (split-parent split))))
                (format ":edges %S" (split-edges split))))))

(defun split-draw (split)
  (with-current-buffer (get-buffer-create "*splits*")
    (erase-buffer)
    (unless (eq major-mode 'picture-mode)
      (picture-mode))
    (picture-open-line (1+ (bottom (split-edges split))))
    (labels ((goto (x y)
               (message "goto %s %s" x y)
               (goto-line y)
               (beginning-of-line)
               (picture-forward-column x))
             (draw-rectangle (edges)
               (picture-draw-rectangle
                (progn (goto (left  edges) (top    edges)) (point))
                (progn (goto (right edges) (bottom edges)) (point))))
             (draw-split (split)
               (draw-rectangle (split-edges split))
               (if (splitp split)
                   (dolist (child (split-children split))
                     (draw-split child)))))
      (draw-split split)))
  (sit-for 1)
  (force-mode-line-update t))



Let's make some windows:

(progn
  (initialize 60 56)
  (delete-other-windows*)
  (split :vertical)
  (split :horizontal)
  (split :vertical)
  (split :vertical)
  (balance-windows) (split-draw (frame-split-root))
  (other-window* 4)
  (split :vertical)
  (split :horizontal)
  (split :horizontal)
  (other-window* 1)
  (split :vertical)
  (balance-windows) (split-draw (frame-split-root))
  (other-window* 7)
  (split :vertical)
  (split :vertical)
  (split :vertical)
  (balance-windows) (split-draw (frame-split-root))
  (split-describe (frame-split-root)))

#<split :direction :vertical :parent nil :edges (0 0 60 56) :children 3>
  #<split :direction :horizontal :parent t :edges (0 0 60 32) :children 2>
    #<split :direction :vertical :parent t :edges (0 0 30 32) :children 3>
      #<window :parent t :edges (0 0 30 10)>
      #<window :parent t :edges (0 10 30 20)>
      #<window :parent t :edges (0 20 30 32)>
    #<split :direction :vertical :parent t :edges (30 0 60 32) :children 4>
      #<window :parent t :edges (30 0 60 8)>
      #<window :parent t :edges (30 8 60 16)>
      #<window :parent t :edges (30 16 60 24)>
      #<window :parent t :edges (30 24 60 32)>
  #<split :direction :horizontal :parent t :edges (0 32 60 48) :children 3>
    #<window :parent t :edges (0 32 20 48)>
    #<split :direction :vertical :parent t :edges (20 32 40 48) :children 2>
      #<window :parent t :edges (20 32 40 40)>
      #<window :parent t :edges (20 40 40 48)>
    #<window :parent t :edges (40 32 60 48)>
  #<window :parent t :edges (0 48 60 56)>


+-----------------------------+-----------------------------+
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             +-----------------------------+
|                             |                             |
+-----------------------------|                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             +-----------------------------+
|                             |                             |
|                             |                             |
|                             |                             |
+-----------------------------|                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             +-----------------------------+
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
+-------------------+-------------------+-------------------+
|                   |                   |                   |
|                   |                   |                   |
|                   |                   |                   |
|                   |                   |                   |
|                   |                   |                   |
|                   |                   |                   |
|                   |                   |                   |
|                   +-------------------|                   |
|                   |                   |                   |
|                   |                   |                   |
|                   |                   |                   |
|                   |                   |                   |
|                   |                   |                   |
|                   |                   |                   |
|                   |                   |                   |
+-----------------------------------------------------------+
|                                                           |
|                                                           |
|                                                           |
|                                                           |
|                                                           |
|                                                           |
|                                                           |
+-----------------------------------------------------------+


The current algorithm something like the following, that doesn't look
like "balanced" to me:

+-----------------------------+-----------------------------+
|                             |                             |
|                             |         too small           |
|                             |                             |
|                             +-----------------------------+
|                             |                             |
|                             |                             |
|                             |                             |
+-----------------------------+-----------------------------+
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
+-----------------------------+-----------------------------+
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
|                             |                             |
+-------------+---------------+-----------------------------+
|             |               |                             |
|             |               |                             |
|             |               |                             |
|             |               |                             |
|             |               |                             |
|             +---------------|        too big              |
|             |               |                             |
|             |               |                             |
|             |               |                             |
|             |               |                             |
|             |               |                             |
+-------------+---------------+-----------------------------+
|                                                           |
|                                                           |
|                                                           |
|                                                           |
|                                                           |
|                                                           |
|                                                           |
|                       too big                             |
|                                                           |
|                                                           |
|                                                           |
+-----------------------------------------------------------+


Finally: I'm posting my balance-windows / balance-split here rather
than on gnu.emacs.develp because I feel it's more a user-level
feature, if only the right internals were exported.

(Perhaps some users will prefer the current version of balance-windows.)


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
-----BEGIN GEEK CODE BLOCK-----
Version: 3.12
GCS d? s++:++ a+ C+++ UL++++ P--- L+++ E+++ W++ N+++ o-- K- w--- 
O- M++ V PS PE++ Y++ PGP t+ 5+ X++ R !tv b+++ DI++++ D++ 
G e+++ h+ r-- z? 
------END GEEK CODE BLOCK------

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
       [not found]         ` <mailman.2888.1123436059.20277.help-gnu-emacs@gnu.org>
@ 2005-08-07 18:31           ` Pascal Bourguignon
  0 siblings, 0 replies; 31+ messages in thread
From: Pascal Bourguignon @ 2005-08-07 18:31 UTC (permalink / raw)


"Richard M. Stallman" <rms@gnu.org> writes:
> Why do you think this is better than the current balance-windows function?

The current balance-windows balances locally, so there may be big
differences in window size when the split tree is deep.

Ehud and I are proposing an algorithm to balance windows globally.

It's not better, it's a matter of user taste.  

The only point for emacs developers though is that some internals are
not available to the emacs lisp programmer (this is the only bad thing
IMHO), and thus such algorithms are harder to implement by users...


> (I would rather we focus attention on the steps needed to make a
> release.)

Of course, we're not discussing this in gnus.emacs.devel, let's emacs
developers work on the important things.  
We users are not in a hurry either.

-- 
"What is this talk of "release"?  Klingons do not make software
"releases".  Our software "escapes" leaving a bloody trail of
designers and quality assurance people in its wake."

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
  2005-08-07 18:23                 ` Pascal Bourguignon
@ 2005-08-07 18:59                   ` Lennart Borgman
       [not found]                   ` <mailman.2899.1123441421.20277.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 31+ messages in thread
From: Lennart Borgman @ 2005-08-07 18:59 UTC (permalink / raw)
  Cc: help-gnu-emacs

Pascal Bourguignon wrote:

>>>File: elisp,  Node: Window Internals
>>>
>>>      
>>>
>>Thanks, I did not know this was available. Then the windows in each
>>frame can be seen as a tree using those fields you mentioned. But what
>>should then be done with this? What should the mapping between this
>>tree and the visual view be? It looks to me that the level in the tree
>>alone will not give any useful hint. The topology (ie whether the
>>splitting was horizontal or vertical) must be taken into account, but
>>maybe the level in the tree can be used too? It actually looks a bit
>>difficult...
>>    
>>
>
>Well, it's only available to the C programmer...
>  
>
I noticed when I tried to implement the algorithm I suggested. However 
it should be possible to find the split tree with a bit of work. It may 
fail when window borders meat each like a + so to say, but maybe trying 
to change the window sizes can resolve such cases. So I was wrong I 
think. It is not absolutely necessary to have the access to those hchild 
etc.

I guess you are counting the children in each sub tree (something 
similar to what I suggested though you may not have read that)? Maybe it 
should be good with some weights for a user to customize?

Finding the split tree is a bit tricky to say the least. You have to 
imagine a split tree and start to pick up the windows from the leafs and 
work upwards. Maybe thinking in sets helps? There are certain cases 
where you can not know how the split tree actually was (like three 
windows above each other), but from a user perspective those are perhaps 
better handled as a node with three childs whether that is the case in 
the internal split tree or not. (Perhaps this shows that it is better 
not to use the internal split tree?)

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
       [not found]                   ` <mailman.2899.1123441421.20277.help-gnu-emacs@gnu.org>
@ 2005-08-07 20:42                     ` Pascal Bourguignon
  0 siblings, 0 replies; 31+ messages in thread
From: Pascal Bourguignon @ 2005-08-07 20:42 UTC (permalink / raw)


Lennart Borgman <lennart.borgman.073@student.lu.se> writes:

> Pascal Bourguignon wrote:
>
>>>>File: elisp,  Node: Window Internals
>>>>
>>>>      
>>>>
>>>Thanks, I did not know this was available. Then the windows in each
>>>frame can be seen as a tree using those fields you mentioned. But what
>>>should then be done with this? What should the mapping between this
>>>tree and the visual view be? It looks to me that the level in the tree
>>>alone will not give any useful hint. The topology (ie whether the
>>>splitting was horizontal or vertical) must be taken into account, but
>>>maybe the level in the tree can be used too? It actually looks a bit
>>>difficult...
>>>    
>>>
>>
>>Well, it's only available to the C programmer...
>>  
>>
> I noticed when I tried to implement the algorithm I suggested. However
> it should be possible to find the split tree with a bit of work. It
> may fail when window borders meat each like a + so to say, but maybe
> trying to change the window sizes can resolve such cases. So I was
> wrong I think. It is not absolutely necessary to have the access to
> those hchild etc.
>
> I guess you are counting the children in each sub tree (something
> similar to what I suggested though you may not have read that)? Maybe
> it should be good with some weights for a user to customize?
>
> Finding the split tree is a bit tricky to say the least. You have to
> imagine a split tree and start to pick up the windows from the leafs
> and work upwards. Maybe thinking in sets helps? There are certain
> cases where you can not know how the split tree actually was (like
> three windows above each other), but from a user perspective those are
> perhaps better handled as a node with three childs whether that is the
> case in the internal split tree or not. (Perhaps this shows that it is
> better not to use the internal split tree?)



Indeed, the + case can be distinguished enlarging one window,
                            |
getting either __|--  or -+-+-, or still +, and checking for 
                          |
changes in the other windows.

So it's possible to recover the split tree from the window list.


-- 
"You cannot really appreciate Dilbert unless you read it in the
original Klingon"

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows (Was Re: Making the width of three windows equal)
  2005-08-07 17:15         ` New balance-windows (Was Re: Making the width of three windows equal) Richard M. Stallman
@ 2005-08-08  9:27           ` Ehud Karni
  2005-08-09  0:27             ` Richard M. Stallman
                               ` (2 more replies)
       [not found]           ` <mailman.2979.1123493766.20277.help-gnu-emacs@gnu.org>
  1 sibling, 3 replies; 31+ messages in thread
From: Ehud Karni @ 2005-08-08  9:27 UTC (permalink / raw)
  Cc: knipknap, help-gnu-emacs, emacs-devel

On Sun, 07 Aug 2005 13:15:35 -0400, Richard M. Stallman <rms@gnu.org> wrote:
>
> Why do you think this is better than the current balance-windows function?

Two reasons: 1. because it fails in a complex windows arrangement.
  2. I added balancing horizontally option (by prefix argument).

Here are some examples of balancing complex windows configuration
(the number in each window is the of lines in the window):

    After `balance-windows'           After my new function
    +-------+-------+-------+        +-------+-------+-------+
    |  9    |       |       |        |       |       |       |
    |       |       |  19   |        |  15   |       |  20   |
    +-------+       |       |        |       |       |       |
    |       |  29   |       |        +-------+  30   |       |
    |  19   |       +-------+        |       |       +-------+
    |       |       |       |        |  15   |       |       |
    |       |       |       |        |       |       |       |
    +----+--+-------+  19   |        +----+--+-------+  20   |
    |    |  |       |       |        |    |  |       |       |
    | 19 |  |       |       |        | 14 |  |       |       |
    |    |  |       +-------+        |    |  |       +-------+
    |    |  |  32   |       |        +----+--+  31   |       |
    +----+--+       |       |        |       |       |       |
    |       |       |  22   |        | 15    |       |  20   |
    | 12    |       |       |        |       |       |       |
    |       |       |       |        |       |       |       |
    +-------+-------+-------+        +-------+-------+-------+

In the above case mine is better.


    After `balance-windows'           After my new function
    +-----------+-----------+        +----------+------------+
    |           |   10      |        |          |     6      |
    |           |           |        |          +------------+
    |           +-----------+        |    19    |     6      |
    |   32      |   10      |        |          +------------+
    |           |           |        |          |     5      |
    |           +-----------+        +------+---+---+--------|
    |           |   10      |        |      |       |        |
    |           |           |        |  18  |       |  18    |
    +------+----+---+-------+        |      |       |        |
    |  10  |        |  10   |        |      |       |        |
    |      |        |       |        +------+-------+--------|
    +------+--------+-------+        |                       |
    |                       |        |         17            |
    |          12           |        |                       |
    |                       |        |                       |
    +-----------------------+        +-----------------------+

In this case the 22.0.50 balance-windows is better.


If 2 more splits are done, both functions fails:

    After `balance-windows'           After my new function
    +-----------+-----------+        +-----------+-----------+
    |           |    8      |        |           |   10      |
    |   17      |           |        |   14      |           |
    |           +-----------+        |           +-----------+
    |           |           |        +-----------+   10      |
    +-----------+           |        |           |           |
    |           |   17      |        |           +-----+-----+
    |   14      |           |        |   17      |     |     |
    |           +-----+-----+        |           | 10  | 10  |
    |           |  4  | 4   |        |           |     |     |
--> +------+----+---+-+-----+  -V-   +------+----+---+-+-----+ <---
    |   8  |        |  8    |        |      |        |       |
    |      |        |       |        |  12  |  12    |  12   |
    +------+--------+-------+        |      |        |       |
    |                       |        +------+--------+-------+
    |          14           |        |          10           |
    |                       |        |                       |
    +-----------------------+        +-----------------------+

The reason to the failure is that in this configuration the
vertical border (-V-) , although full length border, can NOT
be moved by resizing of any window.

I have looked into `enlarge-window' and I it is too complex for
me to fix it.

So, I'll work on my function some more. My proposed logic (for
vertical balancing) is to group the windows according to the
right edge AND the left edge (every window will be in 2 groups)
sort the groups by number of windows in each group, compute the
new size for this group and resize the windows in this group.
Now, repeat the whole process but ignore all the windows that
have already been resized. This approach is using ONLY the
geometry of the windows configuration. It sure will fail when
there is an unmovable edge.

Ehud.


--
 Ehud Karni           Tel: +972-3-7966-561  /"\
 Mivtach - Simon      Fax: +972-3-7966-667  \ /  ASCII Ribbon Campaign
 Insurance agencies   (USA) voice mail and   X   Against   HTML   Mail
 http://www.mvs.co.il  FAX:  1-815-5509341  / \
 GnuPG: 98EA398D <http://www.keyserver.net/>    Better Safe Than Sorry

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
  2005-08-07  2:17           ` Lennart Borgman
@ 2005-08-08  9:36             ` Ehud Karni
  2005-08-08  9:47               ` Lennart Borgman
       [not found]             ` <mailman.2988.1123495783.20277.help-gnu-emacs@gnu.org>
  1 sibling, 1 reply; 31+ messages in thread
From: Ehud Karni @ 2005-08-08  9:36 UTC (permalink / raw)
  Cc: help-gnu-emacs, emacs-devel

On Sun, 07 Aug 2005 04:17:21 +0200, Lennart Borgman <lennart.borgman.073@student.lu.se> wrote:
>
> Pascal Bourguignon wrote:
>
> >...
> >I think a correct algorithm should recover the split tree, then make
> >the balancing depending on the window counts in subtrees.
> >
> >
> I think Pascal is right. Though I think Ehud has made a very nice try I
> believe the split tree must be used. There is not enough information to
> solve the problem otherwise.

I think that balancing the windows should be done based on geometry
ONLY. What do I care how this geometry was reached ?

The split tree may cause technical difficulties to the redisplay
engine, but it should be solved there.

The problem is with `enlarge-window' that can not move some edges,
otherwise there is pure geometry algorithm to resize the windows (see
my other reply).

Ehud.


--
 Ehud Karni           Tel: +972-3-7966-561  /"\
 Mivtach - Simon      Fax: +972-3-7966-667  \ /  ASCII Ribbon Campaign
 Insurance agencies   (USA) voice mail and   X   Against   HTML   Mail
 http://www.mvs.co.il  FAX:  1-815-5509341  / \
 GnuPG: 98EA398D <http://www.keyserver.net/>    Better Safe Than Sorry

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
  2005-08-08  9:36             ` Ehud Karni
@ 2005-08-08  9:47               ` Lennart Borgman
  0 siblings, 0 replies; 31+ messages in thread
From: Lennart Borgman @ 2005-08-08  9:47 UTC (permalink / raw)
  Cc: help-gnu-emacs

Ehud Karni wrote:

>>I think Pascal is right. Though I think Ehud has made a very nice try I
>>believe the split tree must be used. There is not enough information to
>>solve the problem otherwise.
>>    
>>
>
>I think that balancing the windows should be done based on geometry
>ONLY. What do I care how this geometry was reached ?
>
>The split tree may cause technical difficulties to the redisplay
>engine, but it should be solved there.
>  
>
You are right, I am overstating the split tree. Any way it is not 
available now from elisp code.

However I think the problem ought to be solved as if we are looking at a 
tree that could be thought of as a split tree. That tree can be 
constructed from the geometry only - except for certain cases where you 
need to know the actual split tree, but in this cases you can try and 
test. (The cases where the windows meat like a + sign, maybe there are 
more but I can't see any other at the moment.) In this constructed tree 
a node can have any number of childs.

Solving it that way should lead to symmetrical solutions I believe.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
       [not found]             ` <mailman.2988.1123495783.20277.help-gnu-emacs@gnu.org>
@ 2005-08-08 10:18               ` David Kastrup
  2005-08-08 11:18                 ` Ehud Karni
       [not found]                 ` <mailman.3002.1123500982.20277.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 31+ messages in thread
From: David Kastrup @ 2005-08-08 10:18 UTC (permalink / raw)


"Ehud Karni" <ehud@unix.mvs.co.il> writes:

> On Sun, 07 Aug 2005 04:17:21 +0200, Lennart Borgman <lennart.borgman.073@student.lu.se> wrote:
>>
>> Pascal Bourguignon wrote:
>>
>> >...
>> >I think a correct algorithm should recover the split tree, then make
>> >the balancing depending on the window counts in subtrees.
>> >
>> >
>> I think Pascal is right. Though I think Ehud has made a very nice try I
>> believe the split tree must be used. There is not enough information to
>> solve the problem otherwise.
>
> I think that balancing the windows should be done based on geometry
> ONLY. What do I care how this geometry was reached ?
>
> The split tree may cause technical difficulties to the redisplay
> engine, but it should be solved there.
>
> The problem is with `enlarge-window' that can not move some edges,
> otherwise there is pure geometry algorithm to resize the windows (see
> my other reply).


Well, I can arrive at

-------------------------
|           |X          |
|           |           |
|           |           |
-------------------------
|           |           |
|           |           |
|           |           |
-------------------------

with enlarge-window from either

-------------------------
|           |X          |
|           |           |
|           |-----------|
------------|           |
|           |           |
|           |           |
|           |           |
-------------------------

or

-------------------------
|            |X         |
|            |          |
|            |          |
-------------------------
|           |           |
|           |           |
|           |           |
-------------------------

If I now do another enlarge-window, I would be surprised if the
direction of enlargement would suddenly change.

So the proper direction of enlargement _can't_ be determined without
looking at the underlying tree.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
  2005-08-08 10:18               ` David Kastrup
@ 2005-08-08 11:18                 ` Ehud Karni
  2005-08-08 12:05                   ` Lennart Borgman
       [not found]                 ` <mailman.3002.1123500982.20277.help-gnu-emacs@gnu.org>
  1 sibling, 1 reply; 31+ messages in thread
From: Ehud Karni @ 2005-08-08 11:18 UTC (permalink / raw)
  Cc: help-gnu-emacs, emacs-devel

On Mon, 08 Aug 2005 12:18:53 +0200, David Kastrup <dak@gnu.org> wrote:
>
> "Ehud Karni" <ehud@unix.mvs.co.il> writes:
>
> >
> > I think that balancing the windows should be done based on geometry
> > ONLY. What do I care how this geometry was reached ?
> >
> > The split tree may cause technical difficulties to the redisplay
> > engine, but it should be solved there.
> >
> > The problem is with `enlarge-window' that can not move some edges,
> > otherwise there is pure geometry algorithm to resize the windows (see
> > my other reply).
>
>
> Well, I can arrive at
>
> -------------------------
> |           |X          |
> |           |           |
> |           |           | configuration
> -------------------------      0
> |           |           |
> |           |           |
> |           |           |
> -------------------------
>
> with enlarge-window from either
>
> -------------------------
> |           |X          |
> |           |           |
> |           |-----------| configuration
> ------------|           |     1
> |           |           |
> |           |           |
> |           |           |
> -------------------------
>
> or
>
> -------------------------
> |            |X         |
> |            |          | configuration
> |            |          |      2
> -------------------------
> |           |           |
> |           |           |
> |           |           |
> -------------------------
>
> If I now do another enlarge-window, I would be surprised if the
> direction of enlargement would suddenly change.

The direction of enlargement (vertical or horizontal) is given by
the user, how could that be changed by the split tree.

As I said this is only a technical difficulty. I know Emacs behave
this way, but this is because of the design of Emacs.

I expect that when we have configuration 0 (even if we got there going
through configuration 2 and not from 1), and we do enlarge-window
(on window with X) we'll get:

 -------------------------
 |           |X          |
 |           |           |
 |           |           | expectation
 ------------|           |
 |           |-----------|
 |           |           |
 |           |           |
 -------------------------

And the way Emacs works is to move the whole border like this:

 -------------------------
 |           |X          |
 |           |           |
 |           |           | current behavior
 |           |           |
 ------------------------|
 |           |           |
 |           |           |
 -------------------------

Ehud.


--
 Ehud Karni           Tel: +972-3-7966-561  /"\
 Mivtach - Simon      Fax: +972-3-7966-667  \ /  ASCII Ribbon Campaign
 Insurance agencies   (USA) voice mail and   X   Against   HTML   Mail
 http://www.mvs.co.il  FAX:  1-815-5509341  / \
 GnuPG: 98EA398D <http://www.keyserver.net/>    Better Safe Than Sorry

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
  2005-08-08 11:18                 ` Ehud Karni
@ 2005-08-08 12:05                   ` Lennart Borgman
  0 siblings, 0 replies; 31+ messages in thread
From: Lennart Borgman @ 2005-08-08 12:05 UTC (permalink / raw)
  Cc: help-gnu-emacs, dak

Ehud Karni wrote:

>The direction of enlargement (vertical or horizontal) is given by
>the user, how could that be changed by the split tree.
>
>...
> -------------------------
> |           |X          |
> |           |           |
> |           |           | expectation
> ------------|           |
> |           |-----------|
> |           |           |
> |           |           |
> -------------------------
>
>And the way Emacs works is to move the whole border like this:
>
> -------------------------
> |           |X          |
> |           |           |
> |           |           | current behavior
> |           |           |
> ------------------------|
> |           |           |
> |           |           |
> -------------------------
>  
>
I guess what you see here is the how the split was done. This mean that 
you can this way trace the split tree.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
       [not found]           ` <mailman.2979.1123493766.20277.help-gnu-emacs@gnu.org>
@ 2005-08-08 17:55             ` Pascal Bourguignon
  0 siblings, 0 replies; 31+ messages in thread
From: Pascal Bourguignon @ 2005-08-08 17:55 UTC (permalink / raw)


"Ehud Karni" <ehud@unix.mvs.co.il> writes:
> If 2 more splits are done, both functions fails:
>
>     After `balance-windows'           After my new function
>     +-----------+-----------+        +-----------+-----------+
>     |           |    8      |        |           |   10      |
>     |   17      |           |        |   14      |           |
>     |           +-----------+        |           +-----------+
>     |           |           |        +-----------+   10      |
>     +-----------+           |        |           |           |
>     |           |   17      |        |           +-----+-----+
>     |   14      |           |        |   17      |     |     |
>     |           +-----+-----+        |           | 10  | 10  |
>     |  [*]      |  4  | 4   |        |           |     |     |
> --> +------+----+---+-+-----+  -V-   +------+----+---+-+-----+ <---
>     |   8  |        |  8    |        |      |        |       |
>     |      |        |       |        |  12  |  12    |  12   |
>     +------+--------+-------+        |      |        |       |
>     |                       |        +------+--------+-------+
>     |          14           |        |          10           |
>     |                       |        |                       |
>     +-----------------------+        +-----------------------+
>
> The reason to the failure is that in this configuration the
> vertical border (-V-) , although full length border, can NOT
> be moved by resizing of any window.
>
> I have looked into `enlarge-window' and I it is too complex for
> me to fix it.
> [...] It sure will fail when there is an unmovable edge.

One solution would be to rebuild a new window tree.


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
-----BEGIN GEEK CODE BLOCK-----
Version: 3.12
GCS d? s++:++ a+ C+++ UL++++ P--- L+++ E+++ W++ N+++ o-- K- w--- 
O- M++ V PS PE++ Y++ PGP t+ 5+ X++ R !tv b+++ DI++++ D++ 
G e+++ h+ r-- z? 
------END GEEK CODE BLOCK------

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
       [not found]                 ` <mailman.3002.1123500982.20277.help-gnu-emacs@gnu.org>
@ 2005-08-08 18:11                   ` Pascal Bourguignon
  0 siblings, 0 replies; 31+ messages in thread
From: Pascal Bourguignon @ 2005-08-08 18:11 UTC (permalink / raw)


"Ehud Karni" <ehud@unix.mvs.co.il> writes:
>> Well, I can arrive at
>>
>> -------------------------
>> |           |X          |
>> |           |           |
>> |           |           | configuration
>> -------------------------      0
>> |           |           |
>> |           |           |
>> |           |           |
>> -------------------------
>>
>> with enlarge-window from either
>>
>> -------------------------
>> |           |X          |
>> |           |           |
>> |           |-----------| configuration
>> ------------|           |     1
>> |           |           |
>> |           |           |
>> |           |           |
>> -------------------------
>>
>> or
>>
>> -------------------------
>> |            |X         |
>> |            |          | configuration
>> |            |          |      2
>> -------------------------
>> |           |           |
>> |           |           |
>> |           |           |
>> -------------------------
>>
>> If I now do another enlarge-window, I would be surprised if the
>> direction of enlargement would suddenly change.
>
> The direction of enlargement (vertical or horizontal) is given by
> the user, how could that be changed by the split tree.

Look at the problem from the other side!  

Why the user could not start from configuration 1 above, enlarge
window X to reach configuration 0, and then enlarge window X in the
other direction to reach configuration 1?

The only reason it's not possible is because emacs cast it in C
firmware, instead of leaving it up to user emacs lisp code.

If the split tree was available, one could easily swap some split
nodes without changing the window leaves, to change the direction and
enable that.

For example in this configuration:

+---+---+
| 1 | 3 |
+---+---+
| 2 | 4 |
+---+---+

we would have a split tree such as: (H (V 1 2) (V 3 4)) 
if the user clicked on 1|3 separation to move it horizontally, we
could change the split tree to: (V (H 1 3) (H 2 4))

+----+--+
| 1  |3 |
+---++--+
| 2 | 4 |
+---+---+



On the other hand, perhaps we need to add something to this split tree
idea, to alloww the emacs user interface easily let the use move the +
in the middle in any direction, to let the user go from configuration
0 to this in one click-and-drag:

+-+-----+
|1|  3  |
+-+-----+
| |     |
|2|  4  |
| |     |
+-+-----+

in addition to allowing indiscriminate horizontal or vertical window
resizing.


> As I said this is only a technical difficulty. I know Emacs behave
> this way, but this is because of the design of Emacs.
>
> I expect that when we have configuration 0 (even if we got there going
> through configuration 2 and not from 1), and we do enlarge-window
> (on window with X) we'll get:
>
>  -------------------------
>  |           |X          |
>  |           |           |
>  |           |           | expectation
>  ------------|           |
>  |           |-----------|
>  |           |           |
>  |           |           |
>  -------------------------
>
> And the way Emacs works is to move the whole border like this:
>
>  -------------------------
>  |           |X          |
>  |           |           |
>  |           |           | current behavior
>  |           |           |
>  ------------------------|
>  |           |           |
>  |           |           |
>  -------------------------


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
-----BEGIN GEEK CODE BLOCK-----
Version: 3.12
GCS d? s++:++ a+ C+++ UL++++ P--- L+++ E+++ W++ N+++ o-- K- w--- 
O- M++ V PS PE++ Y++ PGP t+ 5+ X++ R !tv b+++ DI++++ D++ 
G e+++ h+ r-- z? 
------END GEEK CODE BLOCK------

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows (Was Re: Making the width of three windows equal)
  2005-08-08  9:27           ` Ehud Karni
@ 2005-08-09  0:27             ` Richard M. Stallman
  2005-08-10  0:05             ` New balance-windows Stefan Monnier
       [not found]             ` <mailman.3158.1123633927.20277.help-gnu-emacs@gnu.org>
  2 siblings, 0 replies; 31+ messages in thread
From: Richard M. Stallman @ 2005-08-09  0:27 UTC (permalink / raw)
  Cc: knipknap, help-gnu-emacs, emacs-devel

    If 2 more splits are done, both functions fails:

    The reason to the failure is that in this configuration the
    vertical border (-V-) , although full length border, can NOT
    be moved by resizing of any window.

Why can't it?

Did you try passing t for the second argument of enlarge-window,
after calling it on one of the windows above the line to be moved?

Anyway, we recently discussed the idea of a way to represent
window configurations as transparent Lisp data, and I suggested
a way that this could be implemented safely.  That would eliminate
a lot of these problems, because you could compute the desired
arrangement as a window configuration and then install it.

All of this is for after the current release.  If you want to work on
it on the side noiw, by all means do.  However, I'd like to ask other
people to join in work needed for the release, rather than this.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
  2005-08-08  9:27           ` Ehud Karni
  2005-08-09  0:27             ` Richard M. Stallman
@ 2005-08-10  0:05             ` Stefan Monnier
  2005-08-10  1:48               ` Stefan Monnier
       [not found]             ` <mailman.3158.1123633927.20277.help-gnu-emacs@gnu.org>
  2 siblings, 1 reply; 31+ messages in thread
From: Stefan Monnier @ 2005-08-10  0:05 UTC (permalink / raw)
  Cc: knipknap, help-gnu-emacs, rms, emacs-devel

>     After `balance-windows'           After my new function
>     +-------+-------+-------+        +-------+-------+-------+
>     |  9    |       |       |        |       |       |       |
>     |       |       |  19   |        |  15   |       |  20   |
>     +-------+       |       |        |       |       |       |
>     |       |  29   |       |        +-------+  30   |       |
>     |  19   |       +-------+        |       |       +-------+
>     |       |       |       |        |  15   |       |       |
>     |       |       |       |        |       |       |       |
>     +----+--+-------+  19   |        +----+--+-------+  20   |
>     |    |  |       |       |        |    |  |       |       |
>     | 19 |  |       |       |        | 14 |  |       |       |
>     |    |  |       +-------+        |    |  |       +-------+
>     |    |  |  32   |       |        +----+--+  31   |       |
>     +----+--+       |       |        |       |       |       |
>     |       |       |  22   |        | 15    |       |  20   |
>     | 12    |       |       |        |       |       |       |
>     |       |       |       |        |       |       |       |
>     +-------+-------+-------+        +-------+-------+-------+

For what it's worth, here is another alternative I wrote a few years ago.
Note how it iterates to try and get to a fix point without using the
`preserve-before' argument (which didn't exist at that point).


        Stefan


(defun balance-windows-area ()
  "Make all visible windows use the same area (approximately)."
  (interactive)
  (save-selected-window
    (let* ((change t)
	   (resizecount 0)
	   (wins (window-list nil 'nomini))
	   (count (length wins))
	   minresize next (carry 0))
      ;; Resizing a window changes the size of surrounding windows
      ;; in complex ways, so it's difficult to set the sizes in a single pass.
      ;; Instead, we just go through all the windows several times
      ;; until nothing needs to be CHANGEd.
      (while (and change (> count 1))
	(setq change nil count (1- count))
	(dolist (win wins)
	  ;; We always have to check liveness because enlarging/shrinking
	  ;; always risks deleting windows (although we are very careful
	  ;; to avoid most such cases).
	  (when (and (window-live-p win) (not (window-fixed-size-p win)))
	    (select-window win)
	    (setq next nil)
	    (while (progn (setq next (next-window next))
			  (window-fixed-size-p next)))
	    (let ((diff (- (* (window-height) (window-width))
			   (* (window-height next) (window-width next)))))
	      (if (< (car (window-edges)) (car (window-edges next)))
		  ;; The windows are side-by-side
		  (unless (zerop (setq diff (/ diff (window-height) 2)))
		    ;; Change things more smoothly.
		    (if (or (> diff 1) (< diff -1)) (setq diff (/ diff 2)))
		    (shrink-window diff)
		    (setq change t))
		(setq diff (/ diff (window-width) 2))
		;; Change things more smoothly.
		(if (or (> diff 1) (< diff -1)) (setq diff (/ diff 2)))
		(cond
		 ((= diff 0))
		 ;; Try to shrink to balance out with a smaller next window.
		 ;; Enlarging risks killing a window, but if the next-window
		 ;; is adjacent, then it should be safe.
		 ((or (and (> diff 0) (window-safely-shrinkable-p))
		      (and (< diff 0)
			   (= (car (window-edges))
			      (car (window-edges next)))
			   (not (eq next (frame-first-window)))))
		  (shrink-window diff)
		  (setq change t))
		 ;; Resizing is also safe if all windows are big enough.
		 ((> (setq minresize
			   (- (apply 'min (mapcar 'window-height wins))
			      window-min-height))
		     0)
		  (shrink-window
		   (if (> diff 0)
		       (min diff minresize) (max diff (- minresize))))
		  (setq change t))
		 ;; Let's try yet something else
		 ((and (< diff 0) (window-safely-shrinkable-p next))
		  (select-window next)
		  (shrink-window (- diff))
		  (setq change t)))))))))))

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
  2005-08-10  0:05             ` New balance-windows Stefan Monnier
@ 2005-08-10  1:48               ` Stefan Monnier
  0 siblings, 0 replies; 31+ messages in thread
From: Stefan Monnier @ 2005-08-10  1:48 UTC (permalink / raw)
  Cc: knipknap, help-gnu-emacs, rms, emacs-devel

> 	      (if (< (car (window-edges)) (car (window-edges next)))
> 		  ;; The windows are side-by-side
> 		  (unless (zerop (setq diff (/ diff (window-height) 2)))
> 		    ;; Change things more smoothly.
> 		    (if (or (> diff 1) (< diff -1)) (setq diff (/ diff 2)))
> 		    (shrink-window diff)
                                      ^^
                                       t

[ I mistakenly removed this second arg before posting my code, thinking I was
  using a local extension of shrink-window, but I later noticed that it was
  not the case (I dropped this local extension when it collided with
  preserve-before). ]


        Stefan

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: New balance-windows
       [not found]             ` <mailman.3158.1123633927.20277.help-gnu-emacs@gnu.org>
@ 2005-08-21  0:33               ` David Combs
  0 siblings, 0 replies; 31+ messages in thread
From: David Combs @ 2005-08-21  0:33 UTC (permalink / raw)


I did grab the entire thread, but not being an elisp-hacker,
not at all, please say:

. Of all those various solutions/attemps/whatever,
  what seems like the "best" one?

. More importantly, I guess, are any (of those that work)
  able to be simply "loaded" into a running emacs, eg cvs,
  and thus actually provide the balance-the-columns-evenly
  facility?

  Better yet, if so, has anyone actually done it?

Thanks,

David

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2005-08-21  0:33 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-08-03  0:47 Making the width of three windows equal Samuel
2005-08-03  1:01 ` Pascal Bourguignon
2005-08-03  2:13   ` Samuel
2005-08-03  3:11     ` Pascal Bourguignon
2005-08-06 11:59       ` New balance-windows (Was Re: Making the width of three windows equal) Ehud Karni
2005-08-06 13:27         ` New balance-windows Ehud Karni
     [not found]         ` <mailman.2758.1123335041.20277.help-gnu-emacs@gnu.org>
2005-08-06 16:42           ` Pascal Bourguignon
2005-08-07 17:15         ` New balance-windows (Was Re: Making the width of three windows equal) Richard M. Stallman
2005-08-08  9:27           ` Ehud Karni
2005-08-09  0:27             ` Richard M. Stallman
2005-08-10  0:05             ` New balance-windows Stefan Monnier
2005-08-10  1:48               ` Stefan Monnier
     [not found]             ` <mailman.3158.1123633927.20277.help-gnu-emacs@gnu.org>
2005-08-21  0:33               ` David Combs
     [not found]           ` <mailman.2979.1123493766.20277.help-gnu-emacs@gnu.org>
2005-08-08 17:55             ` Pascal Bourguignon
     [not found]         ` <mailman.2888.1123436059.20277.help-gnu-emacs@gnu.org>
2005-08-07 18:31           ` Pascal Bourguignon
     [not found]       ` <mailman.2754.1123329756.20277.help-gnu-emacs@gnu.org>
2005-08-06 16:39         ` Pascal Bourguignon
2005-08-06 16:58           ` Lennart Borgman
     [not found]           ` <mailman.2773.1123347813.20277.help-gnu-emacs@gnu.org>
2005-08-06 20:45             ` Pascal Bourguignon
2005-08-06 21:14               ` Lennart Borgman
     [not found]               ` <mailman.2796.1123363907.20277.help-gnu-emacs@gnu.org>
2005-08-07 18:23                 ` Pascal Bourguignon
2005-08-07 18:59                   ` Lennart Borgman
     [not found]                   ` <mailman.2899.1123441421.20277.help-gnu-emacs@gnu.org>
2005-08-07 20:42                     ` Pascal Bourguignon
2005-08-06 21:05           ` Ehud Karni
2005-08-06 23:22             ` Lennart Borgman
2005-08-07  2:17           ` Lennart Borgman
2005-08-08  9:36             ` Ehud Karni
2005-08-08  9:47               ` Lennart Borgman
     [not found]             ` <mailman.2988.1123495783.20277.help-gnu-emacs@gnu.org>
2005-08-08 10:18               ` David Kastrup
2005-08-08 11:18                 ` Ehud Karni
2005-08-08 12:05                   ` Lennart Borgman
     [not found]                 ` <mailman.3002.1123500982.20277.help-gnu-emacs@gnu.org>
2005-08-08 18:11                   ` Pascal Bourguignon

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.