Patch 9.0.1245
Problem:    Code is indented more than necessary.
Solution:   Use an early return where it makes sense. (Yegappan Lakshmanan,
            closes #11879)
Files:      src/tag.c, src/term.c, src/terminal.c, src/testing.c,
            src/textformat.c, src/textprop.c, src/time.c, src/typval.c


*** ../vim-9.0.1244/src/tag.c   2022-11-23 11:23:14.539539089 +0000
--- src/tag.c   2023-01-25 21:02:57.831082028 +0000
***************
*** 3263,3278 ****
      static void
  found_tagfile_cb(char_u *fname, void *cookie UNUSED)
  {
!     if (ga_grow(&tag_fnames, 1) == OK)
!     {
!       char_u  *tag_fname = vim_strsave(fname);
  
  #ifdef BACKSLASH_IN_FILENAME
!       slash_adjust(tag_fname);
  #endif
!       simplify_filename(tag_fname);
!       ((char_u **)(tag_fnames.ga_data))[tag_fnames.ga_len++] = tag_fname;
!     }
  }
  
  #if defined(EXITFREE) || defined(PROTO)
--- 3263,3278 ----
      static void
  found_tagfile_cb(char_u *fname, void *cookie UNUSED)
  {
!     if (ga_grow(&tag_fnames, 1) == FAIL)
!       return;
! 
!     char_u    *tag_fname = vim_strsave(fname);
  
  #ifdef BACKSLASH_IN_FILENAME
!     slash_adjust(tag_fname);
  #endif
!     simplify_filename(tag_fname);
!     ((char_u **)(tag_fnames.ga_data))[tag_fnames.ga_len++] = tag_fname;
  }
  
  #if defined(EXITFREE) || defined(PROTO)
***************
*** 3587,3640 ****
      tagp->tagline = 0;
      tagp->command_end = NULL;
  
!     if (retval == OK)
      {
!       // Try to find a kind field: "kind:<kind>" or just "<kind>"
!       p = tagp->command;
!       if (find_extra(&p) == OK)
!       {
!           if (p > tagp->command && p[-1] == '|')
!               tagp->command_end = p - 1;  // drop trailing bar
!           else
!               tagp->command_end = p;
!           p += 2;     // skip ";\""
!           if (*p++ == TAB)
!               // Accept ASCII alphabetic kind characters and any multi-byte
!               // character.
!               while (ASCII_ISALPHA(*p) || mb_ptr2len(p) > 1)
!               {
!                   if (STRNCMP(p, "kind:", 5) == 0)
!                       tagp->tagkind = p + 5;
!                   else if (STRNCMP(p, "user_data:", 10) == 0)
!                       tagp->user_data = p + 10;
!                   else if (STRNCMP(p, "line:", 5) == 0)
!                       tagp->tagline = atoi((char *)p + 5);
!                   if (tagp->tagkind != NULL && tagp->user_data != NULL)
!                       break;
!                   pc = vim_strchr(p, ':');
!                   pt = vim_strchr(p, '\t');
!                   if (pc == NULL || (pt != NULL && pc > pt))
!                       tagp->tagkind = p;
!                   if (pt == NULL)
!                       break;
!                   p = pt;
!                   MB_PTR_ADV(p);
!               }
!       }
!       if (tagp->tagkind != NULL)
!       {
!           for (p = tagp->tagkind;
!                           *p && *p != '\t' && *p != '\r' && *p != '\n'; 
MB_PTR_ADV(p))
!               ;
!           tagp->tagkind_end = p;
!       }
!       if (tagp->user_data != NULL)
!       {
!           for (p = tagp->user_data;
!                           *p && *p != '\t' && *p != '\r' && *p != '\n'; 
MB_PTR_ADV(p))
!               ;
!           tagp->user_data_end = p;
!       }
      }
      return retval;
  }
--- 3587,3640 ----
      tagp->tagline = 0;
      tagp->command_end = NULL;
  
!     if (retval != OK)
!       return retval;
! 
!     // Try to find a kind field: "kind:<kind>" or just "<kind>"
!     p = tagp->command;
!     if (find_extra(&p) == OK)
      {
!       if (p > tagp->command && p[-1] == '|')
!           tagp->command_end = p - 1;  // drop trailing bar
!       else
!           tagp->command_end = p;
!       p += 2; // skip ";\""
!       if (*p++ == TAB)
!           // Accept ASCII alphabetic kind characters and any multi-byte
!           // character.
!           while (ASCII_ISALPHA(*p) || mb_ptr2len(p) > 1)
!           {
!               if (STRNCMP(p, "kind:", 5) == 0)
!                   tagp->tagkind = p + 5;
!               else if (STRNCMP(p, "user_data:", 10) == 0)
!                   tagp->user_data = p + 10;
!               else if (STRNCMP(p, "line:", 5) == 0)
!                   tagp->tagline = atoi((char *)p + 5);
!               if (tagp->tagkind != NULL && tagp->user_data != NULL)
!                   break;
!               pc = vim_strchr(p, ':');
!               pt = vim_strchr(p, '\t');
!               if (pc == NULL || (pt != NULL && pc > pt))
!                   tagp->tagkind = p;
!               if (pt == NULL)
!                   break;
!               p = pt;
!               MB_PTR_ADV(p);
!           }
!     }
!     if (tagp->tagkind != NULL)
!     {
!       for (p = tagp->tagkind;
!               *p && *p != '\t' && *p != '\r' && *p != '\n'; MB_PTR_ADV(p))
!           ;
!       tagp->tagkind_end = p;
!     }
!     if (tagp->user_data != NULL)
!     {
!       for (p = tagp->user_data;
!               *p && *p != '\t' && *p != '\r' && *p != '\n'; MB_PTR_ADV(p))
!           ;
!       tagp->user_data_end = p;
      }
      return retval;
  }
***************
*** 4372,4465 ****
  
      ret = find_tags(pat, &num_matches, &matches,
                                TAG_REGEXP | TAG_NOIC, (int)MAXCOL, buf_fname);
!     if (ret == OK && num_matches > 0)
      {
!       for (i = 0; i < num_matches; ++i)
        {
!           if (parse_match(matches[i], &tp) == FAIL)
!           {
!               vim_free(matches[i]);
!               continue;
!           }
  
!           is_static = test_for_static(&tp);
  
!           // Skip pseudo-tag lines.
!           if (STRNCMP(tp.tagname, "!_TAG_", 6) == 0)
!           {
!               vim_free(matches[i]);
!               continue;
!           }
  
!           if ((dict = dict_alloc()) == NULL)
!           {
!               ret = FAIL;
!               vim_free(matches[i]);
!               break;
!           }
!           if (list_append_dict(list, dict) == FAIL)
!               ret = FAIL;
  
!           full_fname = tag_full_fname(&tp);
!           if (add_tag_field(dict, "name", tp.tagname, tp.tagname_end) == FAIL
!                   || add_tag_field(dict, "filename", full_fname,
!                                                        NULL) == FAIL
!                   || add_tag_field(dict, "cmd", tp.command,
!                                                      tp.command_end) == FAIL
!                   || add_tag_field(dict, "kind", tp.tagkind,
!                                                     tp.tagkind_end) == FAIL
!                   || dict_add_number(dict, "static", is_static) == FAIL)
!               ret = FAIL;
  
!           vim_free(full_fname);
  
!           if (tp.command_end != NULL)
            {
!               for (p = tp.command_end + 3;
!                         *p != NUL && *p != '\n' && *p != '\r'; MB_PTR_ADV(p))
                {
!                   if (p == tp.tagkind || (p + 5 == tp.tagkind
!                                             && STRNCMP(p, "kind:", 5) == 0))
!                       // skip "kind:<kind>" and "<kind>"
!                       p = tp.tagkind_end - 1;
!                   else if (STRNCMP(p, "file:", 5) == 0)
!                       // skip "file:" (static tag)
!                       p += 4;
!                   else if (!VIM_ISWHITE(*p))
!                   {
!                       char_u  *s, *n;
!                       int     len;
  
!                       // Add extra field as a dict entry.  Fields are
!                       // separated by Tabs.
!                       n = p;
!                       while (*p != NUL && *p >= ' ' && *p < 127 && *p != ':')
                            ++p;
!                       len = (int)(p - n);
!                       if (*p == ':' && len > 0)
!                       {
!                           s = ++p;
!                           while (*p != NUL && *p >= ' ')
!                               ++p;
!                           n[len] = NUL;
!                           if (add_tag_field(dict, (char *)n, s, p) == FAIL)
!                               ret = FAIL;
!                           n[len] = ':';
!                       }
!                       else
!                           // Skip field without colon.
!                           while (*p != NUL && *p >= ' ')
!                               ++p;
!                       if (*p == NUL)
!                           break;
                    }
                }
            }
- 
-           vim_free(matches[i]);
        }
!       vim_free(matches);
      }
      return ret;
  }
  
--- 4372,4465 ----
  
      ret = find_tags(pat, &num_matches, &matches,
                                TAG_REGEXP | TAG_NOIC, (int)MAXCOL, buf_fname);
!     if (ret != OK || num_matches <= 0)
!       return ret;
! 
!     for (i = 0; i < num_matches; ++i)
      {
!       if (parse_match(matches[i], &tp) == FAIL)
        {
!           vim_free(matches[i]);
!           continue;
!       }
  
!       is_static = test_for_static(&tp);
  
!       // Skip pseudo-tag lines.
!       if (STRNCMP(tp.tagname, "!_TAG_", 6) == 0)
!       {
!           vim_free(matches[i]);
!           continue;
!       }
  
!       if ((dict = dict_alloc()) == NULL)
!       {
!           ret = FAIL;
!           vim_free(matches[i]);
!           break;
!       }
!       if (list_append_dict(list, dict) == FAIL)
!           ret = FAIL;
  
!       full_fname = tag_full_fname(&tp);
!       if (add_tag_field(dict, "name", tp.tagname, tp.tagname_end) == FAIL
!               || add_tag_field(dict, "filename", full_fname,
!                   NULL) == FAIL
!               || add_tag_field(dict, "cmd", tp.command,
!                   tp.command_end) == FAIL
!               || add_tag_field(dict, "kind", tp.tagkind,
!                   tp.tagkind_end) == FAIL
!               || dict_add_number(dict, "static", is_static) == FAIL)
!           ret = FAIL;
  
!       vim_free(full_fname);
  
!       if (tp.command_end != NULL)
!       {
!           for (p = tp.command_end + 3;
!                   *p != NUL && *p != '\n' && *p != '\r'; MB_PTR_ADV(p))
            {
!               if (p == tp.tagkind || (p + 5 == tp.tagkind
!                           && STRNCMP(p, "kind:", 5) == 0))
!                   // skip "kind:<kind>" and "<kind>"
!                   p = tp.tagkind_end - 1;
!               else if (STRNCMP(p, "file:", 5) == 0)
!                   // skip "file:" (static tag)
!                   p += 4;
!               else if (!VIM_ISWHITE(*p))
                {
!                   char_u      *s, *n;
!                   int len;
  
!                   // Add extra field as a dict entry.  Fields are
!                   // separated by Tabs.
!                   n = p;
!                   while (*p != NUL && *p >= ' ' && *p < 127 && *p != ':')
!                       ++p;
!                   len = (int)(p - n);
!                   if (*p == ':' && len > 0)
!                   {
!                       s = ++p;
!                       while (*p != NUL && *p >= ' ')
                            ++p;
!                       n[len] = NUL;
!                       if (add_tag_field(dict, (char *)n, s, p) == FAIL)
!                           ret = FAIL;
!                       n[len] = ':';
                    }
+                   else
+                       // Skip field without colon.
+                       while (*p != NUL && *p >= ' ')
+                           ++p;
+                   if (*p == NUL)
+                       break;
                }
            }
        }
! 
!       vim_free(matches[i]);
      }
+     vim_free(matches);
      return ret;
  }
  
*** ../vim-9.0.1244/src/term.c  2023-01-23 12:33:15.826715782 +0000
--- src/term.c  2023-01-25 21:02:57.831082028 +0000
***************
*** 1644,1667 ****
      static void
  may_adjust_color_count(int val)
  {
!     if (val != t_colors)
!     {
!       // Nr of colors changed, initialize highlighting and redraw everything.
!       // This causes a redraw, which usually clears the message.  Try keeping
!       // the message if it might work.
!       set_keep_msg_from_hist();
!       set_color_count(val);
!       init_highlight(TRUE, FALSE);
  #ifdef DEBUG_TERMRESPONSE
!       {
!           int r = redraw_asap(UPD_CLEAR);
  
!           log_tr("Received t_Co, redraw_asap(): %d", r);
!       }
  #else
!       redraw_asap(UPD_CLEAR);
  #endif
-     }
  }
  
  #ifdef HAVE_TGETENT
--- 1644,1667 ----
      static void
  may_adjust_color_count(int val)
  {
!     if (val == t_colors)
!       return;
! 
!     // Nr of colors changed, initialize highlighting and redraw everything.
!     // This causes a redraw, which usually clears the message.  Try keeping
!     // the message if it might work.
!     set_keep_msg_from_hist();
!     set_color_count(val);
!     init_highlight(TRUE, FALSE);
  #ifdef DEBUG_TERMRESPONSE
!     {
!       int r = redraw_asap(UPD_CLEAR);
  
!       log_tr("Received t_Co, redraw_asap(): %d", r);
!     }
  #else
!     redraw_asap(UPD_CLEAR);
  #endif
  }
  
  #ifdef HAVE_TGETENT
***************
*** 2419,2431 ****
  {
      char_u    tbuf[TBUFSZ];
  
!     if (T_NAME != NULL && *T_NAME != NUL && invoke_tgetent(tbuf, T_NAME) == 
NULL)
!     {
!       if (*cp == 0)
!           *cp = tgetnum("co");
!       if (*rp == 0)
!           *rp = tgetnum("li");
!     }
  }
  #endif // defined(HAVE_TGETENT) && defined(UNIX)
  
--- 2419,2432 ----
  {
      char_u    tbuf[TBUFSZ];
  
!     if (T_NAME == NULL || *T_NAME == NUL
!           || invoke_tgetent(tbuf, T_NAME) != NULL)
!       return;
! 
!     if (*cp == 0)
!       *cp = tgetnum("co");
!     if (*rp == 0)
!       *rp = tgetnum("li");
  }
  #endif // defined(HAVE_TGETENT) && defined(UNIX)
  
***************
*** 2569,2583 ****
      static int
  term_7to8bit(char_u *p)
  {
!     if (*p == ESC)
!     {
!       if (p[1] == '[')
!           return CSI;
!       if (p[1] == ']')
!           return OSC;
!       if (p[1] == 'O')
!           return 0x8f;
!     }
      return 0;
  }
  
--- 2570,2584 ----
      static int
  term_7to8bit(char_u *p)
  {
!     if (*p != ESC)
!       return 0;
! 
!     if (p[1] == '[')
!       return CSI;
!     else if (p[1] == ']')
!       return OSC;
!     else if (p[1] == 'O')
!       return 0x8f;
      return 0;
  }
  
***************
*** 2712,2738 ****
  {
      int           len;
  
!     if (out_pos != 0)
!     {
!       // set out_pos to 0 before ui_write, to avoid recursiveness
!       len = out_pos;
!       out_pos = 0;
!       ui_write(out_buf, len, FALSE);
  #ifdef FEAT_EVAL
!       if (ch_log_output != FALSE)
!       {
!           out_buf[len] = NUL;
!           ch_log(NULL, "raw %s output: \"%s\"",
  # ifdef FEAT_GUI
!                       (gui.in_use && !gui.dying && !gui.starting) ? "GUI" :
  # endif
!                       "terminal",
!                       out_buf);
!           if (ch_log_output == TRUE)
!               ch_log_output = FALSE;  // only log once
!       }
! #endif
      }
  }
  
  /*
--- 2713,2739 ----
  {
      int           len;
  
!     if (out_pos == 0)
!       return;
! 
!     // set out_pos to 0 before ui_write, to avoid recursiveness
!     len = out_pos;
!     out_pos = 0;
!     ui_write(out_buf, len, FALSE);
  #ifdef FEAT_EVAL
!     if (ch_log_output != FALSE)
!     {
!       out_buf[len] = NUL;
!       ch_log(NULL, "raw %s output: \"%s\"",
  # ifdef FEAT_GUI
!               (gui.in_use && !gui.dying && !gui.starting) ? "GUI" :
  # endif
!               "terminal",
!               out_buf);
!       if (ch_log_output == TRUE)
!           ch_log_output = FALSE;  // only log once
      }
+ #endif
  }
  
  /*
***************
*** 2846,2911 ****
      void
  out_str_cf(char_u *s)
  {
!     if (s != NULL && *s)
!     {
  #ifdef HAVE_TGETENT
!       char_u *p;
  #endif
  
  #ifdef FEAT_GUI
!       // Don't use tputs() when GUI is used, ncurses crashes.
!       if (gui.in_use)
!       {
!           out_str_nf(s);
!           return;
!       }
  #endif
!       if (out_pos > OUT_SIZE - MAX_ESC_SEQ_LEN)
!           out_flush();
  #ifdef HAVE_TGETENT
!       for (p = s; *s; ++s)
        {
!           // flush just before delay command
!           if (*s == '$' && *(s + 1) == '<')
!           {
!               char_u save_c = *s;
!               int duration = atoi((char *)s + 2);
  
!               *s = NUL;
!               tputs((char *)p, 1, TPUTSFUNCAST out_char_nf);
!               *s = save_c;
!               out_flush();
  # ifdef ELAPSED_FUNC
!               // Only sleep here if we can limit this happening in
!               // vim_beep().
!               p = vim_strchr(s, '>');
!               if (p == NULL || duration <= 0)
!               {
!                   // can't parse the time, don't sleep here
!                   p = s;
!               }
!               else
!               {
!                   ++p;
!                   do_sleep(duration, FALSE);
!               }
! # else
!               // Rely on the terminal library to sleep.
                p = s;
- # endif
-               break;
            }
        }
!       tputs((char *)p, 1, TPUTSFUNCAST out_char_nf);
  #else
!       while (*s)
!           out_char_nf(*s++);
  #endif
  
!       // For testing we write one string at a time.
!       if (p_wd)
!           out_flush();
!     }
  }
  
  /*
--- 2847,2912 ----
      void
  out_str_cf(char_u *s)
  {
!     if (s == NULL || *s == NUL)
!       return;
! 
  #ifdef HAVE_TGETENT
!     char_u *p;
  #endif
  
  #ifdef FEAT_GUI
!     // Don't use tputs() when GUI is used, ncurses crashes.
!     if (gui.in_use)
!     {
!       out_str_nf(s);
!       return;
!     }
  #endif
!     if (out_pos > OUT_SIZE - MAX_ESC_SEQ_LEN)
!       out_flush();
  #ifdef HAVE_TGETENT
!     for (p = s; *s; ++s)
!     {
!       // flush just before delay command
!       if (*s == '$' && *(s + 1) == '<')
        {
!           char_u save_c = *s;
!           int duration = atoi((char *)s + 2);
  
!           *s = NUL;
!           tputs((char *)p, 1, TPUTSFUNCAST out_char_nf);
!           *s = save_c;
!           out_flush();
  # ifdef ELAPSED_FUNC
!           // Only sleep here if we can limit this happening in
!           // vim_beep().
!           p = vim_strchr(s, '>');
!           if (p == NULL || duration <= 0)
!           {
!               // can't parse the time, don't sleep here
                p = s;
            }
+           else
+           {
+               ++p;
+               do_sleep(duration, FALSE);
+           }
+ # else
+           // Rely on the terminal library to sleep.
+           p = s;
+ # endif
+           break;
        }
!     }
!     tputs((char *)p, 1, TPUTSFUNCAST out_char_nf);
  #else
!     while (*s)
!       out_char_nf(*s++);
  #endif
  
!     // For testing we write one string at a time.
!     if (p_wd)
!       out_flush();
  }
  
  /*
***************
*** 2917,2946 ****
      void
  out_str(char_u *s)
  {
!     if (s != NULL && *s)
!     {
  #ifdef FEAT_GUI
!       // Don't use tputs() when GUI is used, ncurses crashes.
!       if (gui.in_use)
!       {
!           out_str_nf(s);
!           return;
!       }
  #endif
!       // avoid terminal strings being split up
!       if (out_pos > OUT_SIZE - MAX_ESC_SEQ_LEN)
!           out_flush();
  #ifdef HAVE_TGETENT
!       tputs((char *)s, 1, TPUTSFUNCAST out_char_nf);
  #else
!       while (*s)
!           out_char_nf(*s++);
  #endif
  
!       // For testing we write one string at a time.
!       if (p_wd)
!           out_flush();
!     }
  }
  
  /*
--- 2918,2947 ----
      void
  out_str(char_u *s)
  {
!     if (s == NULL || *s == NUL)
!       return;
! 
  #ifdef FEAT_GUI
!     // Don't use tputs() when GUI is used, ncurses crashes.
!     if (gui.in_use)
!     {
!       out_str_nf(s);
!       return;
!     }
  #endif
!     // avoid terminal strings being split up
!     if (out_pos > OUT_SIZE - MAX_ESC_SEQ_LEN)
!       out_flush();
  #ifdef HAVE_TGETENT
!     tputs((char *)s, 1, TPUTSFUNCAST out_char_nf);
  #else
!     while (*s)
!       out_char_nf(*s++);
  #endif
  
!     // For testing we write one string at a time.
!     if (p_wd)
!       out_flush();
  }
  
  /*
***************
*** 3468,3480 ****
  
      *val = 0;
      len = get_bytes_from_buf(buf, bytes, (int)sizeof(long_u));
!     if (len != -1)
      {
!       for (i = 0; i < (int)sizeof(long_u); i++)
!       {
!           shift = 8 * (sizeof(long_u) - 1 - i);
!           *val += (long_u)bytes[i] << shift;
!       }
      }
      return len;
  }
--- 3469,3480 ----
  
      *val = 0;
      len = get_bytes_from_buf(buf, bytes, (int)sizeof(long_u));
!     if (len == -1)
!       return -1;
!     for (i = 0; i < (int)sizeof(long_u); i++)
      {
!       shift = 8 * (sizeof(long_u) - 1 - i);
!       *val += (long_u)bytes[i] << shift;
      }
      return len;
  }
***************
*** 3598,3616 ****
      int               old_Rows = Rows;
      int               old_Columns = Columns;
  
!     if (!exiting
  #ifdef FEAT_GUI
            // Do not get the size when executing a shell command during
            // startup.
!           && !gui.starting
  #endif
            )
!     {
!       (void)ui_get_shellsize();
!       check_shellsize();
!       if (old_Rows != Rows || old_Columns != Columns)
!           shell_resized();
!     }
  }
  
  /*
--- 3598,3616 ----
      int               old_Rows = Rows;
      int               old_Columns = Columns;
  
!     if (exiting
  #ifdef FEAT_GUI
            // Do not get the size when executing a shell command during
            // startup.
!           || gui.starting
  #endif
            )
!       return;
! 
!     (void)ui_get_shellsize();
!     check_shellsize();
!     if (old_Rows != Rows || old_Columns != Columns)
!       shell_resized();
  }
  
  /*
***************
*** 3843,3943 ****
        return;
  #endif
  
!     if (full_screen)
      {
-       /*
-        * When returning after calling a shell cur_tmode is TMODE_UNKNOWN,
-        * set the terminal to raw mode, even though we think it already is,
-        * because the shell program may have reset the terminal mode.
-        * When we think the terminal is normal, don't try to set it to
-        * normal again, because that causes problems (logout!) on some
-        * machines.
-        */
-       if (tmode != cur_tmode)
-       {
  #ifdef FEAT_TERMRESPONSE
  # ifdef FEAT_GUI
!           if (!gui.in_use && !gui.starting)
  # endif
!           {
!               // May need to check for T_CRV response and termcodes, it
!               // doesn't work in Cooked mode, an external program may get
!               // them.
!               if (tmode != TMODE_RAW && termrequest_any_pending())
!                   (void)vpeekc_nomap();
!               check_for_codes_from_term();
!           }
  #endif
!           if (tmode != TMODE_RAW)
!               mch_setmouse(FALSE);    // switch mouse off
  
!           // Disable bracketed paste and modifyOtherKeys in cooked mode.
!           // Avoid doing this too often, on some terminals the codes are not
!           // handled properly.
!           if (termcap_active && tmode != TMODE_SLEEP
!                                                  && cur_tmode != TMODE_SLEEP)
!           {
!               MAY_WANT_TO_LOG_THIS;
  
!               if (tmode != TMODE_RAW)
!               {
!                   out_str(T_BD);      // disable bracketed paste mode
!                   out_str_t_TE();     // possibly disables modifyOtherKeys
!               }
!               else
!               {
!                   out_str_t_BE();     // enable bracketed paste mode (should
!                                       // be before mch_settmode().
!                   out_str_t_TI();     // possibly enables modifyOtherKeys
!               }
            }
-           out_flush();
-           mch_settmode(tmode);        // machine specific function
-           cur_tmode = tmode;
-           if (tmode == TMODE_RAW)
-               setmouse();             // may switch mouse on
-           out_flush();
        }
  #ifdef FEAT_TERMRESPONSE
!       may_req_termresponse();
  #endif
-     }
  }
  
      void
  starttermcap(void)
  {
!     if (full_screen && !termcap_active)
!     {
!       MAY_WANT_TO_LOG_THIS;
  
!       out_str(T_TI);                  // start termcap mode
!       out_str_t_TI();                 // start "raw" mode
!       out_str(T_KS);                  // start "keypad transmit" mode
!       out_str_t_BE();                 // enable bracketed paste mode
  
  #if defined(UNIX) || defined(VMS)
!       // Enable xterm's focus reporting mode when 'esckeys' is set.
!       if (p_ek && *T_FE != NUL)
!           out_str(T_FE);
  #endif
  
!       out_flush();
!       termcap_active = TRUE;
!       screen_start();                 // don't know where cursor is now
  #ifdef FEAT_TERMRESPONSE
  # ifdef FEAT_GUI
!       if (!gui.in_use && !gui.starting)
  # endif
!       {
!           may_req_termresponse();
!           // Immediately check for a response.  If t_Co changes, we don't
!           // want to redraw with wrong colors first.
!           if (crv_status.tr_progress == STATUS_SENT)
!               check_for_codes_from_term();
!       }
! #endif
      }
  }
  
      void
--- 3843,3943 ----
        return;
  #endif
  
!     if (!full_screen)
!       return;
! 
!     /*
!      * When returning after calling a shell cur_tmode is TMODE_UNKNOWN,
!      * set the terminal to raw mode, even though we think it already is,
!      * because the shell program may have reset the terminal mode.
!      * When we think the terminal is normal, don't try to set it to
!      * normal again, because that causes problems (logout!) on some
!      * machines.
!      */
!     if (tmode != cur_tmode)
      {
  #ifdef FEAT_TERMRESPONSE
  # ifdef FEAT_GUI
!       if (!gui.in_use && !gui.starting)
  # endif
!       {
!           // May need to check for T_CRV response and termcodes, it
!           // doesn't work in Cooked mode, an external program may get
!           // them.
!           if (tmode != TMODE_RAW && termrequest_any_pending())
!               (void)vpeekc_nomap();
!           check_for_codes_from_term();
!       }
  #endif
!       if (tmode != TMODE_RAW)
!           mch_setmouse(FALSE);        // switch mouse off
  
!       // Disable bracketed paste and modifyOtherKeys in cooked mode.
!       // Avoid doing this too often, on some terminals the codes are not
!       // handled properly.
!       if (termcap_active && tmode != TMODE_SLEEP
!               && cur_tmode != TMODE_SLEEP)
!       {
!           MAY_WANT_TO_LOG_THIS;
  
!           if (tmode != TMODE_RAW)
!           {
!               out_str(T_BD);  // disable bracketed paste mode
!               out_str_t_TE(); // possibly disables modifyOtherKeys
!           }
!           else
!           {
!               out_str_t_BE(); // enable bracketed paste mode (should
!                               // be before mch_settmode().
!               out_str_t_TI(); // possibly enables modifyOtherKeys
            }
        }
+       out_flush();
+       mch_settmode(tmode);    // machine specific function
+       cur_tmode = tmode;
+       if (tmode == TMODE_RAW)
+           setmouse();         // may switch mouse on
+       out_flush();
+     }
  #ifdef FEAT_TERMRESPONSE
!     may_req_termresponse();
  #endif
  }
  
      void
  starttermcap(void)
  {
!     if (!full_screen || termcap_active)
!       return;
! 
!     MAY_WANT_TO_LOG_THIS;
  
!     out_str(T_TI);                    // start termcap mode
!     out_str_t_TI();                   // start "raw" mode
!     out_str(T_KS);                    // start "keypad transmit" mode
!     out_str_t_BE();                   // enable bracketed paste mode
  
  #if defined(UNIX) || defined(VMS)
!     // Enable xterm's focus reporting mode when 'esckeys' is set.
!     if (p_ek && *T_FE != NUL)
!       out_str(T_FE);
  #endif
  
!     out_flush();
!     termcap_active = TRUE;
!     screen_start();                   // don't know where cursor is now
  #ifdef FEAT_TERMRESPONSE
  # ifdef FEAT_GUI
!     if (!gui.in_use && !gui.starting)
  # endif
!     {
!       may_req_termresponse();
!       // Immediately check for a response.  If t_Co changes, we don't
!       // want to redraw with wrong colors first.
!       if (crv_status.tr_progress == STATUS_SENT)
!           check_for_codes_from_term();
      }
+ #endif
  }
  
      void
***************
*** 3945,4007 ****
  {
      screen_stop_highlight();
      reset_cterm_colors();
!     if (termcap_active)
!     {
  #ifdef FEAT_TERMRESPONSE
  # ifdef FEAT_GUI
!       if (!gui.in_use && !gui.starting)
  # endif
        {
-           // May need to discard T_CRV, T_U7 or T_RBG response.
-           if (termrequest_any_pending())
-           {
  # ifdef UNIX
!               // Give the terminal a chance to respond.
!               mch_delay(100L, 0);
  # endif
  # ifdef TCIFLUSH
!               // Discard data received but not read.
!               if (exiting)
!                   tcflush(fileno(stdin), TCIFLUSH);
  # endif
-           }
-           // Check for termcodes first, otherwise an external program may
-           // get them.
-           check_for_codes_from_term();
        }
  #endif
!       MAY_WANT_TO_LOG_THIS;
  
  #if defined(UNIX) || defined(VMS)
!       // Disable xterm's focus reporting mode if 'esckeys' is set.
!       if (p_ek && *T_FD != NUL)
!           out_str(T_FD);
  #endif
  
!       out_str(T_BD);                  // disable bracketed paste mode
!       out_str(T_KE);                  // stop "keypad transmit" mode
!       out_flush();
!       termcap_active = FALSE;
  
!       // Output t_te before t_TE, t_te may switch between main and alternate
!       // screen and following codes may work on the active screen only.
!       //
!       // When using the Kitty keyboard protocol the main and alternate screen
!       // use a separate state.  If we are (or were) using the Kitty keyboard
!       // protocol and t_te is not empty (possibly switching screens) then
!       // output t_TE both before and after outputting t_te.
!       if (*T_TE != NUL && (kitty_protocol_state == KKPS_ENABLED
!                                    || kitty_protocol_state == KKPS_DISABLED))
!           out_str_t_TE();             // probably disables the kitty keyboard
!                                       // protocol
! 
!       out_str(T_TE);                  // stop termcap mode
!       cursor_on();                    // just in case it is still off
!       out_str_t_TE();                 // stop "raw" mode, modifyOtherKeys and
                                        // Kitty keyboard protocol
!       screen_start();                 // don't know where cursor is now
!       out_flush();
!     }
  }
  
  #if defined(FEAT_TERMRESPONSE) || defined(PROTO)
--- 3945,4008 ----
  {
      screen_stop_highlight();
      reset_cterm_colors();
! 
!     if (!termcap_active)
!       return;
! 
  #ifdef FEAT_TERMRESPONSE
  # ifdef FEAT_GUI
!     if (!gui.in_use && !gui.starting)
  # endif
+     {
+       // May need to discard T_CRV, T_U7 or T_RBG response.
+       if (termrequest_any_pending())
        {
  # ifdef UNIX
!           // Give the terminal a chance to respond.
!           mch_delay(100L, 0);
  # endif
  # ifdef TCIFLUSH
!           // Discard data received but not read.
!           if (exiting)
!               tcflush(fileno(stdin), TCIFLUSH);
  # endif
        }
+       // Check for termcodes first, otherwise an external program may
+       // get them.
+       check_for_codes_from_term();
+     }
  #endif
!     MAY_WANT_TO_LOG_THIS;
  
  #if defined(UNIX) || defined(VMS)
!     // Disable xterm's focus reporting mode if 'esckeys' is set.
!     if (p_ek && *T_FD != NUL)
!       out_str(T_FD);
  #endif
  
!     out_str(T_BD);                    // disable bracketed paste mode
!     out_str(T_KE);                    // stop "keypad transmit" mode
!     out_flush();
!     termcap_active = FALSE;
  
!     // Output t_te before t_TE, t_te may switch between main and alternate
!     // screen and following codes may work on the active screen only.
!     //
!     // When using the Kitty keyboard protocol the main and alternate screen
!     // use a separate state.  If we are (or were) using the Kitty keyboard
!     // protocol and t_te is not empty (possibly switching screens) then
!     // output t_TE both before and after outputting t_te.
!     if (*T_TE != NUL && (kitty_protocol_state == KKPS_ENABLED
!               || kitty_protocol_state == KKPS_DISABLED))
!       out_str_t_TE();         // probably disables the kitty keyboard
!                               // protocol
! 
!     out_str(T_TE);                    // stop termcap mode
!     cursor_on();                      // just in case it is still off
!     out_str_t_TE();                   // stop "raw" mode, modifyOtherKeys and
                                        // Kitty keyboard protocol
!     screen_start();                   // don't know where cursor is now
!     out_flush();
  }
  
  #if defined(FEAT_TERMRESPONSE) || defined(PROTO)
***************
*** 4219,4231 ****
      void
  scroll_start(void)
  {
!     if (*T_VS != NUL && *T_CVS != NUL)
!     {
!       MAY_WANT_TO_LOG_THIS;
!       out_str(T_VS);
!       out_str(T_CVS);
!       screen_start();         // don't know where cursor is now
!     }
  }
  
  // True if cursor is not visible
--- 4220,4232 ----
      void
  scroll_start(void)
  {
!     if (*T_VS == NUL || *T_CVS == NUL)
!       return;
! 
!     MAY_WANT_TO_LOG_THIS;
!     out_str(T_VS);
!     out_str(T_CVS);
!     screen_start();           // don't know where cursor is now
  }
  
  // True if cursor is not visible
***************
*** 4355,4367 ****
      void
  term_cursor_color(char_u *color)
  {
!     if (*T_CSC != NUL)
!     {
!       out_str(T_CSC);         // set cursor color start
!       out_str_nf(color);
!       out_str(T_CEC);         // set cursor color end
!       out_flush();
!     }
  }
  # endif
  
--- 4356,4368 ----
      void
  term_cursor_color(char_u *color)
  {
!     if (*T_CSC == NUL)
!       return;
! 
!     out_str(T_CSC);           // set cursor color start
!     out_str_nf(color);
!     out_str(T_CEC);           // set cursor color end
!     out_flush();
  }
  # endif
  
***************
*** 4922,4939 ****
  {
      int new_slen = 0;
  
      if (modifiers != 0)
      {
!       // Some keys have the modifier included.  Need to handle that here to
!       // make mappings work.  This may result in a special key, such as
!       // K_S_TAB.
!       *key = simplify_key(*key, &modifiers);
!       if (modifiers != 0)
!       {
!           string[new_slen++] = K_SPECIAL;
!           string[new_slen++] = (int)KS_MODIFIER;
!           string[new_slen++] = modifiers;
!       }
      }
      return new_slen;
  }
--- 4923,4940 ----
  {
      int new_slen = 0;
  
+     if (modifiers == 0)
+       return 0;
+ 
+     // Some keys have the modifier included.  Need to handle that here to
+     // make mappings work.  This may result in a special key, such as
+     // K_S_TAB.
+     *key = simplify_key(*key, &modifiers);
      if (modifiers != 0)
      {
!       string[new_slen++] = K_SPECIAL;
!       string[new_slen++] = (int)KS_MODIFIER;
!       string[new_slen++] = modifiers;
      }
      return new_slen;
  }
***************
*** 6523,6534 ****
      void
  term_get_fg_color(char_u *r, char_u *g, char_u *b)
  {
!     if (rfg_status.tr_progress == STATUS_GOT)
!     {
!       *r = fg_r;
!       *g = fg_g;
!       *b = fg_b;
!     }
  }
  
  /*
--- 6524,6535 ----
      void
  term_get_fg_color(char_u *r, char_u *g, char_u *b)
  {
!     if (rfg_status.tr_progress != STATUS_GOT)
!       return;
! 
!     *r = fg_r;
!     *g = fg_g;
!     *b = fg_b;
  }
  
  /*
***************
*** 6537,6548 ****
      void
  term_get_bg_color(char_u *r, char_u *g, char_u *b)
  {
!     if (rbg_status.tr_progress == STATUS_GOT)
!     {
!       *r = bg_r;
!       *g = bg_g;
!       *b = bg_b;
!     }
  }
  #endif
  
--- 6538,6549 ----
      void
  term_get_bg_color(char_u *r, char_u *g, char_u *b)
  {
!     if (rbg_status.tr_progress != STATUS_GOT)
!       return;
! 
!     *r = bg_r;
!     *g = bg_g;
!     *b = bg_b;
  }
  #endif
  
***************
*** 7283,7296 ****
      int           code)
  {
      tcap_entry_T *p = find_builtin_term(name);
!     if (p != NULL)
      {
!       while (p->bt_string != NULL)
!       {
!           if (p->bt_entry == code)
!               return p;
!           ++p;
!       }
      }
      return NULL;
  }
--- 7284,7296 ----
      int           code)
  {
      tcap_entry_T *p = find_builtin_term(name);
!     if (p == NULL)
!       return NULL;
!     while (p->bt_string != NULL)
      {
!       if (p->bt_entry == code)
!           return p;
!       ++p;
      }
      return NULL;
  }
*** ../vim-9.0.1244/src/terminal.c      2022-11-28 18:51:38.959571588 +0000
--- src/terminal.c      2023-01-25 21:02:57.835082030 +0000
***************
*** 259,277 ****
      *rows = 0;
      *cols = 0;
  
!     if (*wp->w_p_tws != NUL)
!     {
!       char_u *p = vim_strchr(wp->w_p_tws, 'x');
  
!       // Syntax of value was already checked when it's set.
!       if (p == NULL)
!       {
!           minsize = TRUE;
!           p = vim_strchr(wp->w_p_tws, '*');
!       }
!       *rows = atoi((char *)wp->w_p_tws);
!       *cols = atoi((char *)p + 1);
      }
      return minsize;
  }
  
--- 259,277 ----
      *rows = 0;
      *cols = 0;
  
!     if (*wp->w_p_tws == NUL)
!       return FALSE;
  
!     char_u *p = vim_strchr(wp->w_p_tws, 'x');
! 
!     // Syntax of value was already checked when it's set.
!     if (p == NULL)
!     {
!       minsize = TRUE;
!       p = vim_strchr(wp->w_p_tws, '*');
      }
+     *rows = atoi((char *)wp->w_p_tws);
+     *cols = atoi((char *)p + 1);
      return minsize;
  }
  
***************
*** 1620,1640 ****
  {
      // Also consider the job finished when the channel is closed, to avoid a
      // race condition when updating the title.
!     if (term != NULL
!       && term->tl_job != NULL
!       && channel_is_open(term->tl_job->jv_channel))
!     {
!       job_T *job = term->tl_job;
  
!       // Careful: Checking the job status may invoke callbacks, which close
!       // the buffer and terminate "term".  However, "job" will not be freed
!       // yet.
!       if (check_job_status)
!           job_status(job);
!       return (job->jv_status == JOB_STARTED
!               || (job->jv_channel != NULL && job->jv_channel->ch_keep_open));
!     }
!     return FALSE;
  }
  
  /*
--- 1620,1639 ----
  {
      // Also consider the job finished when the channel is closed, to avoid a
      // race condition when updating the title.
!     if (term == NULL
!       || term->tl_job == NULL
!       || !channel_is_open(term->tl_job->jv_channel))
!       return FALSE;
  
!     job_T *job = term->tl_job;
! 
!     // Careful: Checking the job status may invoke callbacks, which close
!     // the buffer and terminate "term".  However, "job" will not be freed
!     // yet.
!     if (check_job_status)
!       job_status(job);
!     return (job->jv_status == JOB_STARTED
!           || (job->jv_channel != NULL && job->jv_channel->ch_keep_open));
  }
  
  /*
***************
*** 1807,1834 ****
      static int
  add_empty_scrollback(term_T *term, cellattr_T *fill_attr, int lnum)
  {
!     if (ga_grow(&term->tl_scrollback, 1) == OK)
      {
!       sb_line_T *line = (sb_line_T *)term->tl_scrollback.ga_data
!                                     + term->tl_scrollback.ga_len;
  
!       if (lnum > 0)
        {
!           int i;
! 
!           for (i = 0; i < term->tl_scrollback.ga_len - lnum; ++i)
!           {
!               *line = *(line - 1);
!               --line;
!           }
        }
-       line->sb_cols = 0;
-       line->sb_cells = NULL;
-       line->sb_fill_attr = *fill_attr;
-       ++term->tl_scrollback.ga_len;
-       return OK;
      }
!     return FALSE;
  }
  
  /*
--- 1806,1832 ----
      static int
  add_empty_scrollback(term_T *term, cellattr_T *fill_attr, int lnum)
  {
!     if (ga_grow(&term->tl_scrollback, 1) == FAIL)
!       return FALSE;
! 
!     sb_line_T *line = (sb_line_T *)term->tl_scrollback.ga_data
!       + term->tl_scrollback.ga_len;
! 
!     if (lnum > 0)
      {
!       int i;
  
!       for (i = 0; i < term->tl_scrollback.ga_len - lnum; ++i)
        {
!           *line = *(line - 1);
!           --line;
        }
      }
!     line->sb_cols = 0;
!     line->sb_cells = NULL;
!     line->sb_fill_attr = *fill_attr;
!     ++term->tl_scrollback.ga_len;
!     return OK;
  }
  
  /*
***************
*** 2409,2451 ****
        return;
  
      l = (list_T *)get_reg_contents(c, GREG_LIST);
!     if (l != NULL)
      {
!       type = get_reg_type(c, &reglen);
!       FOR_ALL_LIST_ITEMS(l, item)
!       {
!           char_u *s = tv_get_string(&item->li_tv);
  #ifdef MSWIN
!           char_u *tmp = s;
  
!           if (!enc_utf8 && enc_codepage > 0)
!           {
!               WCHAR   *ret = NULL;
!               int     length = 0;
  
!               MultiByteToWideChar_alloc(enc_codepage, 0, (char *)s,
!                                               (int)STRLEN(s), &ret, &length);
!               if (ret != NULL)
!               {
!                   WideCharToMultiByte_alloc(CP_UTF8, 0,
!                                   ret, length, (char **)&s, &length, 0, 0);
!                   vim_free(ret);
!               }
            }
  #endif
!           channel_send(curbuf->b_term->tl_job->jv_channel, PART_IN,
!                                                     s, (int)STRLEN(s), NULL);
  #ifdef MSWIN
!           if (tmp != s)
!               vim_free(s);
  #endif
  
!           if (item->li_next != NULL || type == MLINE)
!               channel_send(curbuf->b_term->tl_job->jv_channel, PART_IN,
!                                                     (char_u *)"\r", 1, NULL);
!       }
!       list_free(l);
      }
  }
  
  /*
--- 2407,2449 ----
        return;
  
      l = (list_T *)get_reg_contents(c, GREG_LIST);
!     if (l == NULL)
!       return;
! 
!     type = get_reg_type(c, &reglen);
!     FOR_ALL_LIST_ITEMS(l, item)
      {
!       char_u *s = tv_get_string(&item->li_tv);
  #ifdef MSWIN
!       char_u *tmp = s;
  
!       if (!enc_utf8 && enc_codepage > 0)
!       {
!           WCHAR   *ret = NULL;
!           int length = 0;
  
!           MultiByteToWideChar_alloc(enc_codepage, 0, (char *)s,
!                   (int)STRLEN(s), &ret, &length);
!           if (ret != NULL)
!           {
!               WideCharToMultiByte_alloc(CP_UTF8, 0,
!                       ret, length, (char **)&s, &length, 0, 0);
!               vim_free(ret);
            }
+       }
  #endif
!       channel_send(curbuf->b_term->tl_job->jv_channel, PART_IN,
!               s, (int)STRLEN(s), NULL);
  #ifdef MSWIN
!       if (tmp != s)
!           vim_free(s);
  #endif
  
!       if (item->li_next != NULL || type == MLINE)
!           channel_send(curbuf->b_term->tl_job->jv_channel, PART_IN,
!                   (char_u *)"\r", 1, NULL);
      }
+     list_free(l);
  }
  
  /*
***************
*** 2615,2632 ****
  {
      term_T *term = curbuf->b_term;
  
!     if (term != NULL)
      {
!       if (term_use_loop_check(TRUE))
!       {
!           reset_VIsual_and_resel();
!           if (State & MODE_INSERT)
!               stop_insert_mode = TRUE;
!       }
!       mouse_was_outside = FALSE;
!       enter_mouse_col = mouse_col;
!       enter_mouse_row = mouse_row;
!     }
  }
  
      void
--- 2613,2630 ----
  {
      term_T *term = curbuf->b_term;
  
!     if (term == NULL)
!       return;
! 
!     if (term_use_loop_check(TRUE))
      {
!       reset_VIsual_and_resel();
!       if (State & MODE_INSERT)
!           stop_insert_mode = TRUE;
!     }
!     mouse_was_outside = FALSE;
!     enter_mouse_col = mouse_col;
!     enter_mouse_row = mouse_row;
  }
  
      void
***************
*** 2634,2649 ****
  {
      term_T *term = curbuf->b_term;
  
!     if (term != NULL && term->tl_vterm != NULL)
!     {
!       VTermState      *state = vterm_obtain_state(term->tl_vterm);
  
!       if (in_focus)
!           vterm_state_focus_in(state);
!       else
!           vterm_state_focus_out(state);
!       term_forward_output(term);
!     }
  }
  
  /*
--- 2632,2647 ----
  {
      term_T *term = curbuf->b_term;
  
!     if (term == NULL || term->tl_vterm == NULL)
!       return;
  
!     VTermState        *state = vterm_obtain_state(term->tl_vterm);
! 
!     if (in_focus)
!       vterm_state_focus_in(state);
!     else
!       vterm_state_focus_out(state);
!     term_forward_output(term);
  }
  
  /*
***************
*** 2886,2898 ****
      static void
  may_toggle_cursor(term_T *term)
  {
!     if (in_terminal_loop == term)
!     {
!       if (term->tl_cursor_visible)
!           cursor_on();
!       else
!           cursor_off();
!     }
  }
  
  /*
--- 2884,2896 ----
      static void
  may_toggle_cursor(term_T *term)
  {
!     if (in_terminal_loop != term)
!       return;
! 
!     if (term->tl_cursor_visible)
!       cursor_on();
!     else
!       cursor_off();
  }
  
  /*
***************
*** 3320,3346 ****
      static void
  limit_scrollback(term_T *term, garray_T *gap, int update_buffer)
  {
!     if (gap->ga_len >= term->tl_buffer->b_p_twsl)
!     {
!       int     todo = term->tl_buffer->b_p_twsl / 10;
!       int     i;
  
!       curbuf = term->tl_buffer;
!       for (i = 0; i < todo; ++i)
!       {
!           vim_free(((sb_line_T *)gap->ga_data + i)->sb_cells);
!           if (update_buffer)
!               ml_delete(1);
!       }
!       curbuf = curwin->w_buffer;
  
!       gap->ga_len -= todo;
!       mch_memmove(gap->ga_data,
!                   (sb_line_T *)gap->ga_data + todo,
!                   sizeof(sb_line_T) * gap->ga_len);
        if (update_buffer)
!           term->tl_scrollback_scrolled -= todo;
      }
  }
  
  /*
--- 3318,3344 ----
      static void
  limit_scrollback(term_T *term, garray_T *gap, int update_buffer)
  {
!     if (gap->ga_len < term->tl_buffer->b_p_twsl)
!       return;
  
!     int       todo = term->tl_buffer->b_p_twsl / 10;
!     int       i;
  
!     curbuf = term->tl_buffer;
!     for (i = 0; i < todo; ++i)
!     {
!       vim_free(((sb_line_T *)gap->ga_data + i)->sb_cells);
        if (update_buffer)
!           ml_delete(1);
      }
+     curbuf = curwin->w_buffer;
+ 
+     gap->ga_len -= todo;
+     mch_memmove(gap->ga_data,
+           (sb_line_T *)gap->ga_data + todo,
+           sizeof(sb_line_T) * gap->ga_len);
+     if (update_buffer)
+       term->tl_scrollback_scrolled -= todo;
  }
  
  /*
***************
*** 3371,3448 ****
  
      limit_scrollback(term, gap, update_buffer);
  
!     if (ga_grow(gap, 1) == OK)
!     {
!       cellattr_T      *p = NULL;
!       int             len = 0;
!       int             i;
!       int             c;
!       int             col;
!       int             text_len;
!       char_u          *text;
!       sb_line_T       *line;
!       garray_T        ga;
!       cellattr_T      fill_attr = term->tl_default_color;
  
!       // do not store empty cells at the end
!       for (i = 0; i < cols; ++i)
!           if (cells[i].chars[0] != 0)
!               len = i + 1;
!           else
!               cell2cellattr(&cells[i], &fill_attr);
  
!       ga_init2(&ga, 1, 100);
!       if (len > 0)
!           p = ALLOC_MULT(cellattr_T, len);
!       if (p != NULL)
        {
!           for (col = 0; col < len; col += cells[col].width)
            {
!               if (ga_grow(&ga, MB_MAXBYTES) == FAIL)
!               {
!                   ga.ga_len = 0;
!                   break;
!               }
!               for (i = 0; (c = cells[col].chars[i]) > 0 || i == 0; ++i)
!                   ga.ga_len += utf_char2bytes(c == NUL ? ' ' : c,
!                                            (char_u *)ga.ga_data + ga.ga_len);
!               cell2cellattr(&cells[col], &p[col]);
            }
        }
!       if (ga_grow(&ga, 1) == FAIL)
!       {
!           if (update_buffer)
!               text = (char_u *)"";
!           else
!               text = vim_strsave((char_u *)"");
!           text_len = 0;
!       }
!       else
!       {
!           text = ga.ga_data;
!           text_len = ga.ga_len;
!           *(text + text_len) = NUL;
!       }
!       if (update_buffer)
!           add_scrollback_line_to_buffer(term, text, text_len);
! 
!       line = (sb_line_T *)gap->ga_data + gap->ga_len;
!       line->sb_cols = len;
!       line->sb_cells = p;
!       line->sb_fill_attr = fill_attr;
        if (update_buffer)
!       {
!           line->sb_text = NULL;
!           ++term->tl_scrollback_scrolled;
!           ga_clear(&ga);  // free the text
!       }
        else
!       {
!           line->sb_text = text;
!           ga_init(&ga);  // text is kept in tl_scrollback_postponed
!       }
!       ++gap->ga_len;
      }
      return 0; // ignored
  }
  
--- 3369,3446 ----
  
      limit_scrollback(term, gap, update_buffer);
  
!     if (ga_grow(gap, 1) == FAIL)
!       return 0;
  
!     cellattr_T        *p = NULL;
!     int               len = 0;
!     int               i;
!     int               c;
!     int               col;
!     int               text_len;
!     char_u            *text;
!     sb_line_T *line;
!     garray_T  ga;
!     cellattr_T        fill_attr = term->tl_default_color;
  
!     // do not store empty cells at the end
!     for (i = 0; i < cols; ++i)
!       if (cells[i].chars[0] != 0)
!           len = i + 1;
!       else
!           cell2cellattr(&cells[i], &fill_attr);
! 
!     ga_init2(&ga, 1, 100);
!     if (len > 0)
!       p = ALLOC_MULT(cellattr_T, len);
!     if (p != NULL)
!     {
!       for (col = 0; col < len; col += cells[col].width)
        {
!           if (ga_grow(&ga, MB_MAXBYTES) == FAIL)
            {
!               ga.ga_len = 0;
!               break;
            }
+           for (i = 0; (c = cells[col].chars[i]) > 0 || i == 0; ++i)
+               ga.ga_len += utf_char2bytes(c == NUL ? ' ' : c,
+                       (char_u *)ga.ga_data + ga.ga_len);
+           cell2cellattr(&cells[col], &p[col]);
        }
!     }
!     if (ga_grow(&ga, 1) == FAIL)
!     {
        if (update_buffer)
!           text = (char_u *)"";
        else
!           text = vim_strsave((char_u *)"");
!       text_len = 0;
      }
+     else
+     {
+       text = ga.ga_data;
+       text_len = ga.ga_len;
+       *(text + text_len) = NUL;
+     }
+     if (update_buffer)
+       add_scrollback_line_to_buffer(term, text, text_len);
+ 
+     line = (sb_line_T *)gap->ga_data + gap->ga_len;
+     line->sb_cols = len;
+     line->sb_cells = p;
+     line->sb_fill_attr = fill_attr;
+     if (update_buffer)
+     {
+       line->sb_text = NULL;
+       ++term->tl_scrollback_scrolled;
+       ga_clear(&ga);  // free the text
+     }
+     else
+     {
+       line->sb_text = text;
+       ga_init(&ga);  // text is kept in tl_scrollback_postponed
+     }
+     ++gap->ga_len;
      return 0; // ignored
  }
  
***************
*** 3612,3628 ****
      int
  may_close_term_popup(void)
  {
!     if (popup_is_popup(curwin) && curbuf->b_term != NULL
!                                && !term_job_running_not_none(curbuf->b_term))
!     {
!       win_T *pwin = curwin;
  
!       if (win_valid(prevwin))
!           win_enter(prevwin, FALSE);
!       popup_close_with_retval(pwin, 0);
!       return OK;
!     }
!     return FAIL;
  }
  #endif
  
--- 3610,3625 ----
      int
  may_close_term_popup(void)
  {
!     if (!popup_is_popup(curwin) || curbuf->b_term == NULL
!                                || term_job_running_not_none(curbuf->b_term))
!       return FAIL;
  
!     win_T *pwin = curwin;
! 
!     if (win_valid(prevwin))
!       win_enter(prevwin, FALSE);
!     popup_close_with_retval(pwin, 0);
!     return OK;
  }
  #endif
  
***************
*** 4002,4013 ****
  {
      term_T    *term = wp->w_buffer->b_term;
  
!     if (term != NULL && term->tl_vterm != NULL && !term->tl_normal_mode
!                                                      && wp->w_redr_type == 0)
!     {
!       term->tl_dirty_row_start = MAX_ROW;
!       term->tl_dirty_row_end = 0;
!     }
  }
  
  /*
--- 3999,4010 ----
  {
      term_T    *term = wp->w_buffer->b_term;
  
!     if (term == NULL || term->tl_vterm == NULL || term->tl_normal_mode
!                                               || wp->w_redr_type != 0)
!       return;
! 
!     term->tl_dirty_row_start = MAX_ROW;
!     term->tl_dirty_row_end = 0;
  }
  
  /*
***************
*** 4040,4055 ****
  {
      term_T *term = curbuf->b_term;
  
!     if (term_is_finished(curbuf) && term->tl_scrollback.ga_len > 0)
!     {
!       free_scrollback(term);
!       redraw_buf_later(term->tl_buffer, UPD_NOT_VALID);
  
!       // The buffer is now like a normal buffer, it cannot be easily
!       // abandoned when changed.
!       set_string_option_direct((char_u *)"buftype", -1,
!                                         (char_u *)"", OPT_FREE|OPT_LOCAL, 0);
!     }
  }
  
  /*
--- 4037,4052 ----
  {
      term_T *term = curbuf->b_term;
  
!     if (!term_is_finished(curbuf) || term->tl_scrollback.ga_len <= 0)
!       return;
  
!     free_scrollback(term);
!     redraw_buf_later(term->tl_buffer, UPD_NOT_VALID);
! 
!     // The buffer is now like a normal buffer, it cannot be easily
!     // abandoned when changed.
!     set_string_option_direct((char_u *)"buftype", -1,
!           (char_u *)"", OPT_FREE|OPT_LOCAL, 0);
  }
  
  /*
***************
*** 4908,4941 ****
      char_u *
  term_get_status_text(term_T *term)
  {
!     if (term->tl_status_text == NULL)
!     {
!       char_u *txt;
!       size_t len;
!       char_u *fname;
  
!       if (term->tl_normal_mode)
!       {
!           if (term_job_running(term))
!               txt = (char_u *)_("Terminal");
!           else
!               txt = (char_u *)_("Terminal-finished");
!       }
!       else if (term->tl_title != NULL)
!           txt = term->tl_title;
!       else if (term_none_open(term))
!           txt = (char_u *)_("active");
!       else if (term_job_running(term))
!           txt = (char_u *)_("running");
        else
!           txt = (char_u *)_("finished");
!       fname = buf_get_fname(term->tl_buffer);
!       len = 9 + STRLEN(fname) + STRLEN(txt);
!       term->tl_status_text = alloc(len);
!       if (term->tl_status_text != NULL)
!           vim_snprintf((char *)term->tl_status_text, len, "%s [%s]",
!                                                                  fname, txt);
      }
      return term->tl_status_text;
  }
  
--- 4905,4938 ----
      char_u *
  term_get_status_text(term_T *term)
  {
!     if (term->tl_status_text != NULL)
!       return term->tl_status_text;
  
!     char_u *txt;
!     size_t len;
!     char_u *fname;
! 
!     if (term->tl_normal_mode)
!     {
!       if (term_job_running(term))
!           txt = (char_u *)_("Terminal");
        else
!           txt = (char_u *)_("Terminal-finished");
      }
+     else if (term->tl_title != NULL)
+       txt = term->tl_title;
+     else if (term_none_open(term))
+       txt = (char_u *)_("active");
+     else if (term_job_running(term))
+       txt = (char_u *)_("running");
+     else
+       txt = (char_u *)_("finished");
+     fname = buf_get_fname(term->tl_buffer);
+     len = 9 + STRLEN(fname) + STRLEN(txt);
+     term->tl_status_text = alloc(len);
+     if (term->tl_status_text != NULL)
+       vim_snprintf((char *)term->tl_status_text, len, "%s [%s]",
+               fname, txt);
      return term->tl_status_text;
  }
  
***************
*** 5236,5246 ****
      static void
  append_cell(garray_T *gap, cellattr_T *cell)
  {
!     if (ga_grow(gap, 1) == OK)
!     {
!       *(((cellattr_T *)gap->ga_data) + gap->ga_len) = *cell;
!       ++gap->ga_len;
!     }
  }
  
      static void
--- 5233,5243 ----
      static void
  append_cell(garray_T *gap, cellattr_T *cell)
  {
!     if (ga_grow(gap, 1) == FAIL)
!       return;
! 
!     *(((cellattr_T *)gap->ga_data) + gap->ga_len) = *cell;
!     ++gap->ga_len;
  }
  
      static void
***************
*** 6036,6050 ****
      list_append_number(l, term->tl_cursor_pos.col + 1);
  
      d = dict_alloc();
!     if (d != NULL)
!     {
!       dict_add_number(d, "visible", term->tl_cursor_visible);
!       dict_add_number(d, "blink", blink_state_is_inverted()
!                           ? !term->tl_cursor_blink : term->tl_cursor_blink);
!       dict_add_number(d, "shape", term->tl_cursor_shape);
!       dict_add_string(d, "color", cursor_color_get(term->tl_cursor_color));
!       list_append_dict(l, d);
!     }
  }
  
  /*
--- 6033,6047 ----
      list_append_number(l, term->tl_cursor_pos.col + 1);
  
      d = dict_alloc();
!     if (d == NULL)
!       return;
! 
!     dict_add_number(d, "visible", term->tl_cursor_visible);
!     dict_add_number(d, "blink", blink_state_is_inverted()
!           ? !term->tl_cursor_blink : term->tl_cursor_blink);
!     dict_add_number(d, "shape", term->tl_cursor_shape);
!     dict_add_string(d, "color", cursor_color_get(term->tl_cursor_color));
!     list_append_dict(l, d);
  }
  
  /*
***************
*** 7692,7711 ****
  term_report_winsize(term_T *term, int rows, int cols)
  {
      // Use an ioctl() to report the new window size to the job.
!     if (term->tl_job != NULL && term->tl_job->jv_channel != NULL)
!     {
!       int fd = -1;
!       int part;
  
!       for (part = PART_OUT; part < PART_COUNT; ++part)
!       {
!           fd = term->tl_job->jv_channel->ch_part[part].ch_fd;
!           if (mch_isatty(fd))
!               break;
!       }
!       if (part < PART_COUNT && mch_report_winsize(fd, rows, cols) == OK)
!           mch_signal_job(term->tl_job, (char_u *)"winch");
      }
  }
  
  # endif
--- 7689,7708 ----
  term_report_winsize(term_T *term, int rows, int cols)
  {
      // Use an ioctl() to report the new window size to the job.
!     if (term->tl_job == NULL || term->tl_job->jv_channel == NULL)
!       return;
  
!     int fd = -1;
!     int part;
! 
!     for (part = PART_OUT; part < PART_COUNT; ++part)
!     {
!       fd = term->tl_job->jv_channel->ch_part[part].ch_fd;
!       if (mch_isatty(fd))
!           break;
      }
+     if (part < PART_COUNT && mch_report_winsize(fd, rows, cols) == OK)
+       mch_signal_job(term->tl_job, (char_u *)"winch");
  }
  
  # endif
*** ../vim-9.0.1244/src/testing.c       2022-12-20 20:01:09.624090908 +0000
--- src/testing.c       2023-01-25 21:02:57.835082030 +0000
***************
*** 55,62 ****
        mch_memmove(buf, p, clen);
        buf[clen] = NUL;
        ga_concat(gap, buf);
      }
!     else switch (*p)
      {
        case BS: ga_concat(gap, (char_u *)"\\b"); break;
        case ESC: ga_concat(gap, (char_u *)"\\e"); break;
--- 55,64 ----
        mch_memmove(buf, p, clen);
        buf[clen] = NUL;
        ga_concat(gap, buf);
+       return;
      }
! 
!     switch (*p)
      {
        case BS: ga_concat(gap, (char_u *)"\\b"); break;
        case ESC: ga_concat(gap, (char_u *)"\\e"); break;
*** ../vim-9.0.1244/src/textformat.c    2023-01-23 16:56:52.740404170 +0000
--- src/textformat.c    2023-01-25 21:02:57.835082030 +0000
***************
*** 752,777 ****
      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;
!           }
        }
      }
  }
--- 752,777 ----
      int               c = ' ';
      int               cc;
  
!     if (!did_add_space)
!       return;
! 
!     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;
        }
      }
  }
*** ../vim-9.0.1244/src/textprop.c      2023-01-02 18:10:00.019271226 +0000
--- src/textprop.c      2023-01-25 21:02:57.835082030 +0000
***************
*** 1939,1966 ****
      }
  
      hi = find_prop_type_hi(name, buf);
!     if (hi != NULL)
!     {
!       hashtab_T       *ht;
!       proptype_T      *prop = HI2PT(hi);
  
!       if (buf == NULL)
!       {
!           ht = global_proptypes;
!           VIM_CLEAR(global_proparray);
!       }
!       else
!       {
!           ht = buf->b_proptypes;
!           VIM_CLEAR(buf->b_proparray);
!       }
!       hash_remove(ht, hi, "prop type delete");
!       vim_free(prop);
  
!       // currently visibile text properties will disappear
!       redraw_all_later(UPD_CLEAR);
!       changed_window_setting_buf(buf == NULL ? curbuf : buf);
      }
  }
  
  /*
--- 1939,1966 ----
      }
  
      hi = find_prop_type_hi(name, buf);
!     if (hi == NULL)
!       return;
  
!     hashtab_T *ht;
!     proptype_T        *prop = HI2PT(hi);
  
!     if (buf == NULL)
!     {
!       ht = global_proptypes;
!       VIM_CLEAR(global_proparray);
!     }
!     else
!     {
!       ht = buf->b_proptypes;
!       VIM_CLEAR(buf->b_proparray);
      }
+     hash_remove(ht, hi, "prop type delete");
+     vim_free(prop);
+ 
+     // currently visibile text properties will disappear
+     redraw_all_later(UPD_CLEAR);
+     changed_window_setting_buf(buf == NULL ? curbuf : buf);
  }
  
  /*
***************
*** 1982,2016 ****
        semsg(_(e_invalid_argument_str), "\"\"");
        return;
      }
-     if (rettv_dict_alloc(rettv) == OK)
-     {
-       proptype_T  *prop = NULL;
-       buf_T       *buf = NULL;
  
!       if (argvars[1].v_type != VAR_UNKNOWN)
!       {
!           if (get_bufnr_from_arg(&argvars[1], &buf) == FAIL)
!               return;
!       }
  
!       prop = find_prop_type(name, buf);
!       if (prop != NULL)
!       {
!           dict_T *d = rettv->vval.v_dict;
  
!           if (prop->pt_hl_id > 0)
!               dict_add_string(d, "highlight", syn_id2name(prop->pt_hl_id));
!           dict_add_number(d, "priority", prop->pt_priority);
!           dict_add_number(d, "combine",
!                                  (prop->pt_flags & PT_FLAG_COMBINE) ? 1 : 0);
!           dict_add_number(d, "start_incl",
!                           (prop->pt_flags & PT_FLAG_INS_START_INCL) ? 1 : 0);
!           dict_add_number(d, "end_incl",
!                             (prop->pt_flags & PT_FLAG_INS_END_INCL) ? 1 : 0);
!           if (buf != NULL)
!               dict_add_number(d, "bufnr", buf->b_fnum);
!       }
      }
  }
  
      static void
--- 1982,2017 ----
        semsg(_(e_invalid_argument_str), "\"\"");
        return;
      }
  
!     if (rettv_dict_alloc(rettv) == FAIL)
!       return;
  
!     proptype_T  *prop = NULL;
!     buf_T         *buf = NULL;
  
!     if (argvars[1].v_type != VAR_UNKNOWN)
!     {
!       if (get_bufnr_from_arg(&argvars[1], &buf) == FAIL)
!           return;
      }
+ 
+     prop = find_prop_type(name, buf);
+     if (prop == NULL)
+       return;
+ 
+     dict_T *d = rettv->vval.v_dict;
+ 
+     if (prop->pt_hl_id > 0)
+       dict_add_string(d, "highlight", syn_id2name(prop->pt_hl_id));
+     dict_add_number(d, "priority", prop->pt_priority);
+     dict_add_number(d, "combine",
+           (prop->pt_flags & PT_FLAG_COMBINE) ? 1 : 0);
+     dict_add_number(d, "start_incl",
+           (prop->pt_flags & PT_FLAG_INS_START_INCL) ? 1 : 0);
+     dict_add_number(d, "end_incl",
+           (prop->pt_flags & PT_FLAG_INS_END_INCL) ? 1 : 0);
+     if (buf != NULL)
+       dict_add_number(d, "bufnr", buf->b_fnum);
  }
  
      static void
***************
*** 2040,2063 ****
  {
      buf_T *buf = NULL;
  
!     if (rettv_list_alloc(rettv) == OK)
      {
!       if (in_vim9script() && check_for_opt_dict_arg(argvars, 0) == FAIL)
            return;
- 
-       if (argvars[0].v_type != VAR_UNKNOWN)
-       {
-           if (get_bufnr_from_arg(&argvars[0], &buf) == FAIL)
-               return;
-       }
-       if (buf == NULL)
-       {
-           if (global_proptypes != NULL)
-               list_types(global_proptypes, rettv->vval.v_list);
-       }
-       else if (buf->b_proptypes != NULL)
-           list_types(buf->b_proptypes, rettv->vval.v_list);
      }
  }
  
  /*
--- 2041,2064 ----
  {
      buf_T *buf = NULL;
  
!     if (rettv_list_alloc(rettv) == FAIL)
!       return;
! 
!     if (in_vim9script() && check_for_opt_dict_arg(argvars, 0) == FAIL)
!       return;
! 
!     if (argvars[0].v_type != VAR_UNKNOWN)
      {
!       if (get_bufnr_from_arg(&argvars[0], &buf) == FAIL)
            return;
      }
+     if (buf == NULL)
+     {
+       if (global_proptypes != NULL)
+           list_types(global_proptypes, rettv->vval.v_list);
+     }
+     else if (buf->b_proptypes != NULL)
+       list_types(buf->b_proptypes, rettv->vval.v_list);
  }
  
  /*
*** ../vim-9.0.1244/src/time.c  2022-12-02 15:58:34.610705474 +0000
--- src/time.c  2023-01-25 21:02:57.835082030 +0000
***************
*** 302,348 ****
      curtime = vim_localtime(&seconds, &tmval);
      // MSVC returns NULL for an invalid value of seconds.
      if (curtime == NULL)
-       rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
-     else
      {
  # ifdef MSWIN
!       WCHAR       result_buf[256];
!       WCHAR       *wp;
  
!       wp = enc_to_utf16(p, NULL);
!       if (wp != NULL)
!           (void)wcsftime(result_buf, ARRAY_LENGTH(result_buf), wp, curtime);
!       else
!           result_buf[0] = NUL;
!       rettv->vval.v_string = utf16_to_enc(result_buf, NULL);
!       vim_free(wp);
  # else
!       char_u      result_buf[256];
!       vimconv_T   conv;
!       char_u      *enc;
! 
!       conv.vc_type = CONV_NONE;
!       enc = enc_locale();
!       convert_setup(&conv, p_enc, enc);
!       if (conv.vc_type != CONV_NONE)
!           p = string_convert(&conv, p, NULL);
!       if (p == NULL || strftime((char *)result_buf, sizeof(result_buf),
!                                                 (char *)p, curtime) == 0)
!           result_buf[0] = NUL;
! 
!       if (conv.vc_type != CONV_NONE)
!           vim_free(p);
!       convert_setup(&conv, enc, p_enc);
!       if (conv.vc_type != CONV_NONE)
!           rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
!       else
!           rettv->vval.v_string = vim_strsave(result_buf);
  
!       // Release conversion descriptors
!       convert_setup(&conv, NULL, NULL);
!       vim_free(enc);
  # endif
-     }
  }
  # endif
  
--- 302,349 ----
      curtime = vim_localtime(&seconds, &tmval);
      // MSVC returns NULL for an invalid value of seconds.
      if (curtime == NULL)
      {
+       rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
+       return;
+     }
+ 
  # ifdef MSWIN
!     WCHAR         result_buf[256];
!     WCHAR         *wp;
  
!     wp = enc_to_utf16(p, NULL);
!     if (wp != NULL)
!       (void)wcsftime(result_buf, ARRAY_LENGTH(result_buf), wp, curtime);
!     else
!       result_buf[0] = NUL;
!     rettv->vval.v_string = utf16_to_enc(result_buf, NULL);
!     vim_free(wp);
  # else
!     char_u        result_buf[256];
!     vimconv_T   conv;
!     char_u        *enc;
  
!     conv.vc_type = CONV_NONE;
!     enc = enc_locale();
!     convert_setup(&conv, p_enc, enc);
!     if (conv.vc_type != CONV_NONE)
!       p = string_convert(&conv, p, NULL);
!     if (p == NULL || strftime((char *)result_buf, sizeof(result_buf),
!               (char *)p, curtime) == 0)
!       result_buf[0] = NUL;
! 
!     if (conv.vc_type != CONV_NONE)
!       vim_free(p);
!     convert_setup(&conv, enc, p_enc);
!     if (conv.vc_type != CONV_NONE)
!       rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
!     else
!       rettv->vval.v_string = vim_strsave(result_buf);
! 
!     // Release conversion descriptors
!     convert_setup(&conv, NULL, NULL);
!     vim_free(enc);
  # endif
  }
  # endif
  
***************
*** 672,683 ****
  {
      timer_T *timer;
  
!     if (id >= 0)
!     {
!       FOR_ALL_TIMERS(timer)
!           if (timer->tr_id == id)
!               return timer;
!     }
      return NULL;
  }
  
--- 673,684 ----
  {
      timer_T *timer;
  
!     if (id < 0)
!       return NULL;
! 
!     FOR_ALL_TIMERS(timer)
!       if (timer->tr_id == id)
!           return timer;
      return NULL;
  }
  
***************
*** 791,797 ****
  {
      if (timer == NULL)
        return FALSE;
!     for (timer_T *t = first_timer; t != NULL; t = t->tr_next)
        if (t == timer)
            return TRUE;
      return FALSE;
--- 792,800 ----
  {
      if (timer == NULL)
        return FALSE;
! 
!     timer_T *t;
!     FOR_ALL_TIMERS(t)
        if (t == timer)
            return TRUE;
      return FALSE;
***************
*** 848,862 ****
        return;
  
      if (argvars[0].v_type != VAR_NUMBER)
-       emsg(_(e_number_expected));
-     else
      {
!       int     paused = (int)tv_get_bool(&argvars[1]);
! 
!       timer = find_timer((int)tv_get_number(&argvars[0]));
!       if (timer != NULL)
!           timer->tr_paused = paused;
      }
  }
  
  /*
--- 851,866 ----
        return;
  
      if (argvars[0].v_type != VAR_NUMBER)
      {
!       emsg(_(e_number_expected));
!       return;
      }
+ 
+     int       paused = (int)tv_get_bool(&argvars[1]);
+ 
+     timer = find_timer((int)tv_get_number(&argvars[0]));
+     if (timer != NULL)
+       timer->tr_paused = paused;
  }
  
  /*
***************
*** 904,917 ****
  
      timer = create_timer(msec, repeat);
      if (timer == NULL)
-       free_callback(&callback);
-     else
      {
!       set_callback(&timer->tr_callback, &callback);
!       if (callback.cb_free_name)
!           vim_free(callback.cb_name);
!       rettv->vval.v_number = (varnumber_T)timer->tr_id;
      }
  }
  
  /*
--- 908,921 ----
  
      timer = create_timer(msec, repeat);
      if (timer == NULL)
      {
!       free_callback(&callback);
!       return;
      }
+     set_callback(&timer->tr_callback, &callback);
+     if (callback.cb_free_name)
+       vim_free(callback.cb_name);
+     rettv->vval.v_number = (varnumber_T)timer->tr_id;
  }
  
  /*
***************
*** 1019,1046 ****
      static struct timeval     start;
      struct timeval            now;
  
!     if (time_fd != NULL)
      {
-       if (strstr(mesg, "STARTING") != NULL)
-       {
-           gettimeofday(&start, NULL);
-           prev_timeval = start;
-           fprintf(time_fd, "\n\ntimes in msec\n");
-           fprintf(time_fd, " clock   self+sourced   self:  sourced script\n");
-           fprintf(time_fd, " clock   elapsed:              other lines\n\n");
-       }
-       gettimeofday(&now, NULL);
-       time_diff(&start, &now);
-       if (((struct timeval *)tv_start) != NULL)
-       {
-           fprintf(time_fd, "  ");
-           time_diff(((struct timeval *)tv_start), &now);
-       }
        fprintf(time_fd, "  ");
!       time_diff(&prev_timeval, &now);
!       prev_timeval = now;
!       fprintf(time_fd, ": %s\n", mesg);
      }
  }
  # endif       // STARTUPTIME
  #endif // FEAT_EVAL
--- 1023,1050 ----
      static struct timeval     start;
      struct timeval            now;
  
!     if (time_fd == NULL)
!       return;
! 
!     if (strstr(mesg, "STARTING") != NULL)
!     {
!       gettimeofday(&start, NULL);
!       prev_timeval = start;
!       fprintf(time_fd, "\n\ntimes in msec\n");
!       fprintf(time_fd, " clock   self+sourced   self:  sourced script\n");
!       fprintf(time_fd, " clock   elapsed:              other lines\n\n");
!     }
!     gettimeofday(&now, NULL);
!     time_diff(&start, &now);
!     if (((struct timeval *)tv_start) != NULL)
      {
        fprintf(time_fd, "  ");
!       time_diff(((struct timeval *)tv_start), &now);
      }
+     fprintf(time_fd, "  ");
+     time_diff(&prev_timeval, &now);
+     prev_timeval = now;
+     fprintf(time_fd, ": %s\n", mesg);
  }
  # endif       // STARTUPTIME
  #endif // FEAT_EVAL
*** ../vim-9.0.1244/src/typval.c        2023-01-02 20:32:18.425749782 +0000
--- src/typval.c        2023-01-25 21:02:57.835082030 +0000
***************
*** 52,108 ****
      void
  free_tv(typval_T *varp)
  {
!     if (varp != NULL)
      {
!       switch (varp->v_type)
!       {
!           case VAR_FUNC:
!               func_unref(varp->vval.v_string);
!               // FALLTHROUGH
!           case VAR_STRING:
!               vim_free(varp->vval.v_string);
!               break;
!           case VAR_PARTIAL:
!               partial_unref(varp->vval.v_partial);
!               break;
!           case VAR_BLOB:
!               blob_unref(varp->vval.v_blob);
!               break;
!           case VAR_LIST:
!               list_unref(varp->vval.v_list);
!               break;
!           case VAR_DICT:
!               dict_unref(varp->vval.v_dict);
!               break;
!           case VAR_JOB:
  #ifdef FEAT_JOB_CHANNEL
!               job_unref(varp->vval.v_job);
!               break;
  #endif
!           case VAR_CHANNEL:
  #ifdef FEAT_JOB_CHANNEL
!               channel_unref(varp->vval.v_channel);
!               break;
  #endif
!           case VAR_CLASS:
!               class_unref(varp->vval.v_class);
!               break;
!           case VAR_OBJECT:
!               object_unref(varp->vval.v_object);
!               break;
  
!           case VAR_NUMBER:
!           case VAR_FLOAT:
!           case VAR_ANY:
!           case VAR_UNKNOWN:
!           case VAR_VOID:
!           case VAR_BOOL:
!           case VAR_SPECIAL:
!           case VAR_INSTR:
!               break;
!       }
!       vim_free(varp);
      }
  }
  
  /*
--- 52,108 ----
      void
  free_tv(typval_T *varp)
  {
!     if (varp == NULL)
!       return;
! 
!     switch (varp->v_type)
      {
!       case VAR_FUNC:
!           func_unref(varp->vval.v_string);
!           // FALLTHROUGH
!       case VAR_STRING:
!           vim_free(varp->vval.v_string);
!           break;
!       case VAR_PARTIAL:
!           partial_unref(varp->vval.v_partial);
!           break;
!       case VAR_BLOB:
!           blob_unref(varp->vval.v_blob);
!           break;
!       case VAR_LIST:
!           list_unref(varp->vval.v_list);
!           break;
!       case VAR_DICT:
!           dict_unref(varp->vval.v_dict);
!           break;
!       case VAR_JOB:
  #ifdef FEAT_JOB_CHANNEL
!           job_unref(varp->vval.v_job);
!           break;
  #endif
!       case VAR_CHANNEL:
  #ifdef FEAT_JOB_CHANNEL
!           channel_unref(varp->vval.v_channel);
!           break;
  #endif
!       case VAR_CLASS:
!           class_unref(varp->vval.v_class);
!           break;
!       case VAR_OBJECT:
!           object_unref(varp->vval.v_object);
!           break;
  
!       case VAR_NUMBER:
!       case VAR_FLOAT:
!       case VAR_ANY:
!       case VAR_UNKNOWN:
!       case VAR_VOID:
!       case VAR_BOOL:
!       case VAR_SPECIAL:
!       case VAR_INSTR:
!           break;
      }
+     vim_free(varp);
  }
  
  /*
***************
*** 111,180 ****
      void
  clear_tv(typval_T *varp)
  {
!     if (varp != NULL)
      {
!       switch (varp->v_type)
!       {
!           case VAR_FUNC:
!               func_unref(varp->vval.v_string);
!               // FALLTHROUGH
!           case VAR_STRING:
!               VIM_CLEAR(varp->vval.v_string);
!               break;
!           case VAR_PARTIAL:
!               partial_unref(varp->vval.v_partial);
!               varp->vval.v_partial = NULL;
!               break;
!           case VAR_BLOB:
!               blob_unref(varp->vval.v_blob);
!               varp->vval.v_blob = NULL;
!               break;
!           case VAR_LIST:
!               list_unref(varp->vval.v_list);
!               varp->vval.v_list = NULL;
!               break;
!           case VAR_DICT:
!               dict_unref(varp->vval.v_dict);
!               varp->vval.v_dict = NULL;
!               break;
!           case VAR_NUMBER:
!           case VAR_BOOL:
!           case VAR_SPECIAL:
!               varp->vval.v_number = 0;
!               break;
!           case VAR_FLOAT:
!               varp->vval.v_float = 0.0;
!               break;
!           case VAR_JOB:
  #ifdef FEAT_JOB_CHANNEL
!               job_unref(varp->vval.v_job);
!               varp->vval.v_job = NULL;
  #endif
!               break;
!           case VAR_CHANNEL:
  #ifdef FEAT_JOB_CHANNEL
!               channel_unref(varp->vval.v_channel);
!               varp->vval.v_channel = NULL;
  #endif
!               break;
!           case VAR_INSTR:
!               VIM_CLEAR(varp->vval.v_instr);
!               break;
!           case VAR_CLASS:
!               class_unref(varp->vval.v_class);
!               varp->vval.v_class = NULL;
!               break;
!           case VAR_OBJECT:
!               object_unref(varp->vval.v_object);
!               varp->vval.v_object = NULL;
!               break;
!           case VAR_UNKNOWN:
!           case VAR_ANY:
!           case VAR_VOID:
!               break;
!       }
!       varp->v_lock = 0;
      }
  }
  
  /*
--- 111,180 ----
      void
  clear_tv(typval_T *varp)
  {
!     if (varp == NULL)
!       return;
! 
!     switch (varp->v_type)
      {
!       case VAR_FUNC:
!           func_unref(varp->vval.v_string);
!           // FALLTHROUGH
!       case VAR_STRING:
!           VIM_CLEAR(varp->vval.v_string);
!           break;
!       case VAR_PARTIAL:
!           partial_unref(varp->vval.v_partial);
!           varp->vval.v_partial = NULL;
!           break;
!       case VAR_BLOB:
!           blob_unref(varp->vval.v_blob);
!           varp->vval.v_blob = NULL;
!           break;
!       case VAR_LIST:
!           list_unref(varp->vval.v_list);
!           varp->vval.v_list = NULL;
!           break;
!       case VAR_DICT:
!           dict_unref(varp->vval.v_dict);
!           varp->vval.v_dict = NULL;
!           break;
!       case VAR_NUMBER:
!       case VAR_BOOL:
!       case VAR_SPECIAL:
!           varp->vval.v_number = 0;
!           break;
!       case VAR_FLOAT:
!           varp->vval.v_float = 0.0;
!           break;
!       case VAR_JOB:
  #ifdef FEAT_JOB_CHANNEL
!           job_unref(varp->vval.v_job);
!           varp->vval.v_job = NULL;
  #endif
!           break;
!       case VAR_CHANNEL:
  #ifdef FEAT_JOB_CHANNEL
!           channel_unref(varp->vval.v_channel);
!           varp->vval.v_channel = NULL;
  #endif
!           break;
!       case VAR_INSTR:
!           VIM_CLEAR(varp->vval.v_instr);
!           break;
!       case VAR_CLASS:
!           class_unref(varp->vval.v_class);
!           varp->vval.v_class = NULL;
!           break;
!       case VAR_OBJECT:
!           object_unref(varp->vval.v_object);
!           varp->vval.v_object = NULL;
!           break;
!       case VAR_UNKNOWN:
!       case VAR_ANY:
!       case VAR_VOID:
!           break;
      }
+     varp->v_lock = 0;
  }
  
  /*
*** ../vim-9.0.1244/src/version.c       2023-01-25 17:34:38.013795178 +0000
--- src/version.c       2023-01-25 21:03:52.359067883 +0000
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     1245,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
46. Your wife makes a new rule: "The computer cannot come to bed."

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            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/20230125210614.820E11C065A%40moolenaar.net.

Raspunde prin e-mail lui