Patch 8.2.0674
Problem:    Some source files are too big.
Solution:   Move text formatting functions to a new file. (Yegappan
            Lakshmanan, closes #6021)
Files:      Filelist, src/Make_cyg_ming.mak, src/Make_morph.mak,
            src/Make_mvc.mak, src/Make_vms.mms, src/Makefile, src/README.md,
            src/edit.c, src/getchar.c, src/ops.c, src/option.c, src/proto.h,
            src/proto/edit.pro, src/proto/getchar.pro, src/proto/ops.pro,
            src/proto/option.pro, src/proto/textformat.pro, src/textformat.c


*** ../vim-8.2.0673/Filelist    2020-04-30 19:54:04.833418299 +0200
--- Filelist    2020-05-01 14:23:34.745538417 +0200
***************
*** 128,133 ****
--- 128,134 ----
                src/term.h \
                src/termlib.c \
                src/testing.c \
+               src/textformat.c \
                src/textobject.c \
                src/textprop.c \
                src/time.c \
***************
*** 280,285 ****
--- 281,287 ----
                src/proto/terminal.pro \
                src/proto/termlib.pro \
                src/proto/testing.pro \
+               src/proto/textformat.pro \
                src/proto/textobject.pro \
                src/proto/textprop.pro \
                src/proto/time.pro \
*** ../vim-8.2.0673/src/Make_cyg_ming.mak       2020-04-29 21:03:51.115170232 
+0200
--- src/Make_cyg_ming.mak       2020-05-01 14:23:34.745538417 +0200
***************
*** 787,792 ****
--- 787,793 ----
        $(OUTDIR)/tag.o \
        $(OUTDIR)/term.o \
        $(OUTDIR)/testing.o \
+       $(OUTDIR)/textformat.o \
        $(OUTDIR)/textobject.o \
        $(OUTDIR)/textprop.o \
        $(OUTDIR)/time.o \
*** ../vim-8.2.0673/src/Make_morph.mak  2020-04-29 21:03:51.115170232 +0200
--- src/Make_morph.mak  2020-05-01 14:23:34.745538417 +0200
***************
*** 103,108 ****
--- 103,109 ----
        tag.c                                                   \
        term.c                                                  \
        testing.c                                               \
+       textformat.c                                            \
        textobject.c                                            \
        textprop.c                                              \
        time.c                                                  \
*** ../vim-8.2.0673/src/Make_mvc.mak    2020-04-29 21:03:51.115170232 +0200
--- src/Make_mvc.mak    2020-05-01 14:23:34.749538404 +0200
***************
*** 806,811 ****
--- 806,812 ----
        $(OUTDIR)\tag.obj \
        $(OUTDIR)\term.obj \
        $(OUTDIR)\testing.obj \
+       $(OUTDIR)\textformat.obj \
        $(OUTDIR)\textobject.obj \
        $(OUTDIR)\textprop.obj \
        $(OUTDIR)\time.obj \
***************
*** 1745,1750 ****
--- 1746,1753 ----
  
  $(OUTDIR)/term.obj:   $(OUTDIR) testing.c  $(INCL)
  
+ $(OUTDIR)/textformat.obj:     $(OUTDIR) textformat.c  $(INCL)
+ 
  $(OUTDIR)/textobject.obj:     $(OUTDIR) textobject.c  $(INCL)
  
  $(OUTDIR)/textprop.obj:       $(OUTDIR) textprop.c  $(INCL)
***************
*** 1945,1950 ****
--- 1948,1954 ----
        proto/tag.pro \
        proto/term.pro \
        proto/testing.pro \
+       proto/textformat.pro \
        proto/textobject.pro \
        proto/textprop.pro \
        proto/time.pro \
*** ../vim-8.2.0673/src/Make_vms.mms    2020-04-29 21:03:51.115170232 +0200
--- src/Make_vms.mms    2020-05-01 14:23:34.749538404 +0200
***************
*** 382,387 ****
--- 382,388 ----
        term.c \
        termlib.c \
        testing.c \
+       textformat.c \
        textobject.c \
        textprop.c \
        time.c \
***************
*** 492,497 ****
--- 493,499 ----
        term.obj \
        termlib.obj \
        testing.obj \
+       textformat.obj \
        textobject.obj \
        textprop.obj \
        time.obj \
***************
*** 991,996 ****
--- 993,1001 ----
  testing.obj : testing.c vim.h [.auto]config.h feature.h os_unix.h   \
   ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \
   [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h
+ textformat.obj : textformat.c vim.h [.auto]config.h feature.h os_unix.h   \
+  ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \
+  [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h
  textobject.obj : textobject.c vim.h [.auto]config.h feature.h os_unix.h   \
   ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \
   [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h
*** ../vim-8.2.0673/src/Makefile        2020-05-01 14:14:04.359578294 +0200
--- src/Makefile        2020-05-01 14:23:34.749538404 +0200
***************
*** 1680,1685 ****
--- 1680,1686 ----
        term.c \
        terminal.c \
        testing.c \
+       textformat.c \
        textobject.c \
        textprop.c \
        time.c \
***************
*** 1823,1828 ****
--- 1824,1830 ----
        objects/term.o \
        objects/terminal.o \
        objects/testing.o \
+       objects/textformat.o \
        objects/textobject.o \
        objects/textprop.o \
        objects/time.o \
***************
*** 1998,2003 ****
--- 2000,2006 ----
        terminal.pro \
        termlib.pro \
        testing.pro \
+       textformat.pro \
        textobject.pro \
        textprop.pro \
        time.pro \
***************
*** 3479,3484 ****
--- 3482,3490 ----
  objects/testing.o: testing.c
        $(CCC) -o $@ testing.c
  
+ objects/textformat.o: textformat.c
+       $(CCC) -o $@ textformat.c
+ 
  objects/textobject.o: textobject.c
        $(CCC) -o $@ textobject.c
  
***************
*** 4073,4078 ****
--- 4079,4088 ----
   auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
   proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
   proto.h globals.h
+ objects/textformat.o: textformat.c vim.h protodef.h auto/config.h feature.h 
os_unix.h \
+  auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
+  proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
+  proto.h globals.h
  objects/textobject.o: textobject.c vim.h protodef.h auto/config.h feature.h 
os_unix.h \
   auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \
   proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \
*** ../vim-8.2.0673/src/README.md       2020-04-29 21:03:51.115170232 +0200
--- src/README.md       2020-05-01 14:23:34.749538404 +0200
***************
*** 80,85 ****
--- 80,86 ----
  tag.c         | tags
  term.c                | terminal handling, termcap codes
  testing.c     | testing: assert and test functions
+ textformat.c  | text formatting
  textobject.c  | text objects
  textprop.c    | text properties
  time.c                | time and timer functions
*** ../vim-8.2.0673/src/edit.c  2020-04-30 22:29:36.622024155 +0200
--- src/edit.c  2020-05-01 14:23:34.749538404 +0200
***************
*** 28,35 ****
  static void init_prompt(int cmdchar_todo);
  #endif
  static void insert_special(int, int, int);
- static void internal_format(int textwidth, int second_indent, int flags, int 
format_only, int c);
- static void check_auto_format(int);
  static void redo_literal(int c);
  static void start_arrow_common(pos_T *end_insert_pos, int change);
  #ifdef FEAT_SPELL
--- 28,33 ----
***************
*** 104,111 ****
                                        // char.  Set when edit() is called.
                                        // after that arrow_used is used.
  
- static int    did_add_space = FALSE;  // auto_format() added an extra space
-                                       // under the cursor
  static int    dont_sync_undo = FALSE; // CTRL-G U prevents syncing undo for
                                        // the next left/right cursor key
  
--- 102,107 ----
***************
*** 2063,2070 ****
  # define ISSPECIAL(c) ((c) < ' ' || (c) >= DEL || (c) == '0' || (c) == '^')
  #endif
  
- #define WHITECHAR(cc) (VIM_ISWHITE(cc) && (!enc_utf8 || 
!utf_iscomposing(utf_ptr2char(ml_get_cursor() + 1))))
- 
  /*
   * "flags": INSCHAR_FORMAT - force formatting
   *        INSCHAR_CTRLV  - char typed just after CTRL-V
--- 2059,2064 ----
***************
*** 2302,2868 ****
  }
  
  /*
-  * Format text at the current insert position.
-  *
-  * If the INSCHAR_COM_LIST flag is present, then the value of second_indent
-  * will be the comment leader length sent to open_line().
-  */
-     static void
- internal_format(
-     int               textwidth,
-     int               second_indent,
-     int               flags,
-     int               format_only,
-     int               c) // character to be inserted (can be NUL)
- {
-     int               cc;
-     int               save_char = NUL;
-     int               haveto_redraw = FALSE;
-     int               fo_ins_blank = has_format_option(FO_INS_BLANK);
-     int               fo_multibyte = has_format_option(FO_MBYTE_BREAK);
-     int               fo_white_par = has_format_option(FO_WHITE_PAR);
-     int               first_line = TRUE;
-     colnr_T   leader_len;
-     int               no_leader = FALSE;
-     int               do_comments = (flags & INSCHAR_DO_COM);
- #ifdef FEAT_LINEBREAK
-     int               has_lbr = curwin->w_p_lbr;
- 
-     // make sure win_lbr_chartabsize() counts correctly
-     curwin->w_p_lbr = FALSE;
- #endif
- 
-     /*
-      * When 'ai' is off we don't want a space under the cursor to be
-      * deleted.  Replace it with an 'x' temporarily.
-      */
-     if (!curbuf->b_p_ai && !(State & VREPLACE_FLAG))
-     {
-       cc = gchar_cursor();
-       if (VIM_ISWHITE(cc))
-       {
-           save_char = cc;
-           pchar_cursor('x');
-       }
-     }
- 
-     /*
-      * Repeat breaking lines, until the current line is not too long.
-      */
-     while (!got_int)
-     {
-       int     startcol;               // Cursor column at entry
-       int     wantcol;                // column at textwidth border
-       int     foundcol;               // column for start of spaces
-       int     end_foundcol = 0;       // column for start of word
-       colnr_T len;
-       colnr_T virtcol;
-       int     orig_col = 0;
-       char_u  *saved_text = NULL;
-       colnr_T col;
-       colnr_T end_col;
-       int     wcc;                    // counter for whitespace chars
- 
-       virtcol = get_nolist_virtcol()
-               + char2cells(c != NUL ? c : gchar_cursor());
-       if (virtcol <= (colnr_T)textwidth)
-           break;
- 
-       if (no_leader)
-           do_comments = FALSE;
-       else if (!(flags & INSCHAR_FORMAT)
-                                      && has_format_option(FO_WRAP_COMS))
-           do_comments = TRUE;
- 
-       // Don't break until after the comment leader
-       if (do_comments)
-           leader_len = get_leader_len(ml_get_curline(), NULL, FALSE, TRUE);
-       else
-           leader_len = 0;
- 
-       // If the line doesn't start with a comment leader, then don't
-       // start one in a following broken line.  Avoids that a %word
-       // moved to the start of the next line causes all following lines
-       // to start with %.
-       if (leader_len == 0)
-           no_leader = TRUE;
-       if (!(flags & INSCHAR_FORMAT)
-               && leader_len == 0
-               && !has_format_option(FO_WRAP))
- 
-           break;
-       if ((startcol = curwin->w_cursor.col) == 0)
-           break;
- 
-       // find column of textwidth border
-       coladvance((colnr_T)textwidth);
-       wantcol = curwin->w_cursor.col;
- 
-       curwin->w_cursor.col = startcol;
-       foundcol = 0;
- 
-       /*
-        * Find position to break at.
-        * Stop at first entered white when 'formatoptions' has 'v'
-        */
-       while ((!fo_ins_blank && !has_format_option(FO_INS_VI))
-                   || (flags & INSCHAR_FORMAT)
-                   || curwin->w_cursor.lnum != Insstart.lnum
-                   || curwin->w_cursor.col >= Insstart.col)
-       {
-           if (curwin->w_cursor.col == startcol && c != NUL)
-               cc = c;
-           else
-               cc = gchar_cursor();
-           if (WHITECHAR(cc))
-           {
-               // remember position of blank just before text
-               end_col = curwin->w_cursor.col;
- 
-               // find start of sequence of blanks
-               wcc = 0;
-               while (curwin->w_cursor.col > 0 && WHITECHAR(cc))
-               {
-                   dec_cursor();
-                   cc = gchar_cursor();
- 
-                   // Increment count of how many whitespace chars in this
-                   // group; we only need to know if it's more than one.
-                   if (wcc < 2)
-                       wcc++;
-               }
-               if (curwin->w_cursor.col == 0 && WHITECHAR(cc))
-                   break;              // only spaces in front of text
- 
-               // Don't break after a period when 'formatoptions' has 'p' and
-               // there are less than two spaces.
-               if (has_format_option(FO_PERIOD_ABBR) && cc == '.' && wcc < 2)
-                   continue;
- 
-               // Don't break until after the comment leader
-               if (curwin->w_cursor.col < leader_len)
-                   break;
-               if (has_format_option(FO_ONE_LETTER))
-               {
-                   // do not break after one-letter words
-                   if (curwin->w_cursor.col == 0)
-                       break;  // one-letter word at begin
-                   // do not break "#a b" when 'tw' is 2
-                   if (curwin->w_cursor.col <= leader_len)
-                       break;
-                   col = curwin->w_cursor.col;
-                   dec_cursor();
-                   cc = gchar_cursor();
- 
-                   if (WHITECHAR(cc))
-                       continue;       // one-letter, continue
-                   curwin->w_cursor.col = col;
-               }
- 
-               inc_cursor();
- 
-               end_foundcol = end_col + 1;
-               foundcol = curwin->w_cursor.col;
-               if (curwin->w_cursor.col <= (colnr_T)wantcol)
-                   break;
-           }
-           else if (cc >= 0x100 && fo_multibyte)
-           {
-               // Break after or before a multi-byte character.
-               if (curwin->w_cursor.col != startcol)
-               {
-                   // Don't break until after the comment leader
-                   if (curwin->w_cursor.col < leader_len)
-                       break;
-                   col = curwin->w_cursor.col;
-                   inc_cursor();
-                   // Don't change end_foundcol if already set.
-                   if (foundcol != curwin->w_cursor.col)
-                   {
-                       foundcol = curwin->w_cursor.col;
-                       end_foundcol = foundcol;
-                       if (curwin->w_cursor.col <= (colnr_T)wantcol)
-                           break;
-                   }
-                   curwin->w_cursor.col = col;
-               }
- 
-               if (curwin->w_cursor.col == 0)
-                   break;
- 
-               col = curwin->w_cursor.col;
- 
-               dec_cursor();
-               cc = gchar_cursor();
- 
-               if (WHITECHAR(cc))
-                   continue;           // break with space
-               // Don't break until after the comment leader
-               if (curwin->w_cursor.col < leader_len)
-                   break;
- 
-               curwin->w_cursor.col = col;
- 
-               foundcol = curwin->w_cursor.col;
-               end_foundcol = foundcol;
-               if (curwin->w_cursor.col <= (colnr_T)wantcol)
-                   break;
-           }
-           if (curwin->w_cursor.col == 0)
-               break;
-           dec_cursor();
-       }
- 
-       if (foundcol == 0)              // no spaces, cannot break line
-       {
-           curwin->w_cursor.col = startcol;
-           break;
-       }
- 
-       // Going to break the line, remove any "$" now.
-       undisplay_dollar();
- 
-       /*
-        * Offset between cursor position and line break is used by replace
-        * stack functions.  VREPLACE does not use this, and backspaces
-        * over the text instead.
-        */
-       if (State & VREPLACE_FLAG)
-           orig_col = startcol;        // Will start backspacing from here
-       else
-           replace_offset = startcol - end_foundcol;
- 
-       /*
-        * adjust startcol for spaces that will be deleted and
-        * characters that will remain on top line
-        */
-       curwin->w_cursor.col = foundcol;
-       while ((cc = gchar_cursor(), WHITECHAR(cc))
-                   && (!fo_white_par || curwin->w_cursor.col < startcol))
-           inc_cursor();
-       startcol -= curwin->w_cursor.col;
-       if (startcol < 0)
-           startcol = 0;
- 
-       if (State & VREPLACE_FLAG)
-       {
-           /*
-            * In VREPLACE mode, we will backspace over the text to be
-            * wrapped, so save a copy now to put on the next line.
-            */
-           saved_text = vim_strsave(ml_get_cursor());
-           curwin->w_cursor.col = orig_col;
-           if (saved_text == NULL)
-               break;  // Can't do it, out of memory
-           saved_text[startcol] = NUL;
- 
-           // Backspace over characters that will move to the next line
-           if (!fo_white_par)
-               backspace_until_column(foundcol);
-       }
-       else
-       {
-           // put cursor after pos. to break line
-           if (!fo_white_par)
-               curwin->w_cursor.col = foundcol;
-       }
- 
-       /*
-        * Split the line just before the margin.
-        * Only insert/delete lines, but don't really redraw the window.
-        */
-       open_line(FORWARD, OPENLINE_DELSPACES + OPENLINE_MARKFIX
-               + (fo_white_par ? OPENLINE_KEEPTRAIL : 0)
-               + (do_comments ? OPENLINE_DO_COM : 0)
-               + ((flags & INSCHAR_COM_LIST) ? OPENLINE_COM_LIST : 0)
-               , ((flags & INSCHAR_COM_LIST) ? second_indent : old_indent));
-       if (!(flags & INSCHAR_COM_LIST))
-           old_indent = 0;
- 
-       replace_offset = 0;
-       if (first_line)
-       {
-           if (!(flags & INSCHAR_COM_LIST))
-           {
-               /*
-                * This section is for auto-wrap of numeric lists.  When not
-                * in insert mode (i.e. format_lines()), the INSCHAR_COM_LIST
-                * flag will be set and open_line() will handle it (as seen
-                * above).  The code here (and in get_number_indent()) will
-                * recognize comments if needed...
-                */
-               if (second_indent < 0 && has_format_option(FO_Q_NUMBER))
-                   second_indent =
-                                get_number_indent(curwin->w_cursor.lnum - 1);
-               if (second_indent >= 0)
-               {
-                   if (State & VREPLACE_FLAG)
-                       change_indent(INDENT_SET, second_indent,
-                                                           FALSE, NUL, TRUE);
-                   else
-                       if (leader_len > 0 && second_indent - leader_len > 0)
-                   {
-                       int i;
-                       int padding = second_indent - leader_len;
- 
-                       // We started at the first_line of a numbered list
-                       // that has a comment.  the open_line() function has
-                       // inserted the proper comment leader and positioned
-                       // the cursor at the end of the split line.  Now we
-                       // add the additional whitespace needed after the
-                       // comment leader for the numbered list.
-                       for (i = 0; i < padding; i++)
-                           ins_str((char_u *)" ");
-                   }
-                   else
-                   {
-                       (void)set_indent(second_indent, SIN_CHANGED);
-                   }
-               }
-           }
-           first_line = FALSE;
-       }
- 
-       if (State & VREPLACE_FLAG)
-       {
-           /*
-            * In VREPLACE mode we have backspaced over the text to be
-            * moved, now we re-insert it into the new line.
-            */
-           ins_bytes(saved_text);
-           vim_free(saved_text);
-       }
-       else
-       {
-           /*
-            * Check if cursor is not past the NUL off the line, cindent
-            * may have added or removed indent.
-            */
-           curwin->w_cursor.col += startcol;
-           len = (colnr_T)STRLEN(ml_get_curline());
-           if (curwin->w_cursor.col > len)
-               curwin->w_cursor.col = len;
-       }
- 
-       haveto_redraw = TRUE;
- #ifdef FEAT_CINDENT
-       can_cindent = TRUE;
- #endif
-       // moved the cursor, don't autoindent or cindent now
-       did_ai = FALSE;
- #ifdef FEAT_SMARTINDENT
-       did_si = FALSE;
-       can_si = FALSE;
-       can_si_back = FALSE;
- #endif
-       line_breakcheck();
-     }
- 
-     if (save_char != NUL)             // put back space after cursor
-       pchar_cursor(save_char);
- 
- #ifdef FEAT_LINEBREAK
-     curwin->w_p_lbr = has_lbr;
- #endif
-     if (!format_only && haveto_redraw)
-     {
-       update_topline();
-       redraw_curbuf_later(VALID);
-     }
- }
- 
- /*
-  * Called after inserting or deleting text: When 'formatoptions' includes the
-  * 'a' flag format from the current line until the end of the paragraph.
-  * Keep the cursor at the same position relative to the text.
-  * The caller must have saved the cursor line for undo, following ones will be
-  * saved here.
-  */
-     void
- auto_format(
-     int               trailblank,     // when TRUE also format with trailing 
blank
-     int               prev_line)      // may start in previous line
- {
-     pos_T     pos;
-     colnr_T   len;
-     char_u    *old;
-     char_u    *new, *pnew;
-     int               wasatend;
-     int               cc;
- 
-     if (!has_format_option(FO_AUTO))
-       return;
- 
-     pos = curwin->w_cursor;
-     old = ml_get_curline();
- 
-     // may remove added space
-     check_auto_format(FALSE);
- 
-     // Don't format in Insert mode when the cursor is on a trailing blank, the
-     // user might insert normal text next.  Also skip formatting when "1" is
-     // in 'formatoptions' and there is a single character before the cursor.
-     // Otherwise the line would be broken and when typing another non-white
-     // next they are not joined back together.
-     wasatend = (pos.col == (colnr_T)STRLEN(old));
-     if (*old != NUL && !trailblank && wasatend)
-     {
-       dec_cursor();
-       cc = gchar_cursor();
-       if (!WHITECHAR(cc) && curwin->w_cursor.col > 0
-                                         && has_format_option(FO_ONE_LETTER))
-           dec_cursor();
-       cc = gchar_cursor();
-       if (WHITECHAR(cc))
-       {
-           curwin->w_cursor = pos;
-           return;
-       }
-       curwin->w_cursor = pos;
-     }
- 
-     // With the 'c' flag in 'formatoptions' and 't' missing: only format
-     // comments.
-     if (has_format_option(FO_WRAP_COMS) && !has_format_option(FO_WRAP)
-                               && get_leader_len(old, NULL, FALSE, TRUE) == 0)
-       return;
- 
-     /*
-      * May start formatting in a previous line, so that after "x" a word is
-      * moved to the previous line if it fits there now.  Only when this is not
-      * the start of a paragraph.
-      */
-     if (prev_line && !paragraph_start(curwin->w_cursor.lnum))
-     {
-       --curwin->w_cursor.lnum;
-       if (u_save_cursor() == FAIL)
-           return;
-     }
- 
-     /*
-      * Do the formatting and restore the cursor position.  "saved_cursor" will
-      * be adjusted for the text formatting.
-      */
-     saved_cursor = pos;
-     format_lines((linenr_T)-1, FALSE);
-     curwin->w_cursor = saved_cursor;
-     saved_cursor.lnum = 0;
- 
-     if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
-     {
-       // "cannot happen"
-       curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
-       coladvance((colnr_T)MAXCOL);
-     }
-     else
-       check_cursor_col();
- 
-     // Insert mode: If the cursor is now after the end of the line while it
-     // previously wasn't, the line was broken.  Because of the rule above we
-     // need to add a space when 'w' is in 'formatoptions' to keep a paragraph
-     // formatted.
-     if (!wasatend && has_format_option(FO_WHITE_PAR))
-     {
-       new = ml_get_curline();
-       len = (colnr_T)STRLEN(new);
-       if (curwin->w_cursor.col == len)
-       {
-           pnew = vim_strnsave(new, len + 2);
-           pnew[len] = ' ';
-           pnew[len + 1] = NUL;
-           ml_replace(curwin->w_cursor.lnum, pnew, FALSE);
-           // remove the space later
-           did_add_space = TRUE;
-       }
-       else
-           // may remove added space
-           check_auto_format(FALSE);
-     }
- 
-     check_cursor();
- }
- 
- /*
-  * When an extra space was added to continue a paragraph for auto-formatting,
-  * delete it now.  The space must be under the cursor, just after the insert
-  * position.
-  */
-     static void
- check_auto_format(
-     int               end_insert)         // TRUE when ending Insert mode
- {
-     int               c = ' ';
-     int               cc;
- 
-     if (did_add_space)
-     {
-       cc = gchar_cursor();
-       if (!WHITECHAR(cc))
-           // Somehow the space was removed already.
-           did_add_space = FALSE;
-       else
-       {
-           if (!end_insert)
-           {
-               inc_cursor();
-               c = gchar_cursor();
-               dec_cursor();
-           }
-           if (c != NUL)
-           {
-               // The space is no longer at the end of the line, delete it.
-               del_char(FALSE);
-               did_add_space = FALSE;
-           }
-       }
-     }
- }
- 
- /*
-  * Find out textwidth to be used for formatting:
-  *    if 'textwidth' option is set, use it
-  *    else if 'wrapmargin' option is set, use curwin->w_width - 'wrapmargin'
-  *    if invalid value, use 0.
-  *    Set default to window width (maximum 79) for "gq" operator.
-  */
-     int
- comp_textwidth(
-     int               ff)     // force formatting (for "gq" command)
- {
-     int               textwidth;
- 
-     textwidth = curbuf->b_p_tw;
-     if (textwidth == 0 && curbuf->b_p_wm)
-     {
-       // The width is the window width minus 'wrapmargin' minus all the
-       // things that add to the margin.
-       textwidth = curwin->w_width - curbuf->b_p_wm;
- #ifdef FEAT_CMDWIN
-       if (cmdwin_type != 0)
-           textwidth -= 1;
- #endif
- #ifdef FEAT_FOLDING
-       textwidth -= curwin->w_p_fdc;
- #endif
- #ifdef FEAT_SIGNS
-       if (signcolumn_on(curwin))
-           textwidth -= 1;
- #endif
-       if (curwin->w_p_nu || curwin->w_p_rnu)
-           textwidth -= 8;
-     }
-     if (textwidth < 0)
-       textwidth = 0;
-     if (ff && textwidth == 0)
-     {
-       textwidth = curwin->w_width - 1;
-       if (textwidth > 79)
-           textwidth = 79;
-     }
-     return textwidth;
- }
- 
- /*
   * Put a character in the redo buffer, for when just after a CTRL-V.
   */
      static void
--- 2296,2301 ----
*** ../vim-8.2.0673/src/getchar.c       2020-04-05 18:56:02.233436590 +0200
--- src/getchar.c       2020-05-01 14:23:34.749538404 +0200
***************
*** 685,690 ****
--- 685,730 ----
  }
  
  /*
+  * Stuff a string into the typeahead buffer, such that edit() will insert it
+  * literally ("literally" TRUE) or interpret is as typed characters.
+  */
+     void
+ stuffescaped(char_u *arg, int literally)
+ {
+     int               c;
+     char_u    *start;
+ 
+     while (*arg != NUL)
+     {
+       // Stuff a sequence of normal ASCII characters, that's fast.  Also
+       // stuff K_SPECIAL to get the effect of a special key when "literally"
+       // is TRUE.
+       start = arg;
+       while ((*arg >= ' '
+ #ifndef EBCDIC
+                   && *arg < DEL // EBCDIC: chars above space are normal
+ #endif
+                   )
+               || (*arg == K_SPECIAL && !literally))
+           ++arg;
+       if (arg > start)
+           stuffReadbuffLen(start, (long)(arg - start));
+ 
+       // stuff a single special character
+       if (*arg != NUL)
+       {
+           if (has_mbyte)
+               c = mb_cptr2char_adv(&arg);
+           else
+               c = *arg++;
+           if (literally && ((c < ' ' && c != TAB) || c == DEL))
+               stuffcharReadbuff(Ctrl_V);
+           stuffcharReadbuff(c);
+       }
+     }
+ }
+ 
+ /*
   * Read a character from the redo buffer.  Translates K_SPECIAL, CSI and
   * multibyte characters.
   * The redo buffer is left as it is.
*** ../vim-8.2.0673/src/ops.c   2020-04-12 19:37:13.518297259 +0200
--- src/ops.c   2020-05-01 14:23:34.749538404 +0200
***************
*** 17,24 ****
  static void shift_block(oparg_T *oap, int amount);
  static void   mb_adjust_opend(oparg_T *oap);
  static int    do_addsub(int op_type, pos_T *pos, int length, linenr_T 
Prenum1);
- static int    ends_in_white(linenr_T lnum);
- static int    fmt_check_par(linenr_T, int *, char_u **, int do_comments);
  
  // Flags for third item in "opchars".
  #define OPF_LINES  1  // operator always works on lines
--- 17,22 ----
***************
*** 591,636 ****
  }
  
  /*
-  * Stuff a string into the typeahead buffer, such that edit() will insert it
-  * literally ("literally" TRUE) or interpret is as typed characters.
-  */
-     void
- stuffescaped(char_u *arg, int literally)
- {
-     int               c;
-     char_u    *start;
- 
-     while (*arg != NUL)
-     {
-       // Stuff a sequence of normal ASCII characters, that's fast.  Also
-       // stuff K_SPECIAL to get the effect of a special key when "literally"
-       // is TRUE.
-       start = arg;
-       while ((*arg >= ' '
- #ifndef EBCDIC
-                   && *arg < DEL // EBCDIC: chars above space are normal
- #endif
-                   )
-               || (*arg == K_SPECIAL && !literally))
-           ++arg;
-       if (arg > start)
-           stuffReadbuffLen(start, (long)(arg - start));
- 
-       // stuff a single special character
-       if (*arg != NUL)
-       {
-           if (has_mbyte)
-               c = mb_cptr2char_adv(&arg);
-           else
-               c = *arg++;
-           if (literally && ((c < ' ' && c != TAB) || c == DEL))
-               stuffcharReadbuff(Ctrl_V);
-           stuffcharReadbuff(c);
-       }
-     }
- }
- 
- /*
   * Handle a delete operation.
   *
   * Return FAIL if undo failed, OK otherwise.
--- 589,594 ----
***************
*** 2171,2724 ****
  }
  
  /*
-  * Return TRUE if the two comment leaders given are the same.  "lnum" is
-  * the first line.  White-space is ignored.  Note that the whole of
-  * 'leader1' must match 'leader2_len' characters from 'leader2' -- webb
-  */
-     static int
- same_leader(
-     linenr_T lnum,
-     int           leader1_len,
-     char_u  *leader1_flags,
-     int           leader2_len,
-     char_u  *leader2_flags)
- {
-     int           idx1 = 0, idx2 = 0;
-     char_u  *p;
-     char_u  *line1;
-     char_u  *line2;
- 
-     if (leader1_len == 0)
-       return (leader2_len == 0);
- 
-     /*
-      * If first leader has 'f' flag, the lines can be joined only if the
-      * second line does not have a leader.
-      * If first leader has 'e' flag, the lines can never be joined.
-      * If fist leader has 's' flag, the lines can only be joined if there is
-      * some text after it and the second line has the 'm' flag.
-      */
-     if (leader1_flags != NULL)
-     {
-       for (p = leader1_flags; *p && *p != ':'; ++p)
-       {
-           if (*p == COM_FIRST)
-               return (leader2_len == 0);
-           if (*p == COM_END)
-               return FALSE;
-           if (*p == COM_START)
-           {
-               if (*(ml_get(lnum) + leader1_len) == NUL)
-                   return FALSE;
-               if (leader2_flags == NULL || leader2_len == 0)
-                   return FALSE;
-               for (p = leader2_flags; *p && *p != ':'; ++p)
-                   if (*p == COM_MIDDLE)
-                       return TRUE;
-               return FALSE;
-           }
-       }
-     }
- 
-     /*
-      * Get current line and next line, compare the leaders.
-      * The first line has to be saved, only one line can be locked at a time.
-      */
-     line1 = vim_strsave(ml_get(lnum));
-     if (line1 != NULL)
-     {
-       for (idx1 = 0; VIM_ISWHITE(line1[idx1]); ++idx1)
-           ;
-       line2 = ml_get(lnum + 1);
-       for (idx2 = 0; idx2 < leader2_len; ++idx2)
-       {
-           if (!VIM_ISWHITE(line2[idx2]))
-           {
-               if (line1[idx1++] != line2[idx2])
-                   break;
-           }
-           else
-               while (VIM_ISWHITE(line1[idx1]))
-                   ++idx1;
-       }
-       vim_free(line1);
-     }
-     return (idx2 == leader2_len && idx1 == leader1_len);
- }
- 
- /*
-  * Implementation of the format operator 'gq'.
-  */
-     static void
- op_format(
-     oparg_T   *oap,
-     int               keep_cursor)            // keep cursor on same text char
- {
-     long      old_line_count = curbuf->b_ml.ml_line_count;
- 
-     // Place the cursor where the "gq" or "gw" command was given, so that "u"
-     // can put it back there.
-     curwin->w_cursor = oap->cursor_start;
- 
-     if (u_save((linenr_T)(oap->start.lnum - 1),
-                                      (linenr_T)(oap->end.lnum + 1)) == FAIL)
-       return;
-     curwin->w_cursor = oap->start;
- 
-     if (oap->is_VIsual)
-       // When there is no change: need to remove the Visual selection
-       redraw_curbuf_later(INVERTED);
- 
-     if (!cmdmod.lockmarks)
-       // Set '[ mark at the start of the formatted area
-       curbuf->b_op_start = oap->start;
- 
-     // For "gw" remember the cursor position and put it back below (adjusted
-     // for joined and split lines).
-     if (keep_cursor)
-       saved_cursor = oap->cursor_start;
- 
-     format_lines(oap->line_count, keep_cursor);
- 
-     /*
-      * Leave the cursor at the first non-blank of the last formatted line.
-      * If the cursor was moved one line back (e.g. with "Q}") go to the next
-      * line, so "." will do the next lines.
-      */
-     if (oap->end_adjusted && curwin->w_cursor.lnum < 
curbuf->b_ml.ml_line_count)
-       ++curwin->w_cursor.lnum;
-     beginline(BL_WHITE | BL_FIX);
-     old_line_count = curbuf->b_ml.ml_line_count - old_line_count;
-     msgmore(old_line_count);
- 
-     if (!cmdmod.lockmarks)
-       // put '] mark on the end of the formatted area
-       curbuf->b_op_end = curwin->w_cursor;
- 
-     if (keep_cursor)
-     {
-       curwin->w_cursor = saved_cursor;
-       saved_cursor.lnum = 0;
-     }
- 
-     if (oap->is_VIsual)
-     {
-       win_T   *wp;
- 
-       FOR_ALL_WINDOWS(wp)
-       {
-           if (wp->w_old_cursor_lnum != 0)
-           {
-               // When lines have been inserted or deleted, adjust the end of
-               // the Visual area to be redrawn.
-               if (wp->w_old_cursor_lnum > wp->w_old_visual_lnum)
-                   wp->w_old_cursor_lnum += old_line_count;
-               else
-                   wp->w_old_visual_lnum += old_line_count;
-           }
-       }
-     }
- }
- 
- #if defined(FEAT_EVAL) || defined(PROTO)
- /*
-  * Implementation of the format operator 'gq' for when using 'formatexpr'.
-  */
-     static void
- op_formatexpr(oparg_T *oap)
- {
-     if (oap->is_VIsual)
-       // When there is no change: need to remove the Visual selection
-       redraw_curbuf_later(INVERTED);
- 
-     if (fex_format(oap->start.lnum, oap->line_count, NUL) != 0)
-       // As documented: when 'formatexpr' returns non-zero fall back to
-       // internal formatting.
-       op_format(oap, FALSE);
- }
- 
-     int
- fex_format(
-     linenr_T  lnum,
-     long      count,
-     int               c)      // character to be inserted
- {
-     int               use_sandbox = was_set_insecurely((char_u *)"formatexpr",
-                                                                  OPT_LOCAL);
-     int               r;
-     char_u    *fex;
- 
-     /*
-      * Set v:lnum to the first line number and v:count to the number of lines.
-      * Set v:char to the character to be inserted (can be NUL).
-      */
-     set_vim_var_nr(VV_LNUM, lnum);
-     set_vim_var_nr(VV_COUNT, count);
-     set_vim_var_char(c);
- 
-     // Make a copy, the option could be changed while calling it.
-     fex = vim_strsave(curbuf->b_p_fex);
-     if (fex == NULL)
-       return 0;
- 
-     /*
-      * Evaluate the function.
-      */
-     if (use_sandbox)
-       ++sandbox;
-     r = (int)eval_to_number(fex);
-     if (use_sandbox)
-       --sandbox;
- 
-     set_vim_var_string(VV_CHAR, NULL, -1);
-     vim_free(fex);
- 
-     return r;
- }
- #endif
- 
- /*
-  * Format "line_count" lines, starting at the cursor position.
-  * When "line_count" is negative, format until the end of the paragraph.
-  * Lines after the cursor line are saved for undo, caller must have saved the
-  * first line.
-  */
-     void
- format_lines(
-     linenr_T  line_count,
-     int               avoid_fex)              // don't use 'formatexpr'
- {
-     int               max_len;
-     int               is_not_par;             // current line not part of 
parag.
-     int               next_is_not_par;        // next line not part of 
paragraph
-     int               is_end_par;             // at end of paragraph
-     int               prev_is_end_par = FALSE;// prev. line not part of parag.
-     int               next_is_start_par = FALSE;
-     int               leader_len = 0;         // leader len of current line
-     int               next_leader_len;        // leader len of next line
-     char_u    *leader_flags = NULL;   // flags for leader of current line
-     char_u    *next_leader_flags;     // flags for leader of next line
-     int               do_comments;            // format comments
-     int               do_comments_list = 0;   // format comments with 'n' or 
'2'
-     int               advance = TRUE;
-     int               second_indent = -1;     // indent for second line 
(comment
-                                       // aware)
-     int               do_second_indent;
-     int               do_number_indent;
-     int               do_trail_white;
-     int               first_par_line = TRUE;
-     int               smd_save;
-     long      count;
-     int               need_set_indent = TRUE; // set indent of next paragraph
-     int               force_format = FALSE;
-     int               old_State = State;
- 
-     // length of a line to force formatting: 3 * 'tw'
-     max_len = comp_textwidth(TRUE) * 3;
- 
-     // check for 'q', '2' and '1' in 'formatoptions'
-     do_comments = has_format_option(FO_Q_COMS);
-     do_second_indent = has_format_option(FO_Q_SECOND);
-     do_number_indent = has_format_option(FO_Q_NUMBER);
-     do_trail_white = has_format_option(FO_WHITE_PAR);
- 
-     /*
-      * Get info about the previous and current line.
-      */
-     if (curwin->w_cursor.lnum > 1)
-       is_not_par = fmt_check_par(curwin->w_cursor.lnum - 1
-                               , &leader_len, &leader_flags, do_comments);
-     else
-       is_not_par = TRUE;
-     next_is_not_par = fmt_check_par(curwin->w_cursor.lnum
-                         , &next_leader_len, &next_leader_flags, do_comments);
-     is_end_par = (is_not_par || next_is_not_par);
-     if (!is_end_par && do_trail_white)
-       is_end_par = !ends_in_white(curwin->w_cursor.lnum - 1);
- 
-     curwin->w_cursor.lnum--;
-     for (count = line_count; count != 0 && !got_int; --count)
-     {
-       /*
-        * Advance to next paragraph.
-        */
-       if (advance)
-       {
-           curwin->w_cursor.lnum++;
-           prev_is_end_par = is_end_par;
-           is_not_par = next_is_not_par;
-           leader_len = next_leader_len;
-           leader_flags = next_leader_flags;
-       }
- 
-       /*
-        * The last line to be formatted.
-        */
-       if (count == 1 || curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)
-       {
-           next_is_not_par = TRUE;
-           next_leader_len = 0;
-           next_leader_flags = NULL;
-       }
-       else
-       {
-           next_is_not_par = fmt_check_par(curwin->w_cursor.lnum + 1
-                         , &next_leader_len, &next_leader_flags, do_comments);
-           if (do_number_indent)
-               next_is_start_par =
-                          (get_number_indent(curwin->w_cursor.lnum + 1) > 0);
-       }
-       advance = TRUE;
-       is_end_par = (is_not_par || next_is_not_par || next_is_start_par);
-       if (!is_end_par && do_trail_white)
-           is_end_par = !ends_in_white(curwin->w_cursor.lnum);
- 
-       /*
-        * Skip lines that are not in a paragraph.
-        */
-       if (is_not_par)
-       {
-           if (line_count < 0)
-               break;
-       }
-       else
-       {
-           /*
-            * For the first line of a paragraph, check indent of second line.
-            * Don't do this for comments and empty lines.
-            */
-           if (first_par_line
-                   && (do_second_indent || do_number_indent)
-                   && prev_is_end_par
-                   && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
-           {
-               if (do_second_indent && !LINEEMPTY(curwin->w_cursor.lnum + 1))
-               {
-                   if (leader_len == 0 && next_leader_len == 0)
-                   {
-                       // no comment found
-                       second_indent =
-                                  get_indent_lnum(curwin->w_cursor.lnum + 1);
-                   }
-                   else
-                   {
-                       second_indent = next_leader_len;
-                       do_comments_list = 1;
-                   }
-               }
-               else if (do_number_indent)
-               {
-                   if (leader_len == 0 && next_leader_len == 0)
-                   {
-                       // no comment found
-                       second_indent =
-                                    get_number_indent(curwin->w_cursor.lnum);
-                   }
-                   else
-                   {
-                       // get_number_indent() is now "comment aware"...
-                       second_indent =
-                                    get_number_indent(curwin->w_cursor.lnum);
-                       do_comments_list = 1;
-                   }
-               }
-           }
- 
-           /*
-            * When the comment leader changes, it's the end of the paragraph.
-            */
-           if (curwin->w_cursor.lnum >= curbuf->b_ml.ml_line_count
-                   || !same_leader(curwin->w_cursor.lnum,
-                                       leader_len, leader_flags,
-                                          next_leader_len, next_leader_flags))
-               is_end_par = TRUE;
- 
-           /*
-            * If we have got to the end of a paragraph, or the line is
-            * getting long, format it.
-            */
-           if (is_end_par || force_format)
-           {
-               if (need_set_indent)
-                   // replace indent in first line with minimal number of
-                   // tabs and spaces, according to current options
-                   (void)set_indent(get_indent(), SIN_CHANGED);
- 
-               // put cursor on last non-space
-               State = NORMAL; // don't go past end-of-line
-               coladvance((colnr_T)MAXCOL);
-               while (curwin->w_cursor.col && vim_isspace(gchar_cursor()))
-                   dec_cursor();
- 
-               // do the formatting, without 'showmode'
-               State = INSERT; // for open_line()
-               smd_save = p_smd;
-               p_smd = FALSE;
-               insertchar(NUL, INSCHAR_FORMAT
-                       + (do_comments ? INSCHAR_DO_COM : 0)
-                       + (do_comments && do_comments_list
-                                                      ? INSCHAR_COM_LIST : 0)
-                       + (avoid_fex ? INSCHAR_NO_FEX : 0), second_indent);
-               State = old_State;
-               p_smd = smd_save;
-               second_indent = -1;
-               // at end of par.: need to set indent of next par.
-               need_set_indent = is_end_par;
-               if (is_end_par)
-               {
-                   // When called with a negative line count, break at the
-                   // end of the paragraph.
-                   if (line_count < 0)
-                       break;
-                   first_par_line = TRUE;
-               }
-               force_format = FALSE;
-           }
- 
-           /*
-            * When still in same paragraph, join the lines together.  But
-            * first delete the leader from the second line.
-            */
-           if (!is_end_par)
-           {
-               advance = FALSE;
-               curwin->w_cursor.lnum++;
-               curwin->w_cursor.col = 0;
-               if (line_count < 0 && u_save_cursor() == FAIL)
-                   break;
-               if (next_leader_len > 0)
-               {
-                   (void)del_bytes((long)next_leader_len, FALSE, FALSE);
-                   mark_col_adjust(curwin->w_cursor.lnum, (colnr_T)0, 0L,
-                                                   (long)-next_leader_len, 0);
-               }
-               else if (second_indent > 0)  // the "leader" for FO_Q_SECOND
-               {
-                   int indent = getwhitecols_curline();
- 
-                   if (indent > 0)
-                   {
-                       (void)del_bytes(indent, FALSE, FALSE);
-                       mark_col_adjust(curwin->w_cursor.lnum,
-                                              (colnr_T)0, 0L, (long)-indent, 
0);
-                   }
-               }
-               curwin->w_cursor.lnum--;
-               if (do_join(2, TRUE, FALSE, FALSE, FALSE) == FAIL)
-               {
-                   beep_flush();
-                   break;
-               }
-               first_par_line = FALSE;
-               // If the line is getting long, format it next time
-               if (STRLEN(ml_get_curline()) > (size_t)max_len)
-                   force_format = TRUE;
-               else
-                   force_format = FALSE;
-           }
-       }
-       line_breakcheck();
-     }
- }
- 
- /*
-  * Return TRUE if line "lnum" ends in a white character.
-  */
-     static int
- ends_in_white(linenr_T lnum)
- {
-     char_u    *s = ml_get(lnum);
-     size_t    l;
- 
-     if (*s == NUL)
-       return FALSE;
-     // Don't use STRLEN() inside VIM_ISWHITE(), SAS/C complains: "macro
-     // invocation may call function multiple times".
-     l = STRLEN(s) - 1;
-     return VIM_ISWHITE(s[l]);
- }
- 
- /*
-  * Blank lines, and lines containing only the comment leader, are left
-  * untouched by the formatting.  The function returns TRUE in this
-  * case.  It also returns TRUE when a line starts with the end of a comment
-  * ('e' in comment flags), so that this line is skipped, and not joined to the
-  * previous line.  A new paragraph starts after a blank line, or when the
-  * comment leader changes -- webb.
-  */
-     static int
- fmt_check_par(
-     linenr_T  lnum,
-     int               *leader_len,
-     char_u    **leader_flags,
-     int               do_comments)
- {
-     char_u    *flags = NULL;      // init for GCC
-     char_u    *ptr;
- 
-     ptr = ml_get(lnum);
-     if (do_comments)
-       *leader_len = get_leader_len(ptr, leader_flags, FALSE, TRUE);
-     else
-       *leader_len = 0;
- 
-     if (*leader_len > 0)
-     {
-       /*
-        * Search for 'e' flag in comment leader flags.
-        */
-       flags = *leader_flags;
-       while (*flags && *flags != ':' && *flags != COM_END)
-           ++flags;
-     }
- 
-     return (*skipwhite(ptr + *leader_len) == NUL
-           || (*leader_len > 0 && *flags == COM_END)
-           || startPS(lnum, NUL, FALSE));
- }
- 
- /*
-  * Return TRUE when a paragraph starts in line "lnum".  Return FALSE when the
-  * previous line is in the same paragraph.  Used for auto-formatting.
-  */
-     int
- paragraph_start(linenr_T lnum)
- {
-     char_u    *p;
-     int               leader_len = 0;         // leader len of current line
-     char_u    *leader_flags = NULL;   // flags for leader of current line
-     int               next_leader_len;        // leader len of next line
-     char_u    *next_leader_flags;     // flags for leader of next line
-     int               do_comments;            // format comments
- 
-     if (lnum <= 1)
-       return TRUE;            // start of the file
- 
-     p = ml_get(lnum - 1);
-     if (*p == NUL)
-       return TRUE;            // after empty line
- 
-     do_comments = has_format_option(FO_Q_COMS);
-     if (fmt_check_par(lnum - 1, &leader_len, &leader_flags, do_comments))
-       return TRUE;            // after non-paragraph line
- 
-     if (fmt_check_par(lnum, &next_leader_len, &next_leader_flags, 
do_comments))
-       return TRUE;            // "lnum" is not a paragraph line
- 
-     if (has_format_option(FO_WHITE_PAR) && !ends_in_white(lnum - 1))
-       return TRUE;            // missing trailing space in previous line.
- 
-     if (has_format_option(FO_Q_NUMBER) && (get_number_indent(lnum) > 0))
-       return TRUE;            // numbered item starts in "lnum".
- 
-     if (!same_leader(lnum - 1, leader_len, leader_flags,
-                                         next_leader_len, next_leader_flags))
-       return TRUE;            // change of comment leader.
- 
-     return FALSE;
- }
- 
- /*
   * prepare a few things for block mode yank/delete/tilde
   *
   * for delete:
--- 2129,2134 ----
*** ../vim-8.2.0673/src/option.c        2020-04-17 19:41:16.100078313 +0200
--- src/option.c        2020-05-01 14:23:34.749538404 +0200
***************
*** 6492,6509 ****
  }
  
  /*
-  * Return TRUE if format option 'x' is in effect.
-  * Take care of no formatting when 'paste' is set.
-  */
-     int
- has_format_option(int x)
- {
-     if (p_paste)
-       return FALSE;
-     return (vim_strchr(curbuf->b_p_fo, x) != NULL);
- }
- 
- /*
   * Return TRUE if "x" is present in 'shortmess' option, or
   * 'shortmess' contains 'a' and "x" is present in SHM_A.
   */
--- 6492,6497 ----
*** ../vim-8.2.0673/src/proto.h 2020-04-29 21:03:51.115170232 +0200
--- src/proto.h 2020-05-01 14:23:34.749538404 +0200
***************
*** 224,229 ****
--- 224,230 ----
  # endif
  # include "testing.pro"
  # include "textobject.pro"
+ # include "textformat.pro"
  # include "time.pro"
  # include "ui.pro"
  # include "undo.pro"
*** ../vim-8.2.0673/src/proto/edit.pro  2019-12-12 12:55:18.000000000 +0100
--- src/proto/edit.pro  2020-05-01 14:23:34.753538388 +0200
***************
*** 13,20 ****
  void backspace_until_column(int col);
  int get_literal(void);
  void insertchar(int c, int flags, int second_indent);
- void auto_format(int trailblank, int prev_line);
- int comp_textwidth(int ff);
  void start_arrow(pos_T *end_insert_pos);
  int stop_arrow(void);
  void set_last_insert(int c);
--- 13,18 ----
*** ../vim-8.2.0673/src/proto/getchar.pro       2020-04-05 18:56:02.233436590 
+0200
--- src/proto/getchar.pro       2020-05-01 14:23:34.753538388 +0200
***************
*** 19,24 ****
--- 19,25 ----
  void stuffReadbuffSpec(char_u *s);
  void stuffcharReadbuff(int c);
  void stuffnumReadbuff(long n);
+ void stuffescaped(char_u *arg, int literally);
  int start_redo(long count, int old_redo);
  int start_redo_ins(void);
  void stop_redo_ins(void);
*** ../vim-8.2.0673/src/proto/ops.pro   2020-03-24 21:41:38.027535418 +0100
--- src/proto/ops.pro   2020-05-01 14:23:34.753538388 +0200
***************
*** 5,11 ****
  int get_extra_op_char(int optype);
  void op_shift(oparg_T *oap, int curs_top, int amount);
  void shift_line(int left, int round, int amount, int call_changed_bytes);
- void stuffescaped(char_u *arg, int literally);
  int op_delete(oparg_T *oap);
  int op_replace(oparg_T *oap, int c);
  int swapchar(int op_type, pos_T *pos);
--- 5,10 ----
***************
*** 14,22 ****
  void adjust_cursor_eol(void);
  char_u *skip_comment(char_u *line, int process, int include_space, int 
*is_comment);
  int do_join(long count, int insert_space, int save_undo, int 
use_formatoptions, int setmark);
- int fex_format(linenr_T lnum, long count, int c);
- void format_lines(linenr_T line_count, int avoid_fex);
- int paragraph_start(linenr_T lnum);
  void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, int 
is_del);
  void op_addsub(oparg_T *oap, linenr_T Prenum1, int g_cmd);
  void clear_oparg(oparg_T *oap);
--- 13,18 ----
*** ../vim-8.2.0673/src/proto/option.pro        2020-01-18 15:53:15.950799342 
+0100
--- src/proto/option.pro        2020-05-01 14:23:34.753538388 +0200
***************
*** 62,68 ****
  void set_context_in_set_cmd(expand_T *xp, char_u *arg, int opt_flags);
  int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u 
***file);
  int ExpandOldSetting(int *num_file, char_u ***file);
- int has_format_option(int x);
  int shortmess(int x);
  void vimrc_found(char_u *fname, char_u *envname);
  void change_compatible(int on);
--- 62,67 ----
*** ../vim-8.2.0673/src/proto/textformat.pro    2020-05-01 14:25:12.237185004 
+0200
--- src/proto/textformat.pro    2020-05-01 14:23:34.753538388 +0200
***************
*** 0 ****
--- 1,11 ----
+ /* textformat.c */
+ int has_format_option(int x);
+ void internal_format(int textwidth, int second_indent, int flags, int 
format_only, int c);
+ void auto_format(int trailblank, int prev_line);
+ void check_auto_format(int);
+ int comp_textwidth(int ff);
+ void op_format(oparg_T *oap, int keep_cursor);
+ void op_formatexpr(oparg_T *oap);
+ int fex_format(linenr_T lnum, long count, int c);
+ void format_lines(linenr_T line_count, int avoid_fex);
+ /* vim: set ft=c : */
*** ../vim-8.2.0673/src/textformat.c    2020-05-01 14:25:12.241184990 +0200
--- src/textformat.c    2020-05-01 14:23:34.753538388 +0200
***************
*** 0 ****
--- 1,1088 ----
+ /* vi:set ts=8 sts=4 sw=4 noet:
+  *
+  * VIM - Vi IMproved  by Bram Moolenaar
+  *
+  * Do ":help uganda"  in Vim to read copying and usage conditions.
+  * Do ":help credits" in Vim to see a list of people who contributed.
+  * See README.txt for an overview of the Vim source code.
+  */
+ 
+ /*
+  * textformat.c: text formatting functions
+  */
+ 
+ #include "vim.h"
+ 
+ static int    did_add_space = FALSE;  // auto_format() added an extra space
+                                       // under the cursor
+ 
+ #define WHITECHAR(cc) (VIM_ISWHITE(cc) && (!enc_utf8 || 
!utf_iscomposing(utf_ptr2char(ml_get_cursor() + 1))))
+ 
+ /*
+  * Return TRUE if format option 'x' is in effect.
+  * Take care of no formatting when 'paste' is set.
+  */
+     int
+ has_format_option(int x)
+ {
+     if (p_paste)
+       return FALSE;
+     return (vim_strchr(curbuf->b_p_fo, x) != NULL);
+ }
+ 
+ /*
+  * Format text at the current insert position.
+  *
+  * If the INSCHAR_COM_LIST flag is present, then the value of second_indent
+  * will be the comment leader length sent to open_line().
+  */
+     void
+ internal_format(
+     int               textwidth,
+     int               second_indent,
+     int               flags,
+     int               format_only,
+     int               c) // character to be inserted (can be NUL)
+ {
+     int               cc;
+     int               save_char = NUL;
+     int               haveto_redraw = FALSE;
+     int               fo_ins_blank = has_format_option(FO_INS_BLANK);
+     int               fo_multibyte = has_format_option(FO_MBYTE_BREAK);
+     int               fo_white_par = has_format_option(FO_WHITE_PAR);
+     int               first_line = TRUE;
+     colnr_T   leader_len;
+     int               no_leader = FALSE;
+     int               do_comments = (flags & INSCHAR_DO_COM);
+ #ifdef FEAT_LINEBREAK
+     int               has_lbr = curwin->w_p_lbr;
+ 
+     // make sure win_lbr_chartabsize() counts correctly
+     curwin->w_p_lbr = FALSE;
+ #endif
+ 
+     // When 'ai' is off we don't want a space under the cursor to be
+     // deleted.  Replace it with an 'x' temporarily.
+     if (!curbuf->b_p_ai && !(State & VREPLACE_FLAG))
+     {
+       cc = gchar_cursor();
+       if (VIM_ISWHITE(cc))
+       {
+           save_char = cc;
+           pchar_cursor('x');
+       }
+     }
+ 
+     // Repeat breaking lines, until the current line is not too long.
+     while (!got_int)
+     {
+       int     startcol;               // Cursor column at entry
+       int     wantcol;                // column at textwidth border
+       int     foundcol;               // column for start of spaces
+       int     end_foundcol = 0;       // column for start of word
+       colnr_T len;
+       colnr_T virtcol;
+       int     orig_col = 0;
+       char_u  *saved_text = NULL;
+       colnr_T col;
+       colnr_T end_col;
+       int     wcc;                    // counter for whitespace chars
+ 
+       virtcol = get_nolist_virtcol()
+               + char2cells(c != NUL ? c : gchar_cursor());
+       if (virtcol <= (colnr_T)textwidth)
+           break;
+ 
+       if (no_leader)
+           do_comments = FALSE;
+       else if (!(flags & INSCHAR_FORMAT)
+                                      && has_format_option(FO_WRAP_COMS))
+           do_comments = TRUE;
+ 
+       // Don't break until after the comment leader
+       if (do_comments)
+           leader_len = get_leader_len(ml_get_curline(), NULL, FALSE, TRUE);
+       else
+           leader_len = 0;
+ 
+       // If the line doesn't start with a comment leader, then don't
+       // start one in a following broken line.  Avoids that a %word
+       // moved to the start of the next line causes all following lines
+       // to start with %.
+       if (leader_len == 0)
+           no_leader = TRUE;
+       if (!(flags & INSCHAR_FORMAT)
+               && leader_len == 0
+               && !has_format_option(FO_WRAP))
+ 
+           break;
+       if ((startcol = curwin->w_cursor.col) == 0)
+           break;
+ 
+       // find column of textwidth border
+       coladvance((colnr_T)textwidth);
+       wantcol = curwin->w_cursor.col;
+ 
+       curwin->w_cursor.col = startcol;
+       foundcol = 0;
+ 
+       // Find position to break at.
+       // Stop at first entered white when 'formatoptions' has 'v'
+       while ((!fo_ins_blank && !has_format_option(FO_INS_VI))
+                   || (flags & INSCHAR_FORMAT)
+                   || curwin->w_cursor.lnum != Insstart.lnum
+                   || curwin->w_cursor.col >= Insstart.col)
+       {
+           if (curwin->w_cursor.col == startcol && c != NUL)
+               cc = c;
+           else
+               cc = gchar_cursor();
+           if (WHITECHAR(cc))
+           {
+               // remember position of blank just before text
+               end_col = curwin->w_cursor.col;
+ 
+               // find start of sequence of blanks
+               wcc = 0;
+               while (curwin->w_cursor.col > 0 && WHITECHAR(cc))
+               {
+                   dec_cursor();
+                   cc = gchar_cursor();
+ 
+                   // Increment count of how many whitespace chars in this
+                   // group; we only need to know if it's more than one.
+                   if (wcc < 2)
+                       wcc++;
+               }
+               if (curwin->w_cursor.col == 0 && WHITECHAR(cc))
+                   break;              // only spaces in front of text
+ 
+               // Don't break after a period when 'formatoptions' has 'p' and
+               // there are less than two spaces.
+               if (has_format_option(FO_PERIOD_ABBR) && cc == '.' && wcc < 2)
+                   continue;
+ 
+               // Don't break until after the comment leader
+               if (curwin->w_cursor.col < leader_len)
+                   break;
+               if (has_format_option(FO_ONE_LETTER))
+               {
+                   // do not break after one-letter words
+                   if (curwin->w_cursor.col == 0)
+                       break;  // one-letter word at begin
+                   // do not break "#a b" when 'tw' is 2
+                   if (curwin->w_cursor.col <= leader_len)
+                       break;
+                   col = curwin->w_cursor.col;
+                   dec_cursor();
+                   cc = gchar_cursor();
+ 
+                   if (WHITECHAR(cc))
+                       continue;       // one-letter, continue
+                   curwin->w_cursor.col = col;
+               }
+ 
+               inc_cursor();
+ 
+               end_foundcol = end_col + 1;
+               foundcol = curwin->w_cursor.col;
+               if (curwin->w_cursor.col <= (colnr_T)wantcol)
+                   break;
+           }
+           else if (cc >= 0x100 && fo_multibyte)
+           {
+               // Break after or before a multi-byte character.
+               if (curwin->w_cursor.col != startcol)
+               {
+                   // Don't break until after the comment leader
+                   if (curwin->w_cursor.col < leader_len)
+                       break;
+                   col = curwin->w_cursor.col;
+                   inc_cursor();
+                   // Don't change end_foundcol if already set.
+                   if (foundcol != curwin->w_cursor.col)
+                   {
+                       foundcol = curwin->w_cursor.col;
+                       end_foundcol = foundcol;
+                       if (curwin->w_cursor.col <= (colnr_T)wantcol)
+                           break;
+                   }
+                   curwin->w_cursor.col = col;
+               }
+ 
+               if (curwin->w_cursor.col == 0)
+                   break;
+ 
+               col = curwin->w_cursor.col;
+ 
+               dec_cursor();
+               cc = gchar_cursor();
+ 
+               if (WHITECHAR(cc))
+                   continue;           // break with space
+               // Don't break until after the comment leader
+               if (curwin->w_cursor.col < leader_len)
+                   break;
+ 
+               curwin->w_cursor.col = col;
+ 
+               foundcol = curwin->w_cursor.col;
+               end_foundcol = foundcol;
+               if (curwin->w_cursor.col <= (colnr_T)wantcol)
+                   break;
+           }
+           if (curwin->w_cursor.col == 0)
+               break;
+           dec_cursor();
+       }
+ 
+       if (foundcol == 0)              // no spaces, cannot break line
+       {
+           curwin->w_cursor.col = startcol;
+           break;
+       }
+ 
+       // Going to break the line, remove any "$" now.
+       undisplay_dollar();
+ 
+       // Offset between cursor position and line break is used by replace
+       // stack functions.  VREPLACE does not use this, and backspaces
+       // over the text instead.
+       if (State & VREPLACE_FLAG)
+           orig_col = startcol;        // Will start backspacing from here
+       else
+           replace_offset = startcol - end_foundcol;
+ 
+       // adjust startcol for spaces that will be deleted and
+       // characters that will remain on top line
+       curwin->w_cursor.col = foundcol;
+       while ((cc = gchar_cursor(), WHITECHAR(cc))
+                   && (!fo_white_par || curwin->w_cursor.col < startcol))
+           inc_cursor();
+       startcol -= curwin->w_cursor.col;
+       if (startcol < 0)
+           startcol = 0;
+ 
+       if (State & VREPLACE_FLAG)
+       {
+           // In VREPLACE mode, we will backspace over the text to be
+           // wrapped, so save a copy now to put on the next line.
+           saved_text = vim_strsave(ml_get_cursor());
+           curwin->w_cursor.col = orig_col;
+           if (saved_text == NULL)
+               break;  // Can't do it, out of memory
+           saved_text[startcol] = NUL;
+ 
+           // Backspace over characters that will move to the next line
+           if (!fo_white_par)
+               backspace_until_column(foundcol);
+       }
+       else
+       {
+           // put cursor after pos. to break line
+           if (!fo_white_par)
+               curwin->w_cursor.col = foundcol;
+       }
+ 
+       // Split the line just before the margin.
+       // Only insert/delete lines, but don't really redraw the window.
+       open_line(FORWARD, OPENLINE_DELSPACES + OPENLINE_MARKFIX
+               + (fo_white_par ? OPENLINE_KEEPTRAIL : 0)
+               + (do_comments ? OPENLINE_DO_COM : 0)
+               + ((flags & INSCHAR_COM_LIST) ? OPENLINE_COM_LIST : 0)
+               , ((flags & INSCHAR_COM_LIST) ? second_indent : old_indent));
+       if (!(flags & INSCHAR_COM_LIST))
+           old_indent = 0;
+ 
+       replace_offset = 0;
+       if (first_line)
+       {
+           if (!(flags & INSCHAR_COM_LIST))
+           {
+               // This section is for auto-wrap of numeric lists.  When not
+               // in insert mode (i.e. format_lines()), the INSCHAR_COM_LIST
+               // flag will be set and open_line() will handle it (as seen
+               // above).  The code here (and in get_number_indent()) will
+               // recognize comments if needed...
+               if (second_indent < 0 && has_format_option(FO_Q_NUMBER))
+                   second_indent =
+                                get_number_indent(curwin->w_cursor.lnum - 1);
+               if (second_indent >= 0)
+               {
+                   if (State & VREPLACE_FLAG)
+                       change_indent(INDENT_SET, second_indent,
+                                                           FALSE, NUL, TRUE);
+                   else
+                       if (leader_len > 0 && second_indent - leader_len > 0)
+                   {
+                       int i;
+                       int padding = second_indent - leader_len;
+ 
+                       // We started at the first_line of a numbered list
+                       // that has a comment.  the open_line() function has
+                       // inserted the proper comment leader and positioned
+                       // the cursor at the end of the split line.  Now we
+                       // add the additional whitespace needed after the
+                       // comment leader for the numbered list.
+                       for (i = 0; i < padding; i++)
+                           ins_str((char_u *)" ");
+                   }
+                   else
+                   {
+                       (void)set_indent(second_indent, SIN_CHANGED);
+                   }
+               }
+           }
+           first_line = FALSE;
+       }
+ 
+       if (State & VREPLACE_FLAG)
+       {
+           // In VREPLACE mode we have backspaced over the text to be
+           // moved, now we re-insert it into the new line.
+           ins_bytes(saved_text);
+           vim_free(saved_text);
+       }
+       else
+       {
+           // Check if cursor is not past the NUL off the line, cindent
+           // may have added or removed indent.
+           curwin->w_cursor.col += startcol;
+           len = (colnr_T)STRLEN(ml_get_curline());
+           if (curwin->w_cursor.col > len)
+               curwin->w_cursor.col = len;
+       }
+ 
+       haveto_redraw = TRUE;
+ #ifdef FEAT_CINDENT
+       set_can_cindent(TRUE);
+ #endif
+       // moved the cursor, don't autoindent or cindent now
+       did_ai = FALSE;
+ #ifdef FEAT_SMARTINDENT
+       did_si = FALSE;
+       can_si = FALSE;
+       can_si_back = FALSE;
+ #endif
+       line_breakcheck();
+     }
+ 
+     if (save_char != NUL)             // put back space after cursor
+       pchar_cursor(save_char);
+ 
+ #ifdef FEAT_LINEBREAK
+     curwin->w_p_lbr = has_lbr;
+ #endif
+     if (!format_only && haveto_redraw)
+     {
+       update_topline();
+       redraw_curbuf_later(VALID);
+     }
+ }
+ 
+ /*
+  * Blank lines, and lines containing only the comment leader, are left
+  * untouched by the formatting.  The function returns TRUE in this
+  * case.  It also returns TRUE when a line starts with the end of a comment
+  * ('e' in comment flags), so that this line is skipped, and not joined to the
+  * previous line.  A new paragraph starts after a blank line, or when the
+  * comment leader changes -- webb.
+  */
+     static int
+ fmt_check_par(
+     linenr_T  lnum,
+     int               *leader_len,
+     char_u    **leader_flags,
+     int               do_comments)
+ {
+     char_u    *flags = NULL;      // init for GCC
+     char_u    *ptr;
+ 
+     ptr = ml_get(lnum);
+     if (do_comments)
+       *leader_len = get_leader_len(ptr, leader_flags, FALSE, TRUE);
+     else
+       *leader_len = 0;
+ 
+     if (*leader_len > 0)
+     {
+       // Search for 'e' flag in comment leader flags.
+       flags = *leader_flags;
+       while (*flags && *flags != ':' && *flags != COM_END)
+           ++flags;
+     }
+ 
+     return (*skipwhite(ptr + *leader_len) == NUL
+           || (*leader_len > 0 && *flags == COM_END)
+           || startPS(lnum, NUL, FALSE));
+ }
+ 
+ /*
+  * Return TRUE if line "lnum" ends in a white character.
+  */
+     static int
+ ends_in_white(linenr_T lnum)
+ {
+     char_u    *s = ml_get(lnum);
+     size_t    l;
+ 
+     if (*s == NUL)
+       return FALSE;
+     // Don't use STRLEN() inside VIM_ISWHITE(), SAS/C complains: "macro
+     // invocation may call function multiple times".
+     l = STRLEN(s) - 1;
+     return VIM_ISWHITE(s[l]);
+ }
+ 
+ /*
+  * Return TRUE if the two comment leaders given are the same.  "lnum" is
+  * the first line.  White-space is ignored.  Note that the whole of
+  * 'leader1' must match 'leader2_len' characters from 'leader2' -- webb
+  */
+     static int
+ same_leader(
+     linenr_T lnum,
+     int           leader1_len,
+     char_u  *leader1_flags,
+     int           leader2_len,
+     char_u  *leader2_flags)
+ {
+     int           idx1 = 0, idx2 = 0;
+     char_u  *p;
+     char_u  *line1;
+     char_u  *line2;
+ 
+     if (leader1_len == 0)
+       return (leader2_len == 0);
+ 
+     // If first leader has 'f' flag, the lines can be joined only if the
+     // second line does not have a leader.
+     // If first leader has 'e' flag, the lines can never be joined.
+     // If fist leader has 's' flag, the lines can only be joined if there is
+     // some text after it and the second line has the 'm' flag.
+     if (leader1_flags != NULL)
+     {
+       for (p = leader1_flags; *p && *p != ':'; ++p)
+       {
+           if (*p == COM_FIRST)
+               return (leader2_len == 0);
+           if (*p == COM_END)
+               return FALSE;
+           if (*p == COM_START)
+           {
+               if (*(ml_get(lnum) + leader1_len) == NUL)
+                   return FALSE;
+               if (leader2_flags == NULL || leader2_len == 0)
+                   return FALSE;
+               for (p = leader2_flags; *p && *p != ':'; ++p)
+                   if (*p == COM_MIDDLE)
+                       return TRUE;
+               return FALSE;
+           }
+       }
+     }
+ 
+     // Get current line and next line, compare the leaders.
+     // The first line has to be saved, only one line can be locked at a time.
+     line1 = vim_strsave(ml_get(lnum));
+     if (line1 != NULL)
+     {
+       for (idx1 = 0; VIM_ISWHITE(line1[idx1]); ++idx1)
+           ;
+       line2 = ml_get(lnum + 1);
+       for (idx2 = 0; idx2 < leader2_len; ++idx2)
+       {
+           if (!VIM_ISWHITE(line2[idx2]))
+           {
+               if (line1[idx1++] != line2[idx2])
+                   break;
+           }
+           else
+               while (VIM_ISWHITE(line1[idx1]))
+                   ++idx1;
+       }
+       vim_free(line1);
+     }
+     return (idx2 == leader2_len && idx1 == leader1_len);
+ }
+ 
+ /*
+  * Return TRUE when a paragraph starts in line "lnum".  Return FALSE when the
+  * previous line is in the same paragraph.  Used for auto-formatting.
+  */
+     static int
+ paragraph_start(linenr_T lnum)
+ {
+     char_u    *p;
+     int               leader_len = 0;         // leader len of current line
+     char_u    *leader_flags = NULL;   // flags for leader of current line
+     int               next_leader_len;        // leader len of next line
+     char_u    *next_leader_flags;     // flags for leader of next line
+     int               do_comments;            // format comments
+ 
+     if (lnum <= 1)
+       return TRUE;            // start of the file
+ 
+     p = ml_get(lnum - 1);
+     if (*p == NUL)
+       return TRUE;            // after empty line
+ 
+     do_comments = has_format_option(FO_Q_COMS);
+     if (fmt_check_par(lnum - 1, &leader_len, &leader_flags, do_comments))
+       return TRUE;            // after non-paragraph line
+ 
+     if (fmt_check_par(lnum, &next_leader_len, &next_leader_flags, 
do_comments))
+       return TRUE;            // "lnum" is not a paragraph line
+ 
+     if (has_format_option(FO_WHITE_PAR) && !ends_in_white(lnum - 1))
+       return TRUE;            // missing trailing space in previous line.
+ 
+     if (has_format_option(FO_Q_NUMBER) && (get_number_indent(lnum) > 0))
+       return TRUE;            // numbered item starts in "lnum".
+ 
+     if (!same_leader(lnum - 1, leader_len, leader_flags,
+                                         next_leader_len, next_leader_flags))
+       return TRUE;            // change of comment leader.
+ 
+     return FALSE;
+ }
+ 
+ /*
+  * Called after inserting or deleting text: When 'formatoptions' includes the
+  * 'a' flag format from the current line until the end of the paragraph.
+  * Keep the cursor at the same position relative to the text.
+  * The caller must have saved the cursor line for undo, following ones will be
+  * saved here.
+  */
+     void
+ auto_format(
+     int               trailblank,     // when TRUE also format with trailing 
blank
+     int               prev_line)      // may start in previous line
+ {
+     pos_T     pos;
+     colnr_T   len;
+     char_u    *old;
+     char_u    *new, *pnew;
+     int               wasatend;
+     int               cc;
+ 
+     if (!has_format_option(FO_AUTO))
+       return;
+ 
+     pos = curwin->w_cursor;
+     old = ml_get_curline();
+ 
+     // may remove added space
+     check_auto_format(FALSE);
+ 
+     // Don't format in Insert mode when the cursor is on a trailing blank, the
+     // user might insert normal text next.  Also skip formatting when "1" is
+     // in 'formatoptions' and there is a single character before the cursor.
+     // Otherwise the line would be broken and when typing another non-white
+     // next they are not joined back together.
+     wasatend = (pos.col == (colnr_T)STRLEN(old));
+     if (*old != NUL && !trailblank && wasatend)
+     {
+       dec_cursor();
+       cc = gchar_cursor();
+       if (!WHITECHAR(cc) && curwin->w_cursor.col > 0
+                                         && has_format_option(FO_ONE_LETTER))
+           dec_cursor();
+       cc = gchar_cursor();
+       if (WHITECHAR(cc))
+       {
+           curwin->w_cursor = pos;
+           return;
+       }
+       curwin->w_cursor = pos;
+     }
+ 
+     // With the 'c' flag in 'formatoptions' and 't' missing: only format
+     // comments.
+     if (has_format_option(FO_WRAP_COMS) && !has_format_option(FO_WRAP)
+                               && get_leader_len(old, NULL, FALSE, TRUE) == 0)
+       return;
+ 
+     // May start formatting in a previous line, so that after "x" a word is
+     // moved to the previous line if it fits there now.  Only when this is not
+     // the start of a paragraph.
+     if (prev_line && !paragraph_start(curwin->w_cursor.lnum))
+     {
+       --curwin->w_cursor.lnum;
+       if (u_save_cursor() == FAIL)
+           return;
+     }
+ 
+     // Do the formatting and restore the cursor position.  "saved_cursor" will
+     // be adjusted for the text formatting.
+     saved_cursor = pos;
+     format_lines((linenr_T)-1, FALSE);
+     curwin->w_cursor = saved_cursor;
+     saved_cursor.lnum = 0;
+ 
+     if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
+     {
+       // "cannot happen"
+       curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+       coladvance((colnr_T)MAXCOL);
+     }
+     else
+       check_cursor_col();
+ 
+     // Insert mode: If the cursor is now after the end of the line while it
+     // previously wasn't, the line was broken.  Because of the rule above we
+     // need to add a space when 'w' is in 'formatoptions' to keep a paragraph
+     // formatted.
+     if (!wasatend && has_format_option(FO_WHITE_PAR))
+     {
+       new = ml_get_curline();
+       len = (colnr_T)STRLEN(new);
+       if (curwin->w_cursor.col == len)
+       {
+           pnew = vim_strnsave(new, len + 2);
+           pnew[len] = ' ';
+           pnew[len + 1] = NUL;
+           ml_replace(curwin->w_cursor.lnum, pnew, FALSE);
+           // remove the space later
+           did_add_space = TRUE;
+       }
+       else
+           // may remove added space
+           check_auto_format(FALSE);
+     }
+ 
+     check_cursor();
+ }
+ 
+ /*
+  * When an extra space was added to continue a paragraph for auto-formatting,
+  * delete it now.  The space must be under the cursor, just after the insert
+  * position.
+  */
+     void
+ check_auto_format(
+     int               end_insert)         // TRUE when ending Insert mode
+ {
+     int               c = ' ';
+     int               cc;
+ 
+     if (did_add_space)
+     {
+       cc = gchar_cursor();
+       if (!WHITECHAR(cc))
+           // Somehow the space was removed already.
+           did_add_space = FALSE;
+       else
+       {
+           if (!end_insert)
+           {
+               inc_cursor();
+               c = gchar_cursor();
+               dec_cursor();
+           }
+           if (c != NUL)
+           {
+               // The space is no longer at the end of the line, delete it.
+               del_char(FALSE);
+               did_add_space = FALSE;
+           }
+       }
+     }
+ }
+ 
+ /*
+  * Find out textwidth to be used for formatting:
+  *    if 'textwidth' option is set, use it
+  *    else if 'wrapmargin' option is set, use curwin->w_width - 'wrapmargin'
+  *    if invalid value, use 0.
+  *    Set default to window width (maximum 79) for "gq" operator.
+  */
+     int
+ comp_textwidth(
+     int               ff)     // force formatting (for "gq" command)
+ {
+     int               textwidth;
+ 
+     textwidth = curbuf->b_p_tw;
+     if (textwidth == 0 && curbuf->b_p_wm)
+     {
+       // The width is the window width minus 'wrapmargin' minus all the
+       // things that add to the margin.
+       textwidth = curwin->w_width - curbuf->b_p_wm;
+ #ifdef FEAT_CMDWIN
+       if (cmdwin_type != 0)
+           textwidth -= 1;
+ #endif
+ #ifdef FEAT_FOLDING
+       textwidth -= curwin->w_p_fdc;
+ #endif
+ #ifdef FEAT_SIGNS
+       if (signcolumn_on(curwin))
+           textwidth -= 1;
+ #endif
+       if (curwin->w_p_nu || curwin->w_p_rnu)
+           textwidth -= 8;
+     }
+     if (textwidth < 0)
+       textwidth = 0;
+     if (ff && textwidth == 0)
+     {
+       textwidth = curwin->w_width - 1;
+       if (textwidth > 79)
+           textwidth = 79;
+     }
+     return textwidth;
+ }
+ 
+ /*
+  * Implementation of the format operator 'gq'.
+  */
+     void
+ op_format(
+     oparg_T   *oap,
+     int               keep_cursor)            // keep cursor on same text char
+ {
+     long      old_line_count = curbuf->b_ml.ml_line_count;
+ 
+     // Place the cursor where the "gq" or "gw" command was given, so that "u"
+     // can put it back there.
+     curwin->w_cursor = oap->cursor_start;
+ 
+     if (u_save((linenr_T)(oap->start.lnum - 1),
+                                      (linenr_T)(oap->end.lnum + 1)) == FAIL)
+       return;
+     curwin->w_cursor = oap->start;
+ 
+     if (oap->is_VIsual)
+       // When there is no change: need to remove the Visual selection
+       redraw_curbuf_later(INVERTED);
+ 
+     if (!cmdmod.lockmarks)
+       // Set '[ mark at the start of the formatted area
+       curbuf->b_op_start = oap->start;
+ 
+     // For "gw" remember the cursor position and put it back below (adjusted
+     // for joined and split lines).
+     if (keep_cursor)
+       saved_cursor = oap->cursor_start;
+ 
+     format_lines(oap->line_count, keep_cursor);
+ 
+     // Leave the cursor at the first non-blank of the last formatted line.
+     // If the cursor was moved one line back (e.g. with "Q}") go to the next
+     // line, so "." will do the next lines.
+     if (oap->end_adjusted && curwin->w_cursor.lnum < 
curbuf->b_ml.ml_line_count)
+       ++curwin->w_cursor.lnum;
+     beginline(BL_WHITE | BL_FIX);
+     old_line_count = curbuf->b_ml.ml_line_count - old_line_count;
+     msgmore(old_line_count);
+ 
+     if (!cmdmod.lockmarks)
+       // put '] mark on the end of the formatted area
+       curbuf->b_op_end = curwin->w_cursor;
+ 
+     if (keep_cursor)
+     {
+       curwin->w_cursor = saved_cursor;
+       saved_cursor.lnum = 0;
+     }
+ 
+     if (oap->is_VIsual)
+     {
+       win_T   *wp;
+ 
+       FOR_ALL_WINDOWS(wp)
+       {
+           if (wp->w_old_cursor_lnum != 0)
+           {
+               // When lines have been inserted or deleted, adjust the end of
+               // the Visual area to be redrawn.
+               if (wp->w_old_cursor_lnum > wp->w_old_visual_lnum)
+                   wp->w_old_cursor_lnum += old_line_count;
+               else
+                   wp->w_old_visual_lnum += old_line_count;
+           }
+       }
+     }
+ }
+ 
+ #if defined(FEAT_EVAL) || defined(PROTO)
+ /*
+  * Implementation of the format operator 'gq' for when using 'formatexpr'.
+  */
+     void
+ op_formatexpr(oparg_T *oap)
+ {
+     if (oap->is_VIsual)
+       // When there is no change: need to remove the Visual selection
+       redraw_curbuf_later(INVERTED);
+ 
+     if (fex_format(oap->start.lnum, oap->line_count, NUL) != 0)
+       // As documented: when 'formatexpr' returns non-zero fall back to
+       // internal formatting.
+       op_format(oap, FALSE);
+ }
+ 
+     int
+ fex_format(
+     linenr_T  lnum,
+     long      count,
+     int               c)      // character to be inserted
+ {
+     int               use_sandbox = was_set_insecurely((char_u *)"formatexpr",
+                                                                  OPT_LOCAL);
+     int               r;
+     char_u    *fex;
+ 
+     // Set v:lnum to the first line number and v:count to the number of lines.
+     // Set v:char to the character to be inserted (can be NUL).
+     set_vim_var_nr(VV_LNUM, lnum);
+     set_vim_var_nr(VV_COUNT, count);
+     set_vim_var_char(c);
+ 
+     // Make a copy, the option could be changed while calling it.
+     fex = vim_strsave(curbuf->b_p_fex);
+     if (fex == NULL)
+       return 0;
+ 
+     // Evaluate the function.
+     if (use_sandbox)
+       ++sandbox;
+     r = (int)eval_to_number(fex);
+     if (use_sandbox)
+       --sandbox;
+ 
+     set_vim_var_string(VV_CHAR, NULL, -1);
+     vim_free(fex);
+ 
+     return r;
+ }
+ #endif
+ 
+ /*
+  * Format "line_count" lines, starting at the cursor position.
+  * When "line_count" is negative, format until the end of the paragraph.
+  * Lines after the cursor line are saved for undo, caller must have saved the
+  * first line.
+  */
+     void
+ format_lines(
+     linenr_T  line_count,
+     int               avoid_fex)              // don't use 'formatexpr'
+ {
+     int               max_len;
+     int               is_not_par;             // current line not part of 
parag.
+     int               next_is_not_par;        // next line not part of 
paragraph
+     int               is_end_par;             // at end of paragraph
+     int               prev_is_end_par = FALSE;// prev. line not part of parag.
+     int               next_is_start_par = FALSE;
+     int               leader_len = 0;         // leader len of current line
+     int               next_leader_len;        // leader len of next line
+     char_u    *leader_flags = NULL;   // flags for leader of current line
+     char_u    *next_leader_flags;     // flags for leader of next line
+     int               do_comments;            // format comments
+     int               do_comments_list = 0;   // format comments with 'n' or 
'2'
+     int               advance = TRUE;
+     int               second_indent = -1;     // indent for second line 
(comment
+                                       // aware)
+     int               do_second_indent;
+     int               do_number_indent;
+     int               do_trail_white;
+     int               first_par_line = TRUE;
+     int               smd_save;
+     long      count;
+     int               need_set_indent = TRUE; // set indent of next paragraph
+     int               force_format = FALSE;
+     int               old_State = State;
+ 
+     // length of a line to force formatting: 3 * 'tw'
+     max_len = comp_textwidth(TRUE) * 3;
+ 
+     // check for 'q', '2' and '1' in 'formatoptions'
+     do_comments = has_format_option(FO_Q_COMS);
+     do_second_indent = has_format_option(FO_Q_SECOND);
+     do_number_indent = has_format_option(FO_Q_NUMBER);
+     do_trail_white = has_format_option(FO_WHITE_PAR);
+ 
+     // Get info about the previous and current line.
+     if (curwin->w_cursor.lnum > 1)
+       is_not_par = fmt_check_par(curwin->w_cursor.lnum - 1
+                               , &leader_len, &leader_flags, do_comments);
+     else
+       is_not_par = TRUE;
+     next_is_not_par = fmt_check_par(curwin->w_cursor.lnum
+                         , &next_leader_len, &next_leader_flags, do_comments);
+     is_end_par = (is_not_par || next_is_not_par);
+     if (!is_end_par && do_trail_white)
+       is_end_par = !ends_in_white(curwin->w_cursor.lnum - 1);
+ 
+     curwin->w_cursor.lnum--;
+     for (count = line_count; count != 0 && !got_int; --count)
+     {
+       // Advance to next paragraph.
+       if (advance)
+       {
+           curwin->w_cursor.lnum++;
+           prev_is_end_par = is_end_par;
+           is_not_par = next_is_not_par;
+           leader_len = next_leader_len;
+           leader_flags = next_leader_flags;
+       }
+ 
+       // The last line to be formatted.
+       if (count == 1 || curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)
+       {
+           next_is_not_par = TRUE;
+           next_leader_len = 0;
+           next_leader_flags = NULL;
+       }
+       else
+       {
+           next_is_not_par = fmt_check_par(curwin->w_cursor.lnum + 1
+                         , &next_leader_len, &next_leader_flags, do_comments);
+           if (do_number_indent)
+               next_is_start_par =
+                          (get_number_indent(curwin->w_cursor.lnum + 1) > 0);
+       }
+       advance = TRUE;
+       is_end_par = (is_not_par || next_is_not_par || next_is_start_par);
+       if (!is_end_par && do_trail_white)
+           is_end_par = !ends_in_white(curwin->w_cursor.lnum);
+ 
+       // Skip lines that are not in a paragraph.
+       if (is_not_par)
+       {
+           if (line_count < 0)
+               break;
+       }
+       else
+       {
+           // For the first line of a paragraph, check indent of second line.
+           // Don't do this for comments and empty lines.
+           if (first_par_line
+                   && (do_second_indent || do_number_indent)
+                   && prev_is_end_par
+                   && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
+           {
+               if (do_second_indent && !LINEEMPTY(curwin->w_cursor.lnum + 1))
+               {
+                   if (leader_len == 0 && next_leader_len == 0)
+                   {
+                       // no comment found
+                       second_indent =
+                                  get_indent_lnum(curwin->w_cursor.lnum + 1);
+                   }
+                   else
+                   {
+                       second_indent = next_leader_len;
+                       do_comments_list = 1;
+                   }
+               }
+               else if (do_number_indent)
+               {
+                   if (leader_len == 0 && next_leader_len == 0)
+                   {
+                       // no comment found
+                       second_indent =
+                                    get_number_indent(curwin->w_cursor.lnum);
+                   }
+                   else
+                   {
+                       // get_number_indent() is now "comment aware"...
+                       second_indent =
+                                    get_number_indent(curwin->w_cursor.lnum);
+                       do_comments_list = 1;
+                   }
+               }
+           }
+ 
+           // When the comment leader changes, it's the end of the paragraph.
+           if (curwin->w_cursor.lnum >= curbuf->b_ml.ml_line_count
+                   || !same_leader(curwin->w_cursor.lnum,
+                                       leader_len, leader_flags,
+                                          next_leader_len, next_leader_flags))
+               is_end_par = TRUE;
+ 
+           // If we have got to the end of a paragraph, or the line is
+           // getting long, format it.
+           if (is_end_par || force_format)
+           {
+               if (need_set_indent)
+                   // replace indent in first line with minimal number of
+                   // tabs and spaces, according to current options
+                   (void)set_indent(get_indent(), SIN_CHANGED);
+ 
+               // put cursor on last non-space
+               State = NORMAL; // don't go past end-of-line
+               coladvance((colnr_T)MAXCOL);
+               while (curwin->w_cursor.col && vim_isspace(gchar_cursor()))
+                   dec_cursor();
+ 
+               // do the formatting, without 'showmode'
+               State = INSERT; // for open_line()
+               smd_save = p_smd;
+               p_smd = FALSE;
+               insertchar(NUL, INSCHAR_FORMAT
+                       + (do_comments ? INSCHAR_DO_COM : 0)
+                       + (do_comments && do_comments_list
+                                                      ? INSCHAR_COM_LIST : 0)
+                       + (avoid_fex ? INSCHAR_NO_FEX : 0), second_indent);
+               State = old_State;
+               p_smd = smd_save;
+               second_indent = -1;
+               // at end of par.: need to set indent of next par.
+               need_set_indent = is_end_par;
+               if (is_end_par)
+               {
+                   // When called with a negative line count, break at the
+                   // end of the paragraph.
+                   if (line_count < 0)
+                       break;
+                   first_par_line = TRUE;
+               }
+               force_format = FALSE;
+           }
+ 
+           // When still in same paragraph, join the lines together.  But
+           // first delete the leader from the second line.
+           if (!is_end_par)
+           {
+               advance = FALSE;
+               curwin->w_cursor.lnum++;
+               curwin->w_cursor.col = 0;
+               if (line_count < 0 && u_save_cursor() == FAIL)
+                   break;
+               if (next_leader_len > 0)
+               {
+                   (void)del_bytes((long)next_leader_len, FALSE, FALSE);
+                   mark_col_adjust(curwin->w_cursor.lnum, (colnr_T)0, 0L,
+                                                   (long)-next_leader_len, 0);
+               }
+               else if (second_indent > 0)  // the "leader" for FO_Q_SECOND
+               {
+                   int indent = getwhitecols_curline();
+ 
+                   if (indent > 0)
+                   {
+                       (void)del_bytes(indent, FALSE, FALSE);
+                       mark_col_adjust(curwin->w_cursor.lnum,
+                                              (colnr_T)0, 0L, (long)-indent, 
0);
+                   }
+               }
+               curwin->w_cursor.lnum--;
+               if (do_join(2, TRUE, FALSE, FALSE, FALSE) == FAIL)
+               {
+                   beep_flush();
+                   break;
+               }
+               first_par_line = FALSE;
+               // If the line is getting long, format it next time
+               if (STRLEN(ml_get_curline()) > (size_t)max_len)
+                   force_format = TRUE;
+               else
+                   force_format = FALSE;
+           }
+       }
+       line_breakcheck();
+     }
+ }
*** ../vim-8.2.0673/src/version.c       2020-05-01 14:14:04.359578294 +0200
--- src/version.c       2020-05-01 14:22:33.609759588 +0200
***************
*** 748,749 ****
--- 748,751 ----
  {   /* Add new patch number below this line */
+ /**/
+     674,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
34. You laugh at people with a 10 Mbit connection.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202005011227.041CR3SH025798%40masaka.moolenaar.net.

Raspunde prin e-mail lui