]> granicus.if.org Git - vim/commitdiff
updated for version 7.0228
authorBram Moolenaar <Bram@vim.org>
Sat, 18 Mar 2006 21:30:13 +0000 (21:30 +0000)
committerBram Moolenaar <Bram@vim.org>
Sat, 18 Mar 2006 21:30:13 +0000 (21:30 +0000)
runtime/optwin.vim
src/getchar.c
src/if_ruby.c
src/window.c

index 7cb9050322702815bd02e748c471d844d5ca2958..78df1defe182e2974706783811598fdfb88b65a3 100644 (file)
@@ -1,7 +1,7 @@
 " These commands create the option window.
 "
 " Maintainer:  Bram Moolenaar <Bram@vim.org>
-" Last Change: 2006 Mar 16
+" Last Change: 2006 Mar 18
 
 " If there already is an option window, jump to that one.
 if bufwinnr("option-window") > 0
@@ -435,6 +435,9 @@ call append("$", "winfixheight\tkeep the height of the window")
 call append("$", "\t(local to window)")
 call <SID>BinOptionL("wfh")
 if has("vertsplit")
+call append("$", "winfixwidth\tkeep the width of the window")
+call append("$", "\t(local to window)")
+call <SID>BinOptionL("wfw")
   call append("$", "winwidth\tminimal number of columns used for the current window")
   call append("$", " \tset wiw=" . &wiw)
   call append("$", "winminwidth\tminimal number of columns used for any window")
index 5aa1b2594dd315b9910ca1eb18c65519acc0f66c..9810ed4b900008f8479774020e6b63c80112e59b 100644 (file)
@@ -3273,7 +3273,7 @@ do_map(maptype, arg, mode, abbrev)
        {
            if (abbrev)
            {
-               if (hash != 0)  /* there is only one abbreviation list */
+               if (hash > 0)   /* there is only one abbreviation list */
                    break;
                mpp = abbr_table;
            }
@@ -3595,7 +3595,7 @@ map_clear_int(buf, mode, local, abbr)
     {
        if (abbr)
        {
-           if (hash)       /* there is only one abbrlist */
+           if (hash > 0)       /* there is only one abbrlist */
                break;
 #ifdef FEAT_LOCALMAP
            if (local)
@@ -3734,9 +3734,10 @@ showmap(mp, local)
  * Also checks mappings local to the current buffer.
  */
     int
-map_to_exists(str, modechars)
+map_to_exists(str, modechars, abbr)
     char_u     *str;
     char_u     *modechars;
+    int                abbr;
 {
     int                mode = 0;
     char_u     *rhs;
@@ -3758,7 +3759,7 @@ map_to_exists(str, modechars)
     if (vim_strchr(modechars, 'c') != NULL)
        mode |= CMDLINE;
 
-    retval = map_to_exists_mode(rhs, mode);
+    retval = map_to_exists_mode(rhs, mode, abbr);
     vim_free(buf);
 
     return retval;
@@ -3770,9 +3771,10 @@ map_to_exists(str, modechars)
  * Also checks mappings local to the current buffer.
  */
     int
-map_to_exists_mode(rhs, mode)
+map_to_exists_mode(rhs, mode, abbr)
     char_u     *rhs;
     int                mode;
+    int                abbr;
 {
     mapblock_T *mp;
     int                hash;
@@ -3787,11 +3789,22 @@ map_to_exists_mode(rhs, mode)
 # endif
        for (hash = 0; hash < 256; ++hash)
        {
+           if (abbr)
+           {
+               if (hash > 0)           /* there is only one abbr list */
+                   break;
+#ifdef FEAT_LOCALMAP
+               if (expand_buffer)
+                   mp = curbuf->b_first_abbr;
+               else
+#endif
+                   mp = first_abbr;
+           }
 # ifdef FEAT_LOCALMAP
-           if (expand_buffer)
+           else if (expand_buffer)
                mp = curbuf->b_maphash[hash];
-           else
 # endif
+           else
                mp = maphash[hash];
            for (; mp; mp = mp->m_next)
            {
@@ -3954,7 +3967,7 @@ ExpandMappings(regmatch, num_file, file)
        {
            if (expand_isabbrev)
            {
-               if (hash)       /* only one abbrev list */
+               if (hash > 0)   /* only one abbrev list */
                    break; /* for (hash) */
                mp = first_abbr;
            }
@@ -4255,7 +4268,7 @@ makemap(fd, buf)
        {
            if (abbr)
            {
-               if (hash)           /* there is only one abbr list */
+               if (hash > 0)           /* there is only one abbr list */
                    break;
 #ifdef FEAT_LOCALMAP
                if (buf != NULL)
@@ -4614,11 +4627,12 @@ check_map_keycodes()
  * NULL otherwise
  */
     char_u *
-check_map(keys, mode, exact, ign_mod)
+check_map(keys, mode, exact, ign_mod, abbr)
     char_u     *keys;
     int                mode;
     int                exact;          /* require exact match */
     int                ign_mod;        /* ignore preceding modifier */
+    int                abbr;           /* do abbreviations */
 {
     int                hash;
     int                len, minlen;
@@ -4637,11 +4651,22 @@ check_map(keys, mode, exact, ign_mod)
        /* loop over all hash lists */
        for (hash = 0; hash < 256; ++hash)
        {
+           if (abbr)
+           {
+               if (hash > 0)           /* there is only one list. */
+                   break;
 #ifdef FEAT_LOCALMAP
-           if (local)
+               if (local)
+                   mp = curbuf->b_first_abbr;
+               else
+#endif
+                   mp = first_abbr;
+           }
+#ifdef FEAT_LOCALMAP
+           else if (local)
                mp = curbuf->b_maphash[hash];
-           else
 #endif
+           else
                mp = maphash[hash];
            for ( ; mp != NULL; mp = mp->m_next)
            {
index e424c5d921721b9a2c653b8e11a8ca007922712f..6bafdeb6b8be56d14b611c7e072f4beb1b69e82b 100644 (file)
@@ -1,7 +1,9 @@
 /* vi:set ts=8 sts=4 sw=4:
  *
  * VIM - Vi IMproved   by Bram Moolenaar
- * Ruby interface by Shugo Maeda.
+ *
+ * Ruby interface by Shugo Maeda
+ *   with improvements by SegPhault (Ryan Paul)
  *
  * Do ":help uganda"  in Vim to read copying and usage conditions.
  * Do ":help credits" in Vim to see a list of people who contributed.
@@ -567,7 +569,14 @@ static VALUE buffer_s_count()
     buf_T *b;
     int n = 0;
 
-    for (b = firstbuf; b; b = b->b_next) n++;
+    for (b = firstbuf; b != NULL; b = b->b_next)
+    {
+        /*  Deleted buffers should not be counted
+         *    SegPhault - 01/07/05 */
+        if (b->b_p_bl)
+           n++;
+    }
+
     return INT2NUM(n);
 }
 
@@ -576,9 +585,17 @@ static VALUE buffer_s_aref(VALUE self, VALUE num)
     buf_T *b;
     int n = NUM2INT(num);
 
-    for (b = firstbuf; b; b = b->b_next, --n) {
-       if (n == 0)
+    for (b = firstbuf; b != NULL; b = b->b_next)
+    {
+        /*  Deleted buffers should not be counted
+         *    SegPhault - 01/07/05 */
+        if (!b->b_p_bl)
+           continue;
+
+        if (n == 0)
            return buffer_new(b);
+
+        n--;
     }
     return Qnil;
 }
@@ -604,32 +621,35 @@ static VALUE buffer_count(VALUE self)
     return INT2NUM(buf->b_ml.ml_line_count);
 }
 
-static VALUE buffer_aref(VALUE self, VALUE num)
+static VALUE get_buffer_line(buf_T *buf, linenr_T n)
 {
-    buf_T *buf = get_buf(self);
-    long n = NUM2LONG(num);
-
-    if (n > 0 && n <= buf->b_ml.ml_line_count) {
+    if (n > 0 && n <= buf->b_ml.ml_line_count)
+    {
        char *line = (char *)ml_get_buf(buf, n, FALSE);
        return line ? rb_str_new2(line) : Qnil;
     }
-    else {
-       rb_raise(rb_eIndexError, "index %d out of buffer", n);
-       return Qnil; /* For stop warning */
-    }
+    rb_raise(rb_eIndexError, "index %d out of buffer", n);
+    return Qnil; /* For stop warning */
 }
 
-static VALUE buffer_aset(VALUE self, VALUE num, VALUE str)
+static VALUE buffer_aref(VALUE self, VALUE num)
 {
     buf_T *buf = get_buf(self);
+
+    if (buf != NULL)
+       return get_buffer_line(buf, (linenr_T)NUM2LONG(num));
+    return Qnil; /* For stop warning */
+}
+
+static VALUE set_buffer_line(buf_T *buf, linenr_T n, VALUE str)
+{
     buf_T *savebuf = curbuf;
     char *line = STR2CSTR(str);
-    long n = NUM2LONG(num);
 
     if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL) {
        curbuf = buf;
        if (u_savesub(n) == OK) {
-           ml_replace(n, (char_u *) line, TRUE);
+           ml_replace(n, (char_u *)line, TRUE);
            changed();
 #ifdef SYNTAX_HL
            syn_changed(n); /* recompute syntax hl. for this line */
@@ -645,6 +665,15 @@ static VALUE buffer_aset(VALUE self, VALUE num, VALUE str)
     return str;
 }
 
+static VALUE buffer_aset(VALUE self, VALUE num, VALUE str)
+{
+    buf_T *buf = get_buf(self);
+
+    if (buf != NULL)
+       return set_buffer_line(buf, (linenr_T)NUM2LONG(num), str);
+    return str;
+}
+
 static VALUE buffer_delete(VALUE self, VALUE num)
 {
     buf_T *buf = get_buf(self);
@@ -654,8 +683,12 @@ static VALUE buffer_delete(VALUE self, VALUE num)
     if (n > 0 && n <= buf->b_ml.ml_line_count) {
        curbuf = buf;
        if (u_savedel(n, 1) == OK) {
-           mark_adjust(n, n, MAXLNUM, -1);
            ml_delete(n, 0);
+
+            /* Changes to non-active buffers should properly refresh
+             *   SegPhault - 01/09/05 */
+            deleted_lines_mark(n, 1L);
+
            changed();
        }
        curbuf = savebuf;
@@ -677,9 +710,13 @@ static VALUE buffer_append(VALUE self, VALUE num, VALUE str)
     if (n >= 0 && n <= buf->b_ml.ml_line_count && line != NULL) {
        curbuf = buf;
        if (u_inssub(n + 1) == OK) {
-           mark_adjust(n + 1, MAXLNUM, 1L, 0L);
            ml_append(n, (char_u *) line, (colnr_T) 0, FALSE);
-           changed();
+
+            /*  Changes to non-active buffers should properly refresh screen
+             *    SegPhault - 12/20/04 */
+            appended_lines_mark(n, 1L);
+
+            changed();
        }
        curbuf = savebuf;
        update_curbuf(NOT_VALID);
@@ -720,6 +757,27 @@ static VALUE window_s_current()
     return window_new(curwin);
 }
 
+/*
+ * Added line manipulation functions
+ *    SegPhault - 03/07/05
+ */
+static VALUE line_s_current()
+{
+    return get_buffer_line(curbuf, curwin->w_cursor.lnum);
+}
+
+static VALUE set_current_line(VALUE str)
+{
+    return set_buffer_line(curbuf, curwin->w_cursor.lnum, str);
+}
+
+static VALUE current_line_number()
+{
+    return INT2FIX((int)curwin->w_cursor.lnum);
+}
+
+
+
 static VALUE window_s_count()
 {
 #ifdef FEAT_WINDOWS
@@ -877,6 +935,13 @@ static void ruby_vim_init(void)
     rb_define_method(cBuffer, "delete", buffer_delete, 1);
     rb_define_method(cBuffer, "append", buffer_append, 2);
 
+    /* Added line manipulation functions
+     *   SegPhault - 03/07/05 */
+    rb_define_method(cBuffer, "line_number", current_line_number, 0);
+    rb_define_method(cBuffer, "line", line_s_current, 0);
+    rb_define_method(cBuffer, "line=", set_current_line, 1);
+
+
     cVimWindow = rb_define_class_under(mVIM, "Window", rb_cObject);
     rb_define_singleton_method(cVimWindow, "current", window_s_current, 0);
     rb_define_singleton_method(cVimWindow, "count", window_s_count, 0);
index 10bb8734340d3315306d2e1ce50c2d18b985909d..c450221917792c36db8813fb0d3eca0182e90577 100644 (file)
@@ -36,8 +36,9 @@ static int frame_has_win __ARGS((frame_T *frp, win_T *wp));
 static void frame_new_height __ARGS((frame_T *topfrp, int height, int topfirst, int wfh));
 static int frame_fixed_height __ARGS((frame_T *frp));
 #ifdef FEAT_VERTSPLIT
+static int frame_fixed_width __ARGS((frame_T *frp));
 static void frame_add_statusline __ARGS((frame_T *frp));
-static void frame_new_width __ARGS((frame_T *topfrp, int width, int leftfirst));
+static void frame_new_width __ARGS((frame_T *topfrp, int width, int leftfirst, int wfw));
 static void frame_add_vsep __ARGS((frame_T *frp));
 static int frame_minwidth __ARGS((frame_T *topfrp, win_T *next_curwin));
 static void frame_fix_width __ARGS((win_T *wp));
@@ -723,6 +724,12 @@ win_split_ins(size, flags, newwin, dir)
        /* if it doesn't fit in the current window, need win_equal() */
        if (oldwin->w_width - new_size - 1 < p_wmw)
            do_equal = TRUE;
+
+       /* We don't like to take lines for the new window from a
+        * 'winfixwidth' window.  Take them from a window to the left or right
+        * instead, if possible. */
+       if (oldwin->w_p_wfw)
+           win_setwidth_win(oldwin->w_width + new_size, oldwin);
     }
     else
 #endif
@@ -937,10 +944,11 @@ win_split_ins(size, flags, newwin, dir)
                frame_add_vsep(curfrp);
            /* Set width of neighbor frame */
            frame_new_width(curfrp, curfrp->fr_width
-                   - (new_size + ((flags & WSP_TOP) != 0)), flags & WSP_TOP);
+                    - (new_size + ((flags & WSP_TOP) != 0)), flags & WSP_TOP,
+                                                                      FALSE);
        }
        else
-           oldwin->w_width -= new_size + 1;
+           win_new_width(oldwin, oldwin->w_width - (new_size + 1));
        if (before)     /* new window left of current one */
        {
            wp->w_wincol = oldwin->w_wincol;
@@ -1588,7 +1596,7 @@ win_equal_rec(next_curwin, current, topfr, dir, col, row, width, height)
            frame_new_height(topfr, height, FALSE, FALSE);
 #ifdef FEAT_VERTSPLIT
            topfr->fr_win->w_wincol = col;
-           frame_new_width(topfr, width, FALSE);
+           frame_new_width(topfr, width, FALSE, FALSE);
 #endif
            redraw_all_later(CLEAR);
        }
@@ -1610,8 +1618,13 @@ win_equal_rec(next_curwin, current, topfr, dir, col, row, width, height)
            else
                extra_sep = 0;
            totwincount = (n + extra_sep) / (p_wmw + 1);
+           has_next_curwin = frame_has_win(topfr, next_curwin);
 
-           /* Compute room available for windows other than "next_curwin" */
+           /*
+            * Compute width for "next_curwin" window and room available for
+            * other windows.
+            * "m" is the minimal width when counting p_wiw for "next_curwin".
+            */
            m = frame_minwidth(topfr, next_curwin);
            room = width - m;
            if (room < 0)
@@ -1619,18 +1632,56 @@ win_equal_rec(next_curwin, current, topfr, dir, col, row, width, height)
                next_curwin_size = p_wiw + room;
                room = 0;
            }
-           else if (n == m)            /* doesn't contain curwin */
-               next_curwin_size = 0;
            else
            {
-               next_curwin_size = (room + p_wiw + (totwincount - 1) * p_wmw
+               next_curwin_size = -1;
+               for (fr = topfr->fr_child; fr != NULL; fr = fr->fr_next)
+               {
+                   /* If 'winfixwidth' set keep the window width if
+                    * possible.
+                    * Watch out for this window being the next_curwin. */
+                   if (frame_fixed_width(fr))
+                   {
+                       n = frame_minwidth(fr, NOWIN);
+                       new_size = fr->fr_width;
+                       if (frame_has_win(fr, next_curwin))
+                       {
+                           room += p_wiw - p_wmw;
+                           next_curwin_size = 0;
+                           if (new_size < p_wiw)
+                               new_size = p_wiw;
+                       }
+                       else
+                           /* These windows don't use up room. */
+                           totwincount -= (n + (fr->fr_next == NULL
+                                             ? extra_sep : 0)) / (p_wmw + 1);
+                       room -= new_size - n;
+                       if (room < 0)
+                       {
+                           new_size += room;
+                           room = 0;
+                       }
+                       fr->fr_newwidth = new_size;
+                   }
+               }
+               if (next_curwin_size == -1)
+               {
+                   if (!has_next_curwin)
+                       next_curwin_size = 0;
+                   else if (totwincount > 1
+                           && (room + (totwincount - 2))
+                                                 / (totwincount - 1) > p_wiw)
+                   {
+                       next_curwin_size = (room + p_wiw + totwincount * p_wmw
                                           + (totwincount - 1)) / totwincount;
-               if (next_curwin_size  > p_wiw)
-                   room -= next_curwin_size - p_wiw;
-               else
-                   next_curwin_size = p_wiw;
+                       room -= next_curwin_size - p_wiw;
+                   }
+                   else
+                       next_curwin_size = p_wiw;
+               }
            }
-           if (n != m)
+
+           if (has_next_curwin)
                --totwincount;          /* don't count curwin */
        }
 
@@ -1643,6 +1694,11 @@ win_equal_rec(next_curwin, current, topfr, dir, col, row, width, height)
                new_size = width;
            else if (dir == 'v')
                new_size = fr->fr_width;
+           else if (frame_fixed_width(fr))
+           {
+               new_size = fr->fr_newwidth;
+               wincount = 0;       /* doesn't count as a sizeable window */
+           }
            else
            {
                /* Compute the maximum number of windows horiz. in "fr". */
@@ -1650,30 +1706,37 @@ win_equal_rec(next_curwin, current, topfr, dir, col, row, width, height)
                wincount = (n + (fr->fr_next == NULL ? extra_sep : 0))
                                                                / (p_wmw + 1);
                m = frame_minwidth(fr, next_curwin);
-               if (n != m)         /* don't count next_curwin */
+               if (has_next_curwin)
+                   hnc = frame_has_win(fr, next_curwin);
+               else
+                   hnc = FALSE;
+               if (hnc)            /* don't count next_curwin */
                    --wincount;
-               new_size = (wincount * room + ((unsigned)totwincount >> 1))
+               if (totwincount == 0)
+                   new_size = room;
+               else
+                   new_size = (wincount * room + ((unsigned)totwincount >> 1))
                                                                / totwincount;
-               if (n != m)         /* add next_curwin size */
+               if (hnc)            /* add next_curwin size */
                {
                    next_curwin_size -= p_wiw - (m - n);
                    new_size += next_curwin_size;
+                   room -= new_size - next_curwin_size;
                }
+               else
+                   room -= new_size;
+               new_size += n;
            }
 
-           /* Skip frame that is full height when splitting or closing a
+           /* Skip frame that is full width when splitting or closing a
             * window, unless equalizing all frames. */
            if (!current || dir != 'v' || topfr->fr_parent != NULL
                    || (new_size != fr->fr_width)
                    || frame_has_win(fr, next_curwin))
                win_equal_rec(next_curwin, current, fr, dir, col, row,
-                                                       new_size + n, height);
-           col += new_size + n;
-           width -= new_size + n;
-           if (n != m)     /* contains curwin */
-               room -= new_size - next_curwin_size;
-           else
-               room -= new_size;
+                                                           new_size, height);
+           col += new_size;
+           width -= new_size;
            totwincount -= wincount;
        }
     }
@@ -2172,7 +2235,7 @@ winframe_remove(win, dirp, tp)
     frame_T    *frp, *frp2, *frp3;
     frame_T    *frp_close = win->w_frame;
     win_T      *wp;
-    int                old_height = 0;
+    int                old_size = 0;
 
     /*
      * If there is only one window there is nothing to remove.
@@ -2199,18 +2262,27 @@ winframe_remove(win, dirp, tp)
        if (frp2->fr_win != NULL
                && (frp2->fr_next != NULL || frp2->fr_prev != NULL)
                && frp2->fr_win->w_p_wfh)
-           old_height = frp2->fr_win->w_height;
+           old_size = frp2->fr_win->w_height;
        frame_new_height(frp2, frp2->fr_height + frp_close->fr_height,
                            frp2 == frp_close->fr_next ? TRUE : FALSE, FALSE);
-       if (old_height != 0)
-           win_setheight_win(old_height, frp2->fr_win);
+       if (old_size != 0)
+           win_setheight_win(old_size, frp2->fr_win);
 #ifdef FEAT_VERTSPLIT
        *dirp = 'v';
     }
     else
     {
+       /* When 'winfixwidth' is set, remember its old size and restore
+        * it later (it's a simplistic solution...).  Don't do this if the
+        * window will occupy the full width of the screen. */
+       if (frp2->fr_win != NULL
+               && (frp2->fr_next != NULL || frp2->fr_prev != NULL)
+               && frp2->fr_win->w_p_wfw)
+           old_size = frp2->fr_win->w_width;
        frame_new_width(frp2, frp2->fr_width + frp_close->fr_width,
-                                  frp2 == frp_close->fr_next ? TRUE : FALSE);
+                           frp2 == frp_close->fr_next ? TRUE : FALSE, FALSE);
+       if (old_size != 0)
+           win_setwidth_win(old_size, frp2->fr_win);
        *dirp = 'h';
     }
 #endif
@@ -2390,7 +2462,7 @@ frame_new_height(topfrp, height, topfirst, wfh)
        while (frp != NULL);
     }
 #endif
-    else
+    else    /* fr_layout == FR_COL */
     {
        /* Complicated case: Resize a column of frames.  Resize the bottom
         * frame first, frames above that when needed. */
@@ -2490,6 +2562,36 @@ frame_fixed_height(frp)
 }
 
 #ifdef FEAT_VERTSPLIT
+/*
+ * Return TRUE if width of frame "frp" should not be changed because of
+ * the 'winfixwidth' option.
+ */
+    static int
+frame_fixed_width(frp)
+    frame_T    *frp;
+{
+    /* frame with one window: fixed width if 'winfixwidth' set. */
+    if (frp->fr_win != NULL)
+       return frp->fr_win->w_p_wfw;
+
+    if (frp->fr_layout == FR_COL)
+    {
+       /* The frame is fixed width if one of the frames in the row is fixed
+        * width. */
+       for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
+           if (frame_fixed_width(frp))
+               return TRUE;
+       return FALSE;
+    }
+
+    /* frp->fr_layout == FR_ROW: The frame is fixed width if all of the
+     * frames in the row are fixed width. */
+    for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
+       if (!frame_fixed_width(frp))
+           return FALSE;
+    return TRUE;
+}
+
 /*
  * Add a status line to windows at the bottom of "frp".
  * Note: Does not check if there is room!
@@ -2530,10 +2632,12 @@ frame_add_statusline(frp)
  * May remove separator line for windows at the right side (for win_close()).
  */
     static void
-frame_new_width(topfrp, width, leftfirst)
+frame_new_width(topfrp, width, leftfirst, wfw)
     frame_T    *topfrp;
     int                width;
     int                leftfirst;      /* resize leftmost contained frame first */
+    int                wfw;            /* obey 'winfixwidth' when there is a choice;
+                                  may cause the width not to be set */
 {
     frame_T    *frp;
     int                extra_cols;
@@ -2554,20 +2658,45 @@ frame_new_width(topfrp, width, leftfirst)
     }
     else if (topfrp->fr_layout == FR_COL)
     {
-       /* All frames in this column get the same new width. */
-       for (frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next)
-           frame_new_width(frp, width, leftfirst);
+       do
+       {
+           /* All frames in this column get the same new width. */
+           for (frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next)
+           {
+               frame_new_width(frp, width, leftfirst, wfw);
+               if (frp->fr_width > width)
+               {
+                   /* Could not fit the windows, make whole column wider. */
+                   width = frp->fr_width;
+                   break;
+               }
+           }
+       } while (frp != NULL);
     }
     else    /* fr_layout == FR_ROW */
     {
        /* Complicated case: Resize a row of frames.  Resize the rightmost
         * frame first, frames left of it when needed. */
 
-       /* Find the rightmost frame of this row */
        frp = topfrp->fr_child;
+       if (wfw)
+           /* Advance past frames with one window with 'wfw' set. */
+           while (frame_fixed_width(frp))
+           {
+               frp = frp->fr_next;
+               if (frp == NULL)
+                   return;         /* no frame without 'wfw', give up */
+           }
        if (!leftfirst)
+       {
+           /* Find the rightmost frame of this row */
            while (frp->fr_next != NULL)
                frp = frp->fr_next;
+           if (wfw)
+               /* Advance back for frames with one window with 'wfw' set. */
+               while (frame_fixed_width(frp))
+                   frp = frp->fr_prev;
+       }
 
        extra_cols = width - topfrp->fr_width;
        if (extra_cols < 0)
@@ -2579,23 +2708,35 @@ frame_new_width(topfrp, width, leftfirst)
                if (frp->fr_width + extra_cols < w)
                {
                    extra_cols += frp->fr_width - w;
-                   frame_new_width(frp, w, leftfirst);
+                   frame_new_width(frp, w, leftfirst, wfw);
                }
                else
                {
-                   frame_new_width(frp, frp->fr_width + extra_cols, leftfirst);
+                   frame_new_width(frp, frp->fr_width + extra_cols,
+                                                             leftfirst, wfw);
                    break;
                }
                if (leftfirst)
-                   frp = frp->fr_next;
+               {
+                   do
+                       frp = frp->fr_next;
+                   while (wfw && frp != NULL && frame_fixed_width(frp));
+               }
                else
-                   frp = frp->fr_prev;
+               {
+                   do
+                       frp = frp->fr_prev;
+                   while (wfw && frp != NULL && frame_fixed_width(frp));
+               }
+               /* Increase "width" if we could not reduce enough frames. */
+               if (frp == NULL)
+                   width -= extra_cols;
            }
        }
        else if (extra_cols > 0)
        {
            /* increase width of rightmost frame */
-           frame_new_width(frp, frp->fr_width + extra_cols, leftfirst);
+           frame_new_width(frp, frp->fr_width + extra_cols, leftfirst, wfw);
        }
     }
     topfrp->fr_width = width;
@@ -3689,7 +3830,7 @@ win_enter_ext(wp, undo_sync, curwin_invalid)
 
 #ifdef FEAT_VERTSPLIT
     /* set window width to desired minimal value */
-    if (curwin->w_width < p_wiw)
+    if (curwin->w_width < p_wiw && !curwin->w_p_wfw)
        win_setwidth((int)p_wiw);
 #endif
 
@@ -4012,7 +4153,8 @@ shell_new_rows()
 #ifdef FEAT_WINDOWS
     if (h < frame_minheight(topframe, NULL))
        h = frame_minheight(topframe, NULL);
-    /* First try setting the heights of windows without 'winfixheight'.  If
+
+    /* First try setting the heights of windows with 'winfixheight'.  If
      * that doesn't result in the right height, forget about that option. */
     frame_new_height(topframe, h, FALSE, TRUE);
     if (topframe->fr_height != h)
@@ -4045,7 +4187,13 @@ shell_new_columns()
 {
     if (firstwin == NULL)      /* not initialized yet */
        return;
-    frame_new_width(topframe, (int)Columns, FALSE);
+
+    /* First try setting the widths of windows with 'winfixwidth'.  If that
+     * doesn't result in the right width, forget about that option. */
+    frame_new_width(topframe, (int)Columns, FALSE, TRUE);
+    if (topframe->fr_width != Columns)
+       frame_new_width(topframe, (int)Columns, FALSE, FALSE);
+
     (void)win_comp_pos();              /* recompute w_winrow and w_wincol */
 #if 0
     /* Disabled: don't want making the screen smaller make a window larger. */
@@ -4480,6 +4628,7 @@ frame_setwidth(curfrp, width)
     int                run;
     frame_T    *frp;
     int                w;
+    int                room_reserved;
 
     /* If the width already is the desired value, nothing to do. */
     if (curfrp->fr_width == width)
@@ -4511,9 +4660,14 @@ frame_setwidth(curfrp, width)
        for (run = 1; run <= 2; ++run)
        {
            room = 0;
+           room_reserved = 0;
            for (frp = curfrp->fr_parent->fr_child; frp != NULL;
                                                           frp = frp->fr_next)
            {
+               if (frp != curfrp
+                       && frp->fr_win != NULL
+                       && frp->fr_win->w_p_wfw)
+                   room_reserved += frp->fr_width;
                room += frp->fr_width;
                if (frp != curfrp)
                    room -= frame_minwidth(frp, NULL);
@@ -4531,17 +4685,25 @@ frame_setwidth(curfrp, width)
                 + frame_minwidth(curfrp->fr_parent, NOWIN) - (int)p_wmw - 1);
        }
 
-
        /*
         * Compute the number of lines we will take from others frames (can be
         * negative!).
         */
        take = width - curfrp->fr_width;
 
+       /* If there is not enough room, also reduce the width of a window
+        * with 'winfixwidth' set. */
+       if (width > room - room_reserved)
+           room_reserved = room - width;
+       /* If there is only a 'winfixwidth' window and making the
+        * window smaller, need to make the other window narrower. */
+       if (take < 0 && room - curfrp->fr_width < room_reserved)
+           room_reserved = 0;
+
        /*
         * set the current frame to the new width
         */
-       frame_new_width(curfrp, width, FALSE);
+       frame_new_width(curfrp, width, FALSE, FALSE);
 
        /*
         * First take lines from the frames right of the current frame.  If
@@ -4557,15 +4719,34 @@ frame_setwidth(curfrp, width)
            while (frp != NULL && take != 0)
            {
                w = frame_minwidth(frp, NULL);
-               if (frp->fr_width - take < w)
+               if (room_reserved > 0
+                       && frp->fr_win != NULL
+                       && frp->fr_win->w_p_wfw)
                {
-                   take -= frp->fr_width - w;
-                   frame_new_width(frp, w, FALSE);
+                   if (room_reserved >= frp->fr_width)
+                       room_reserved -= frp->fr_width;
+                   else
+                   {
+                       if (frp->fr_width - room_reserved > take)
+                           room_reserved = frp->fr_width - take;
+                       take -= frp->fr_width - room_reserved;
+                       frame_new_width(frp, room_reserved, FALSE, FALSE);
+                       room_reserved = 0;
+                   }
                }
                else
                {
-                   frame_new_width(frp, frp->fr_width - take, FALSE);
-                   take = 0;
+                   if (frp->fr_width - take < w)
+                   {
+                       take -= frp->fr_width - w;
+                       frame_new_width(frp, w, FALSE, FALSE);
+                   }
+                   else
+                   {
+                       frame_new_width(frp, frp->fr_width - take,
+                                                               FALSE, FALSE);
+                       take = 0;
+                   }
                }
                if (run == 0)
                    frp = frp->fr_next;
@@ -4811,7 +4992,7 @@ win_drag_vsep_line(dragwin, offset)
        return;
 
     /* grow frame fr by offset lines */
-    frame_new_width(fr, fr->fr_width + offset, left);
+    frame_new_width(fr, fr->fr_width + offset, left, FALSE);
 
     /* shrink other frames: current and at the left or at the right */
     if (left)
@@ -4825,11 +5006,11 @@ win_drag_vsep_line(dragwin, offset)
        if (fr->fr_width - offset <= n)
        {
            offset -= fr->fr_width - n;
-           frame_new_width(fr, n, !left);
+           frame_new_width(fr, n, !left, FALSE);
        }
        else
        {
-           frame_new_width(fr, fr->fr_width - offset, !left);
+           frame_new_width(fr, fr->fr_width - offset, !left, FALSE);
            break;
        }
        if (left)
@@ -5762,7 +5943,7 @@ restore_snapshot_rec(sn, fr)
     {
        frame_new_height(fr, fr->fr_height, FALSE, FALSE);
 # ifdef FEAT_VERTSPLIT
-       frame_new_width(fr, fr->fr_width, FALSE);
+       frame_new_width(fr, fr->fr_width, FALSE, FALSE);
 # endif
        wp = sn->fr_win;
     }