]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.1.1437: code to handle callbacks is duplicated v8.1.1437
authorBram Moolenaar <Bram@vim.org>
Sat, 1 Jun 2019 11:28:35 +0000 (13:28 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 1 Jun 2019 11:28:35 +0000 (13:28 +0200)
Problem:    Code to handle callbacks is duplicated.
Solution:   Add callback_T and functions to deal with it.

13 files changed:
src/buffer.c
src/change.c
src/channel.c
src/eval.c
src/evalfunc.c
src/ex_cmds2.c
src/popupwin.c
src/proto/channel.pro
src/proto/evalfunc.pro
src/proto/userfunc.pro
src/structs.h
src/userfunc.c
src/version.c

index 3bfb6396ba976964fbbecc70e234ad0bf3271ae1..66f6fc654c79003de7a7adb847c4ceaf46210689 100644 (file)
@@ -862,7 +862,7 @@ free_buffer(buf_T *buf)
 #endif
 #ifdef FEAT_JOB_CHANNEL
     vim_free(buf->b_prompt_text);
-    free_callback(buf->b_prompt_callback, buf->b_prompt_partial);
+    free_callback(&buf->b_prompt_callback);
 #endif
 
     buf_hashtab_remove(buf);
index b1a56ae4c00facdb78430ff7596a94d1173d82b5..07985ee62ab1eca08d29f11039f014a07d7010fb 100644 (file)
@@ -270,36 +270,34 @@ may_record_change(
     void
 f_listener_add(typval_T *argvars, typval_T *rettv)
 {
-    char_u     *callback;
-    partial_T  *partial;
+    callback_T callback;
     listener_T *lnr;
     buf_T      *buf = curbuf;
 
-    callback = get_callback(&argvars[0], &partial);
-    if (callback == NULL)
+    callback = get_callback(&argvars[0]);
+    if (callback.cb_name == NULL)
        return;
 
     if (argvars[1].v_type != VAR_UNKNOWN)
     {
        buf = get_buf_arg(&argvars[1]);
        if (buf == NULL)
+       {
+           free_callback(&callback);
            return;
+       }
     }
 
     lnr = ALLOC_CLEAR_ONE(listener_T);
     if (lnr == NULL)
     {
-       free_callback(callback, partial);
+       free_callback(&callback);
        return;
     }
     lnr->lr_next = buf->b_listener;
     buf->b_listener = lnr;
 
-    if (partial == NULL)
-       lnr->lr_callback = vim_strsave(callback);
-    else
-       lnr->lr_callback = callback;  // pointer into the partial
-    lnr->lr_partial = partial;
+    set_callback(&lnr->lr_callback, &callback);
 
     lnr->lr_id = ++next_listener_id;
     rettv->vval.v_number = lnr->lr_id;
@@ -344,7 +342,7 @@ f_listener_remove(typval_T *argvars, typval_T *rettv UNUSED)
                    prev->lr_next = lnr->lr_next;
                else
                    buf->b_listener = lnr->lr_next;
-               free_callback(lnr->lr_callback, lnr->lr_partial);
+               free_callback(&lnr->lr_callback);
                vim_free(lnr);
            }
            prev = lnr;
@@ -418,8 +416,8 @@ invoke_listeners(buf_T *buf)
 
     for (lnr = buf->b_listener; lnr != NULL; lnr = lnr->lr_next)
     {
-       call_func(lnr->lr_callback, -1, &rettv,
-                  5, argv, NULL, 0L, 0L, &dummy, TRUE, lnr->lr_partial, NULL);
+       call_callback(&lnr->lr_callback, -1, &rettv,
+                                   5, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
        clear_tv(&rettv);
     }
 
index 558e36d336cd1698d5df36974326b7b25e933e59..5ace0713d198118f35c55b426a80b254e22abba7 100644 (file)
@@ -348,7 +348,7 @@ channel_still_useful(channel_T *channel)
        return FALSE;
 
     /* If there is a close callback it may still need to be invoked. */
-    if (channel->ch_close_cb != NULL)
+    if (channel->ch_close_cb.cb_name != NULL)
        return TRUE;
 
     /* If reading from or a buffer it's still useful. */
@@ -366,12 +366,12 @@ channel_still_useful(channel_T *channel)
     has_err_msg = channel->ch_part[PART_ERR].ch_fd != INVALID_FD
                  || channel->ch_part[PART_ERR].ch_head.rq_next != NULL
                  || channel->ch_part[PART_ERR].ch_json_head.jq_next != NULL;
-    return (channel->ch_callback != NULL && (has_sock_msg
+    return (channel->ch_callback.cb_name != NULL && (has_sock_msg
                || has_out_msg || has_err_msg))
-           || ((channel->ch_part[PART_OUT].ch_callback != NULL
+           || ((channel->ch_part[PART_OUT].ch_callback.cb_name != NULL
                       || channel->ch_part[PART_OUT].ch_bufref.br_buf != NULL)
                    && has_out_msg)
-           || ((channel->ch_part[PART_ERR].ch_callback != NULL
+           || ((channel->ch_part[PART_ERR].ch_callback.cb_name != NULL
                       || channel->ch_part[PART_ERR].ch_bufref.br_buf != NULL)
                    && has_err_msg);
 }
@@ -1178,29 +1178,36 @@ find_buffer(char_u *name, int err, int msg)
     return buf;
 }
 
+/*
+ * Copy callback from "src" to "dest", incrementing the refcounts.
+ */
     static void
-set_callback(
-       char_u **cbp,
-       partial_T **pp,
-       char_u *callback,
-       partial_T *partial)
+copy_callback(callback_T *dest, callback_T *src)
 {
-    free_callback(*cbp, *pp);
-    if (callback != NULL && *callback != NUL)
+    dest->cb_partial = src->cb_partial;
+    if (dest->cb_partial != NULL)
     {
-       if (partial != NULL)
-           *cbp = partial_name(partial);
-       else
-       {
-           *cbp = vim_strsave(callback);
-           func_ref(*cbp);
-       }
+       dest->cb_name = src->cb_name;
+       dest->cb_free_name = FALSE;
+       ++dest->cb_partial->pt_refcount;
+    }
+    else
+    {
+       dest->cb_name = vim_strsave(src->cb_name);
+       dest->cb_free_name = TRUE;
+       func_ref(src->cb_name);
     }
+}
+
+    static void
+free_set_callback(callback_T *cbp, callback_T *callback)
+{
+    free_callback(cbp);
+
+    if (callback->cb_name != NULL && *callback->cb_name != NUL)
+       copy_callback(cbp, callback);
     else
-       *cbp = NULL;
-    *pp = partial;
-    if (partial != NULL)
-       ++partial->pt_refcount;
+       cbp->cb_name = NULL;
 }
 
 /*
@@ -1233,19 +1240,15 @@ channel_set_options(channel_T *channel, jobopt_T *opt)
        channel->ch_part[PART_IN].ch_block_write = 1;
 
     if (opt->jo_set & JO_CALLBACK)
-       set_callback(&channel->ch_callback, &channel->ch_partial,
-                                          opt->jo_callback, opt->jo_partial);
+       free_set_callback(&channel->ch_callback, &opt->jo_callback);
     if (opt->jo_set & JO_OUT_CALLBACK)
-       set_callback(&channel->ch_part[PART_OUT].ch_callback,
-               &channel->ch_part[PART_OUT].ch_partial,
-               opt->jo_out_cb, opt->jo_out_partial);
+       free_set_callback(&channel->ch_part[PART_OUT].ch_callback,
+                                                             &opt->jo_out_cb);
     if (opt->jo_set & JO_ERR_CALLBACK)
-       set_callback(&channel->ch_part[PART_ERR].ch_callback,
-               &channel->ch_part[PART_ERR].ch_partial,
-               opt->jo_err_cb, opt->jo_err_partial);
+       free_set_callback(&channel->ch_part[PART_ERR].ch_callback,
+                                                             &opt->jo_err_cb);
     if (opt->jo_set & JO_CLOSE_CALLBACK)
-       set_callback(&channel->ch_close_cb, &channel->ch_close_partial,
-               opt->jo_close_cb, opt->jo_close_partial);
+       free_set_callback(&channel->ch_close_cb, &opt->jo_close_cb);
     channel->ch_drop_never = opt->jo_drop_never;
 
     if ((opt->jo_set & JO_OUT_IO) && opt->jo_io[PART_OUT] == JIO_BUFFER)
@@ -1349,8 +1352,7 @@ channel_set_options(channel_T *channel, jobopt_T *opt)
 channel_set_req_callback(
        channel_T   *channel,
        ch_part_T   part,
-       char_u      *callback,
-       partial_T   *partial,
+       callback_T  *callback,
        int         id)
 {
     cbq_T *head = &channel->ch_part[part].ch_cb_head;
@@ -1358,17 +1360,7 @@ channel_set_req_callback(
 
     if (item != NULL)
     {
-       item->cq_partial = partial;
-       if (partial != NULL)
-       {
-           ++partial->pt_refcount;
-           item->cq_callback = callback;
-       }
-       else
-       {
-           item->cq_callback = vim_strsave(callback);
-           func_ref(item->cq_callback);
-       }
+       copy_callback(&item->cq_callback, callback);
        item->cq_seq_nr = id;
        item->cq_prev = head->cq_prev;
        head->cq_prev = item;
@@ -1638,8 +1630,7 @@ channel_write_new_lines(buf_T *buf)
  * This does not redraw but sets channel_need_redraw;
  */
     static void
-invoke_callback(channel_T *channel, char_u *callback, partial_T *partial,
-                                                              typval_T *argv)
+invoke_callback(channel_T *channel, callback_T *callback, typval_T *argv)
 {
     typval_T   rettv;
     int                dummy;
@@ -1650,8 +1641,8 @@ invoke_callback(channel_T *channel, char_u *callback, partial_T *partial,
     argv[0].v_type = VAR_CHANNEL;
     argv[0].vval.v_channel = channel;
 
-    call_func(callback, -1, &rettv, 2, argv, NULL,
-                                         0L, 0L, &dummy, TRUE, partial, NULL);
+    call_callback(callback, -1, &rettv, 2, argv, NULL,
+                                                  0L, 0L, &dummy, TRUE, NULL);
     clear_tv(&rettv);
     channel_need_redraw = TRUE;
 }
@@ -2414,12 +2405,12 @@ invoke_one_time_callback(
        typval_T    *argv)
 {
     ch_log(channel, "Invoking one-time callback %s",
-                                                  (char *)item->cq_callback);
+                                           (char *)item->cq_callback.cb_name);
     /* Remove the item from the list first, if the callback
      * invokes ch_close() the list will be cleared. */
     remove_cb_node(cbhead, item);
-    invoke_callback(channel, item->cq_callback, item->cq_partial, argv);
-    free_callback(item->cq_callback, item->cq_partial);
+    invoke_callback(channel, &item->cq_callback, argv);
+    free_callback(&item->cq_callback);
     vim_free(item);
 }
 
@@ -2553,8 +2544,7 @@ may_invoke_callback(channel_T *channel, ch_part_T part)
     ch_mode_T  ch_mode = ch_part->ch_mode;
     cbq_T      *cbhead = &ch_part->ch_cb_head;
     cbq_T      *cbitem;
-    char_u     *callback = NULL;
-    partial_T  *partial = NULL;
+    callback_T *callback = NULL;
     buf_T      *buffer = NULL;
     char_u     *p;
 
@@ -2567,20 +2557,11 @@ may_invoke_callback(channel_T *channel, ch_part_T part)
        if (cbitem->cq_seq_nr == 0)
            break;
     if (cbitem != NULL)
-    {
-       callback = cbitem->cq_callback;
-       partial = cbitem->cq_partial;
-    }
-    else if (ch_part->ch_callback != NULL)
-    {
-       callback = ch_part->ch_callback;
-       partial = ch_part->ch_partial;
-    }
-    else
-    {
-       callback = channel->ch_callback;
-       partial = channel->ch_partial;
-    }
+       callback = &cbitem->cq_callback;
+    else if (ch_part->ch_callback.cb_name != NULL)
+       callback = &ch_part->ch_callback;
+    else if (channel->ch_callback.cb_name != NULL)
+       callback = &channel->ch_callback;
 
     buffer = ch_part->ch_bufref.br_buf;
     if (buffer != NULL && (!bufref_valid(&ch_part->ch_bufref)
@@ -2642,7 +2623,7 @@ may_invoke_callback(channel_T *channel, ch_part_T part)
        {
            /* If there is a close callback it may use ch_read() to get the
             * messages. */
-           if (channel->ch_close_cb == NULL && !channel->ch_drop_never)
+           if (channel->ch_close_cb.cb_name == NULL && !channel->ch_drop_never)
                drop_messages(channel, part);
            return FALSE;
        }
@@ -2761,8 +2742,8 @@ may_invoke_callback(channel_T *channel, ch_part_T part)
            {
                /* invoke the channel callback */
                ch_log(channel, "Invoking channel callback %s",
-                                                           (char *)callback);
-               invoke_callback(channel, callback, partial, argv);
+                                                   (char *)callback->cb_name);
+               invoke_callback(channel, callback, argv);
            }
        }
     }
@@ -2956,18 +2937,18 @@ channel_close(channel_T *channel, int invoke_close_cb)
        ch_part_T       part;
 
        /* Invoke callbacks and flush buffers before the close callback. */
-       if (channel->ch_close_cb != NULL)
+       if (channel->ch_close_cb.cb_name != NULL)
            ch_log(channel,
                     "Invoking callbacks and flushing buffers before closing");
        for (part = PART_SOCK; part < PART_IN; ++part)
        {
-           if (channel->ch_close_cb != NULL
+           if (channel->ch_close_cb.cb_name != NULL
                            || channel->ch_part[part].ch_bufref.br_buf != NULL)
            {
                /* Increment the refcount to avoid the channel being freed
                 * halfway. */
                ++channel->ch_refcount;
-               if (channel->ch_close_cb == NULL)
+               if (channel->ch_close_cb.cb_name == NULL)
                    ch_log(channel, "flushing %s buffers before closing",
                                                             part_names[part]);
                while (may_invoke_callback(channel, part))
@@ -2976,7 +2957,7 @@ channel_close(channel_T *channel, int invoke_close_cb)
            }
        }
 
-       if (channel->ch_close_cb != NULL)
+       if (channel->ch_close_cb.cb_name != NULL)
        {
              typval_T  argv[1];
              typval_T  rettv;
@@ -2986,19 +2967,16 @@ channel_close(channel_T *channel, int invoke_close_cb)
               * halfway. */
              ++channel->ch_refcount;
              ch_log(channel, "Invoking close callback %s",
-                                               (char *)channel->ch_close_cb);
+                                        (char *)channel->ch_close_cb.cb_name);
              argv[0].v_type = VAR_CHANNEL;
              argv[0].vval.v_channel = channel;
-             call_func(channel->ch_close_cb, -1,
-                          &rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE,
-                          channel->ch_close_partial, NULL);
+             call_callback(&channel->ch_close_cb, -1,
+                          &rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
              clear_tv(&rettv);
              channel_need_redraw = TRUE;
 
              /* the callback is only called once */
-             free_callback(channel->ch_close_cb, channel->ch_close_partial);
-             channel->ch_close_cb = NULL;
-             channel->ch_close_partial = NULL;
+             free_callback(&channel->ch_close_cb);
 
              if (channel_need_redraw)
              {
@@ -3061,7 +3039,7 @@ channel_clear_one(channel_T *channel, ch_part_T part)
        cbq_T *node = cb_head->cq_next;
 
        remove_cb_node(cb_head, node);
-       free_callback(node->cq_callback, node->cq_partial);
+       free_callback(&node->cq_callback);
        vim_free(node);
     }
 
@@ -3071,9 +3049,7 @@ channel_clear_one(channel_T *channel, ch_part_T part)
        remove_json_node(json_head, json_head->jq_next);
     }
 
-    free_callback(ch_part->ch_callback, ch_part->ch_partial);
-    ch_part->ch_callback = NULL;
-    ch_part->ch_partial = NULL;
+    free_callback(&ch_part->ch_callback);
 
     while (ch_part->ch_writeque.wq_next != NULL)
        remove_from_writeque(&ch_part->ch_writeque,
@@ -3092,12 +3068,8 @@ channel_clear(channel_T *channel)
     channel_clear_one(channel, PART_OUT);
     channel_clear_one(channel, PART_ERR);
     channel_clear_one(channel, PART_IN);
-    free_callback(channel->ch_callback, channel->ch_partial);
-    channel->ch_callback = NULL;
-    channel->ch_partial = NULL;
-    free_callback(channel->ch_close_cb, channel->ch_close_partial);
-    channel->ch_close_cb = NULL;
-    channel->ch_close_partial = NULL;
+    free_callback(&channel->ch_callback);
+    free_callback(&channel->ch_close_cb);
 }
 
 #if defined(EXITFREE) || defined(PROTO)
@@ -3991,19 +3963,18 @@ send_common(
     /* Set the callback. An empty callback means no callback and not reading
      * the response. With "ch_evalexpr()" and "ch_evalraw()" a callback is not
      * allowed. */
-    if (opt->jo_callback != NULL && *opt->jo_callback != NUL)
+    if (opt->jo_callback.cb_name != NULL && *opt->jo_callback.cb_name != NUL)
     {
        if (eval)
        {
            semsg(_("E917: Cannot use a callback with %s()"), fun);
            return NULL;
        }
-       channel_set_req_callback(channel, *part_read,
-                                      opt->jo_callback, opt->jo_partial, id);
+       channel_set_req_callback(channel, *part_read, &opt->jo_callback, id);
     }
 
     if (channel_send(channel, part_send, text, len, fun) == OK
-                                                 && opt->jo_callback == NULL)
+                                          && opt->jo_callback.cb_name == NULL)
        return channel;
     return NULL;
 }
@@ -4559,26 +4530,26 @@ clear_job_options(jobopt_T *opt)
     void
 free_job_options(jobopt_T *opt)
 {
-    if (opt->jo_partial != NULL)
-       partial_unref(opt->jo_partial);
-    else if (opt->jo_callback != NULL)
-       func_unref(opt->jo_callback);
-    if (opt->jo_out_partial != NULL)
-       partial_unref(opt->jo_out_partial);
-    else if (opt->jo_out_cb != NULL)
-       func_unref(opt->jo_out_cb);
-    if (opt->jo_err_partial != NULL)
-       partial_unref(opt->jo_err_partial);
-    else if (opt->jo_err_cb != NULL)
-       func_unref(opt->jo_err_cb);
-    if (opt->jo_close_partial != NULL)
-       partial_unref(opt->jo_close_partial);
-    else if (opt->jo_close_cb != NULL)
-       func_unref(opt->jo_close_cb);
-    if (opt->jo_exit_partial != NULL)
-       partial_unref(opt->jo_exit_partial);
-    else if (opt->jo_exit_cb != NULL)
-       func_unref(opt->jo_exit_cb);
+    if (opt->jo_callback.cb_partial != NULL)
+       partial_unref(opt->jo_callback.cb_partial);
+    else if (opt->jo_callback.cb_name != NULL)
+       func_unref(opt->jo_callback.cb_name);
+    if (opt->jo_out_cb.cb_partial != NULL)
+       partial_unref(opt->jo_out_cb.cb_partial);
+    else if (opt->jo_out_cb.cb_name != NULL)
+       func_unref(opt->jo_out_cb.cb_name);
+    if (opt->jo_err_cb.cb_partial != NULL)
+       partial_unref(opt->jo_err_cb.cb_partial);
+    else if (opt->jo_err_cb.cb_name != NULL)
+       func_unref(opt->jo_err_cb.cb_name);
+    if (opt->jo_close_cb.cb_partial != NULL)
+       partial_unref(opt->jo_close_cb.cb_partial);
+    else if (opt->jo_close_cb.cb_name != NULL)
+       func_unref(opt->jo_close_cb.cb_name);
+    if (opt->jo_exit_cb.cb_partial != NULL)
+       partial_unref(opt->jo_exit_cb.cb_partial);
+    else if (opt->jo_exit_cb.cb_name != NULL)
+       func_unref(opt->jo_exit_cb.cb_name);
     if (opt->jo_env != NULL)
        dict_unref(opt->jo_env);
 }
@@ -4771,8 +4742,8 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported, int supported2)
                if (!(supported & JO_CALLBACK))
                    break;
                opt->jo_set |= JO_CALLBACK;
-               opt->jo_callback = get_callback(item, &opt->jo_partial);
-               if (opt->jo_callback == NULL)
+               opt->jo_callback = get_callback(item);
+               if (opt->jo_callback.cb_name == NULL)
                {
                    semsg(_(e_invargval), "callback");
                    return FAIL;
@@ -4783,8 +4754,8 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported, int supported2)
                if (!(supported & JO_OUT_CALLBACK))
                    break;
                opt->jo_set |= JO_OUT_CALLBACK;
-               opt->jo_out_cb = get_callback(item, &opt->jo_out_partial);
-               if (opt->jo_out_cb == NULL)
+               opt->jo_out_cb = get_callback(item);
+               if (opt->jo_out_cb.cb_name == NULL)
                {
                    semsg(_(e_invargval), "out_cb");
                    return FAIL;
@@ -4795,8 +4766,8 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported, int supported2)
                if (!(supported & JO_ERR_CALLBACK))
                    break;
                opt->jo_set |= JO_ERR_CALLBACK;
-               opt->jo_err_cb = get_callback(item, &opt->jo_err_partial);
-               if (opt->jo_err_cb == NULL)
+               opt->jo_err_cb = get_callback(item);
+               if (opt->jo_err_cb.cb_name == NULL)
                {
                    semsg(_(e_invargval), "err_cb");
                    return FAIL;
@@ -4807,8 +4778,8 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported, int supported2)
                if (!(supported & JO_CLOSE_CALLBACK))
                    break;
                opt->jo_set |= JO_CLOSE_CALLBACK;
-               opt->jo_close_cb = get_callback(item, &opt->jo_close_partial);
-               if (opt->jo_close_cb == NULL)
+               opt->jo_close_cb = get_callback(item);
+               if (opt->jo_close_cb.cb_name == NULL)
                {
                    semsg(_(e_invargval), "close_cb");
                    return FAIL;
@@ -4833,8 +4804,8 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported, int supported2)
                if (!(supported & JO_EXIT_CB))
                    break;
                opt->jo_set |= JO_EXIT_CB;
-               opt->jo_exit_cb = get_callback(item, &opt->jo_exit_partial);
-               if (opt->jo_exit_cb == NULL)
+               opt->jo_exit_cb = get_callback(item);
+               if (opt->jo_exit_cb.cb_name == NULL)
                {
                    semsg(_(e_invargval), "exit_cb");
                    return FAIL;
@@ -5201,7 +5172,7 @@ job_free_contents(job_T *job)
 #ifdef MSWIN
     vim_free(job->jv_tty_type);
 #endif
-    free_callback(job->jv_exit_cb, job->jv_exit_partial);
+    free_callback(&job->jv_exit_cb);
     if (job->jv_argv != NULL)
     {
        for (i = 0; job->jv_argv[i] != NULL; i++)
@@ -5289,7 +5260,7 @@ job_free_all(void)
 job_need_end_check(job_T *job)
 {
     return job->jv_status == JOB_STARTED
-                  && (job->jv_stoponexit != NULL || job->jv_exit_cb != NULL);
+           && (job->jv_stoponexit != NULL || job->jv_exit_cb.cb_name != NULL);
 }
 
 /*
@@ -5465,22 +5436,22 @@ job_cleanup(job_T *job)
     if (job->jv_channel != NULL)
        ch_close_part(job->jv_channel, PART_IN);
 
-    if (job->jv_exit_cb != NULL)
+    if (job->jv_exit_cb.cb_name != NULL)
     {
        typval_T        argv[3];
        typval_T        rettv;
        int             dummy;
 
        /* Invoke the exit callback. Make sure the refcount is > 0. */
-       ch_log(job->jv_channel, "Invoking exit callback %s", job->jv_exit_cb);
+       ch_log(job->jv_channel, "Invoking exit callback %s",
+                                                     job->jv_exit_cb.cb_name);
        ++job->jv_refcount;
        argv[0].v_type = VAR_JOB;
        argv[0].vval.v_job = job;
        argv[1].v_type = VAR_NUMBER;
        argv[1].vval.v_number = job->jv_exitval;
-       call_func(job->jv_exit_cb, -1,
-           &rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE,
-           job->jv_exit_partial, NULL);
+       call_callback(&job->jv_exit_cb, -1,
+                           &rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
        clear_tv(&rettv);
        --job->jv_refcount;
        channel_need_redraw = TRUE;
@@ -5622,26 +5593,14 @@ job_set_options(job_T *job, jobopt_T *opt)
     }
     if (opt->jo_set & JO_EXIT_CB)
     {
-       free_callback(job->jv_exit_cb, job->jv_exit_partial);
-       if (opt->jo_exit_cb == NULL || *opt->jo_exit_cb == NUL)
+       free_callback(&job->jv_exit_cb);
+       if (opt->jo_exit_cb.cb_name == NULL || *opt->jo_exit_cb.cb_name == NUL)
        {
-           job->jv_exit_cb = NULL;
-           job->jv_exit_partial = NULL;
+           job->jv_exit_cb.cb_name = NULL;
+           job->jv_exit_cb.cb_partial = NULL;
        }
        else
-       {
-           job->jv_exit_partial = opt->jo_exit_partial;
-           if (job->jv_exit_partial != NULL)
-           {
-               job->jv_exit_cb = opt->jo_exit_cb;
-               ++job->jv_exit_partial->pt_refcount;
-           }
-           else
-           {
-               job->jv_exit_cb = vim_strsave(opt->jo_exit_cb);
-               func_ref(job->jv_exit_cb);
-           }
-       }
+           copy_callback(&job->jv_exit_cb, &opt->jo_exit_cb);
     }
 }
 
@@ -5959,7 +5918,7 @@ job_info(job_T *job, dict_T *dict)
     dict_add_string(dict, "tty_out", job->jv_tty_out);
 
     dict_add_number(dict, "exitval", job->jv_exitval);
-    dict_add_string(dict, "exit_cb", job->jv_exit_cb);
+    dict_add_string(dict, "exit_cb", job->jv_exit_cb.cb_name);
     dict_add_string(dict, "stoponexit", job->jv_stoponexit);
 #ifdef UNIX
     dict_add_string(dict, "termsig", job->jv_termsig);
@@ -6059,7 +6018,8 @@ invoke_prompt_callback(void)
     curwin->w_cursor.lnum = lnum + 1;
     curwin->w_cursor.col = 0;
 
-    if (curbuf->b_prompt_callback == NULL || *curbuf->b_prompt_callback == NUL)
+    if (curbuf->b_prompt_callback.cb_name == NULL
+           || *curbuf->b_prompt_callback.cb_name == NUL)
        return;
     text = ml_get(lnum);
     prompt = prompt_text();
@@ -6069,9 +6029,8 @@ invoke_prompt_callback(void)
     argv[0].vval.v_string = vim_strsave(text);
     argv[1].v_type = VAR_UNKNOWN;
 
-    call_func(curbuf->b_prompt_callback, -1,
-             &rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE,
-             curbuf->b_prompt_partial, NULL);
+    call_callback(&curbuf->b_prompt_callback, -1,
+             &rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
     clear_tv(&argv[0]);
     clear_tv(&rettv);
 }
@@ -6086,15 +6045,14 @@ invoke_prompt_interrupt(void)
     int                dummy;
     typval_T   argv[1];
 
-    if (curbuf->b_prompt_interrupt == NULL
-                                       || *curbuf->b_prompt_interrupt == NUL)
+    if (curbuf->b_prompt_interrupt.cb_name == NULL
+           || *curbuf->b_prompt_interrupt.cb_name == NUL)
        return FALSE;
     argv[0].v_type = VAR_UNKNOWN;
 
     got_int = FALSE; // don't skip executing commands
-    call_func(curbuf->b_prompt_interrupt, -1,
-             &rettv, 0, argv, NULL, 0L, 0L, &dummy, TRUE,
-             curbuf->b_prompt_int_partial, NULL);
+    call_callback(&curbuf->b_prompt_interrupt, -1,
+             &rettv, 0, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
     clear_tv(&rettv);
     return TRUE;
 }
index dc96e050b06f438748161b516111719fce7e1d21..af7a4af8a6e3c0aa453a63c4809c5053fcee5490 100644 (file)
@@ -5920,10 +5920,10 @@ set_ref_in_item(
                dtv.vval.v_channel = job->jv_channel;
                set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
            }
-           if (job->jv_exit_partial != NULL)
+           if (job->jv_exit_cb.cb_partial != NULL)
            {
                dtv.v_type = VAR_PARTIAL;
-               dtv.vval.v_partial = job->jv_exit_partial;
+               dtv.vval.v_partial = job->jv_exit_cb.cb_partial;
                set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
            }
        }
@@ -5946,29 +5946,30 @@ set_ref_in_item(
                    set_ref_in_item(jq->jq_value, copyID, ht_stack, list_stack);
                for (cq = ch->ch_part[part].ch_cb_head.cq_next; cq != NULL;
                                                             cq = cq->cq_next)
-                   if (cq->cq_partial != NULL)
+                   if (cq->cq_callback.cb_partial != NULL)
                    {
                        dtv.v_type = VAR_PARTIAL;
-                       dtv.vval.v_partial = cq->cq_partial;
+                       dtv.vval.v_partial = cq->cq_callback.cb_partial;
                        set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
                    }
-               if (ch->ch_part[part].ch_partial != NULL)
+               if (ch->ch_part[part].ch_callback.cb_partial != NULL)
                {
                    dtv.v_type = VAR_PARTIAL;
-                   dtv.vval.v_partial = ch->ch_part[part].ch_partial;
+                   dtv.vval.v_partial =
+                                     ch->ch_part[part].ch_callback.cb_partial;
                    set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
                }
            }
-           if (ch->ch_partial != NULL)
+           if (ch->ch_callback.cb_partial != NULL)
            {
                dtv.v_type = VAR_PARTIAL;
-               dtv.vval.v_partial = ch->ch_partial;
+               dtv.vval.v_partial = ch->ch_callback.cb_partial;
                set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
            }
-           if (ch->ch_close_partial != NULL)
+           if (ch->ch_close_cb.cb_partial != NULL)
            {
                dtv.v_type = VAR_PARTIAL;
-               dtv.vval.v_partial = ch->ch_close_partial;
+               dtv.vval.v_partial = ch->ch_close_cb.cb_partial;
                set_ref_in_item(&dtv, copyID, ht_stack, list_stack);
            }
        }
index eaaa1e696fa089f61957f9cf0824930171a4f204..ccb8b3e89092e1d91ae3d305f499f6479d1d09d5 100644 (file)
@@ -9200,8 +9200,7 @@ f_printf(typval_T *argvars, typval_T *rettv)
 f_prompt_setcallback(typval_T *argvars, typval_T *rettv UNUSED)
 {
     buf_T      *buf;
-    char_u     *callback;
-    partial_T  *partial;
+    callback_T callback;
 
     if (check_secure())
        return;
@@ -9209,17 +9208,12 @@ f_prompt_setcallback(typval_T *argvars, typval_T *rettv UNUSED)
     if (buf == NULL)
        return;
 
-    callback = get_callback(&argvars[1], &partial);
-    if (callback == NULL)
+    callback = get_callback(&argvars[1]);
+    if (callback.cb_name == NULL)
        return;
 
-    free_callback(buf->b_prompt_callback, buf->b_prompt_partial);
-    if (partial == NULL)
-       buf->b_prompt_callback = vim_strsave(callback);
-    else
-       /* pointer into the partial */
-       buf->b_prompt_callback = callback;
-    buf->b_prompt_partial = partial;
+    free_callback(&buf->b_prompt_callback);
+    set_callback(&buf->b_prompt_callback, &callback);
 }
 
 /*
@@ -9229,8 +9223,7 @@ f_prompt_setcallback(typval_T *argvars, typval_T *rettv UNUSED)
 f_prompt_setinterrupt(typval_T *argvars, typval_T *rettv UNUSED)
 {
     buf_T      *buf;
-    char_u     *callback;
-    partial_T  *partial;
+    callback_T callback;
 
     if (check_secure())
        return;
@@ -9238,17 +9231,12 @@ f_prompt_setinterrupt(typval_T *argvars, typval_T *rettv UNUSED)
     if (buf == NULL)
        return;
 
-    callback = get_callback(&argvars[1], &partial);
-    if (callback == NULL)
+    callback = get_callback(&argvars[1]);
+    if (callback.cb_name == NULL)
        return;
 
-    free_callback(buf->b_prompt_interrupt, buf->b_prompt_int_partial);
-    if (partial == NULL)
-       buf->b_prompt_interrupt = vim_strsave(callback);
-    else
-       /* pointer into the partial */
-       buf->b_prompt_interrupt = callback;
-    buf->b_prompt_int_partial = partial;
+    free_callback(&buf->b_prompt_interrupt);
+    set_callback(&buf->b_prompt_interrupt, &callback);
 }
 
 /*
@@ -14631,44 +14619,106 @@ f_test_settime(typval_T *argvars, typval_T *rettv UNUSED)
 /*
  * Get a callback from "arg".  It can be a Funcref or a function name.
  * When "arg" is zero return an empty string.
- * Return NULL for an invalid argument.
+ * "cb_name" is not allocated.
+ * "cb_name" is set to NULL for an invalid argument.
  */
-    char_u *
-get_callback(typval_T *arg, partial_T **pp)
+    callback_T
+get_callback(typval_T *arg)
 {
+    callback_T res;
+
+    res.cb_free_name = FALSE;
     if (arg->v_type == VAR_PARTIAL && arg->vval.v_partial != NULL)
     {
-       *pp = arg->vval.v_partial;
-       ++(*pp)->pt_refcount;
-       return partial_name(*pp);
+       res.cb_partial = arg->vval.v_partial;
+       ++res.cb_partial->pt_refcount;
+       res.cb_name = partial_name(res.cb_partial);
     }
-    *pp = NULL;
-    if (arg->v_type == VAR_FUNC || arg->v_type == VAR_STRING)
+    else
     {
-       func_ref(arg->vval.v_string);
-       return arg->vval.v_string;
+       res.cb_partial = NULL;
+       if (arg->v_type == VAR_FUNC || arg->v_type == VAR_STRING)
+       {
+           // Note that we don't make a copy of the string.
+           res.cb_name = arg->vval.v_string;
+           func_ref(res.cb_name);
+       }
+       else if (arg->v_type == VAR_NUMBER && arg->vval.v_number == 0)
+       {
+           res.cb_name = (char_u *)"";
+       }
+       else
+       {
+           emsg(_("E921: Invalid callback argument"));
+           res.cb_name = NULL;
+       }
     }
-    if (arg->v_type == VAR_NUMBER && arg->vval.v_number == 0)
-       return (char_u *)"";
-    emsg(_("E921: Invalid callback argument"));
-    return NULL;
+    return res;
 }
 
 /*
- * Unref/free "callback" and "partial" returned by get_callback().
+ * Copy a callback into a typval_T.
  */
     void
-free_callback(char_u *callback, partial_T *partial)
+put_callback(callback_T *cb, typval_T *tv)
 {
-    if (partial != NULL)
-       partial_unref(partial);
-    else if (callback != NULL)
+    if (cb->cb_partial != NULL)
     {
-       func_unref(callback);
-       vim_free(callback);
+       tv->v_type = VAR_PARTIAL;
+       tv->vval.v_partial = cb->cb_partial;
+       ++tv->vval.v_partial->pt_refcount;
+    }
+    else
+    {
+       tv->v_type = VAR_FUNC;
+       tv->vval.v_string = vim_strsave(cb->cb_name);
+       func_ref(cb->cb_name);
     }
 }
 
+/*
+ * Make a copy of "src" into "dest", allocating the function name if needed,
+ * without incrementing the refcount.
+ */
+    void
+set_callback(callback_T *dest, callback_T *src)
+{
+    if (src->cb_partial == NULL)
+    {
+       // just a function name, make a copy
+       dest->cb_name = vim_strsave(src->cb_name);
+       dest->cb_free_name = TRUE;
+    }
+    else
+    {
+       // cb_name is a pointer into cb_partial
+       dest->cb_name = src->cb_name;
+       dest->cb_free_name = FALSE;
+    }
+    dest->cb_partial = src->cb_partial;
+}
+
+/*
+ * Unref/free "callback" returned by get_callback() or set_callback().
+ */
+    void
+free_callback(callback_T *callback)
+{
+    if (callback->cb_partial != NULL)
+    {
+       partial_unref(callback->cb_partial);
+       callback->cb_partial = NULL;
+    }
+    else if (callback->cb_name != NULL)
+       func_unref(callback->cb_name);
+    if (callback->cb_free_name)
+    {
+       vim_free(callback->cb_name);
+       callback->cb_free_name = FALSE;
+    }
+    callback->cb_name = NULL;
+}
+
 #ifdef FEAT_TIMERS
 /*
  * "timer_info([timer])" function
@@ -14723,9 +14773,8 @@ f_timer_start(typval_T *argvars, typval_T *rettv)
     long       msec = (long)tv_get_number(&argvars[0]);
     timer_T    *timer;
     int                repeat = 0;
-    char_u     *callback;
+    callback_T callback;
     dict_T     *dict;
-    partial_T  *partial;
 
     rettv->vval.v_number = -1;
     if (check_secure())
@@ -14742,21 +14791,16 @@ f_timer_start(typval_T *argvars, typval_T *rettv)
            repeat = dict_get_number(dict, (char_u *)"repeat");
     }
 
-    callback = get_callback(&argvars[1], &partial);
-    if (callback == NULL)
+    callback = get_callback(&argvars[1]);
+    if (callback.cb_name == NULL)
        return;
 
     timer = create_timer(msec, repeat);
     if (timer == NULL)
-       free_callback(callback, partial);
+       free_callback(&callback);
     else
     {
-       if (partial == NULL)
-           timer->tr_callback = vim_strsave(callback);
-       else
-           /* pointer into the partial */
-           timer->tr_callback = callback;
-       timer->tr_partial = partial;
+       set_callback(&timer->tr_callback, &callback);
        rettv->vval.v_number = (varnumber_T)timer->tr_id;
     }
 }
index f6d9f331fa91f39fc66e1b65c0a3e2a7b88a30c2..5a33bb128c3d82fe1870ca3f0e0336e37247b2d9 100644 (file)
@@ -282,7 +282,7 @@ remove_timer(timer_T *timer)
     static void
 free_timer(timer_T *timer)
 {
-    free_callback(timer->tr_callback, timer->tr_partial);
+    free_callback(&timer->tr_callback);
     vim_free(timer);
 }
 
@@ -325,9 +325,8 @@ timer_callback(timer_T *timer)
     argv[0].vval.v_number = (varnumber_T)timer->tr_id;
     argv[1].v_type = VAR_UNKNOWN;
 
-    call_func(timer->tr_callback, -1,
-                       &rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE,
-                       timer->tr_partial, NULL);
+    call_callback(&timer->tr_callback, -1,
+                       &rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
     clear_tv(&rettv);
 }
 
@@ -542,17 +541,8 @@ add_timer_info(typval_T *rettv, timer_T *timer)
     {
        if (dict_add(dict, di) == FAIL)
            vim_free(di);
-       else if (timer->tr_partial != NULL)
-       {
-           di->di_tv.v_type = VAR_PARTIAL;
-           di->di_tv.vval.v_partial = timer->tr_partial;
-           ++timer->tr_partial->pt_refcount;
-       }
        else
-       {
-           di->di_tv.v_type = VAR_FUNC;
-           di->di_tv.vval.v_string = vim_strsave(timer->tr_callback);
-       }
+           put_callback(&timer->tr_callback, &di->di_tv);
     }
 }
 
@@ -578,15 +568,15 @@ set_ref_in_timer(int copyID)
 
     for (timer = first_timer; timer != NULL; timer = timer->tr_next)
     {
-       if (timer->tr_partial != NULL)
+       if (timer->tr_callback.cb_partial != NULL)
        {
            tv.v_type = VAR_PARTIAL;
-           tv.vval.v_partial = timer->tr_partial;
+           tv.vval.v_partial = timer->tr_callback.cb_partial;
        }
        else
        {
            tv.v_type = VAR_FUNC;
-           tv.vval.v_string = timer->tr_callback;
+           tv.vval.v_string = timer->tr_callback.cb_name;
        }
        abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
     }
index f828d9187834b342b76a7cfdb6b0ec9fb2e2dbba..73b98beed1bac96fdf04e026455095b37a093782 100644 (file)
@@ -149,10 +149,10 @@ apply_options(win_T *wp, buf_T *buf UNUSED, dict_T *dict, int atcursor)
        if (get_lambda_tv(&ptr, &tv, TRUE) == OK)
        {
            wp->w_popup_timer = create_timer(nr, 0);
-           wp->w_popup_timer->tr_callback =
+           wp->w_popup_timer->tr_callback.cb_name =
                                  vim_strsave(partial_name(tv.vval.v_partial));
-           func_ref(wp->w_popup_timer->tr_callback);
-           wp->w_popup_timer->tr_partial = tv.vval.v_partial;
+           func_ref(wp->w_popup_timer->tr_callback.cb_name);
+           wp->w_popup_timer->tr_callback.cb_partial = tv.vval.v_partial;
        }
     }
 #endif
index 0f5b6554670158846c1ff839931c96607cc561c6..4184eefca536bc0b8adad1401739c948a3b86994 100644 (file)
@@ -12,7 +12,7 @@ channel_T *channel_open_func(typval_T *argvars);
 void channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err);
 void channel_set_job(channel_T *channel, job_T *job, jobopt_T *options);
 void channel_set_options(channel_T *channel, jobopt_T *opt);
-void channel_set_req_callback(channel_T *channel, ch_part_T part, char_u *callback, partial_T *partial, int id);
+void channel_set_req_callback(channel_T *channel, ch_part_T part, callback_T *callback, int id);
 void channel_buffer_free(buf_T *buf);
 void channel_write_any_lines(void);
 void channel_write_new_lines(buf_T *buf);
index 5a53136cfd08591ef83fb87d7e0fe2dfb51ae093..533b9823e7ce897a453226a76880fd480f3f0efc 100644 (file)
@@ -11,6 +11,8 @@ void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv);
 float_T vim_round(float_T f);
 long do_searchpair(char_u *spat, char_u *mpat, char_u *epat, int dir, typval_T *skip, int flags, pos_T *match_pos, linenr_T lnum_stop, long time_limit);
 void f_string(typval_T *argvars, typval_T *rettv);
-char_u *get_callback(typval_T *arg, partial_T **pp);
-void free_callback(char_u *callback, partial_T *partial);
+callback_T get_callback(typval_T *arg);
+void put_callback(callback_T *cb, typval_T *tv);
+void set_callback(callback_T *dest, callback_T *src);
+void free_callback(callback_T *callback);
 /* vim: set ft=c : */
index 25f1c3c6cee67537f0a42255d24f4e871b57fc7c..62babf3e7d100ecfb56d00599a87685d6d233800 100644 (file)
@@ -8,6 +8,7 @@ void save_funccal(funccal_entry_T *entry);
 void restore_funccal(void);
 void free_all_functions(void);
 int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv);
+int call_callback(callback_T *callback, int len, typval_T *rettv, int argcount, typval_T *argvars, int (*argv_func)(int, typval_T *, int), linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict);
 int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typval_T *argvars_in, int (*argv_func)(int, typval_T *, int), linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, partial_T *partial, dict_T *selfdict_in);
 char_u *trans_function_name(char_u **pp, int skip, int flags, funcdict_T *fdp, partial_T **partial);
 void ex_function(exarg_T *eap);
index da3162ec808da91195c43fd24d70ed4ef6e47259..2c164ca2bde368b0e37b095fb304f3ce0c7c16b6 100644 (file)
@@ -1237,6 +1237,17 @@ typedef struct dictvar_S dict_T;
 typedef struct partial_S partial_T;
 typedef struct blobvar_S blob_T;
 
+// Struct that holds both a normal function name and a partial_T, as used for a
+// callback argument.
+// When used temporarily "cb_name" is not allocated.  The refcounts to either
+// the function or the partial are incremented and need to be decremented
+// later with free_callback().
+typedef struct {
+    char_u     *cb_name;
+    partial_T  *cb_partial;
+    int                cb_free_name;       // cb_name was allocated
+} callback_T;
+
 typedef struct jobvar_S job_T;
 typedef struct readq_S readq_T;
 typedef struct writeq_S writeq_T;
@@ -1566,8 +1577,7 @@ struct jobvar_S
     char_u     *jv_tty_type;   // allocated
 #endif
     int                jv_exitval;
-    char_u     *jv_exit_cb;    /* allocated */
-    partial_T  *jv_exit_partial;
+    callback_T jv_exit_cb;
 
     buf_T      *jv_in_buf;     /* buffer from "in-name" */
 
@@ -1606,8 +1616,7 @@ struct jsonq_S
 
 struct cbq_S
 {
-    char_u     *cq_callback;
-    partial_T  *cq_partial;
+    callback_T cq_callback;
     int                cq_seq_nr;
     cbq_T      *cq_next;
     cbq_T      *cq_prev;
@@ -1689,8 +1698,7 @@ typedef struct {
     writeq_T   ch_writeque;    /* header for write queue */
 
     cbq_T      ch_cb_head;     /* dummy node for per-request callbacks */
-    char_u     *ch_callback;   /* call when a msg is not handled */
-    partial_T  *ch_partial;
+    callback_T ch_callback;    /* call when a msg is not handled */
 
     bufref_T   ch_bufref;      /* buffer to read from or write to */
     int                ch_nomodifiable; /* TRUE when buffer can be 'nomodifiable' */
@@ -1731,10 +1739,8 @@ struct channel_S {
 #ifdef MSWIN
     int                ch_named_pipe;  /* using named pipe instead of pty */
 #endif
-    char_u     *ch_callback;   /* call when any msg is not handled */
-    partial_T  *ch_partial;
-    char_u     *ch_close_cb;   /* call when channel is closed */
-    partial_T  *ch_close_partial;
+    callback_T ch_callback;    /* call when any msg is not handled */
+    callback_T ch_close_cb;    /* call when channel is closed */
     int                ch_drop_never;
     int                ch_keep_open;   /* do not close on read error */
     int                ch_nonblock;
@@ -1833,16 +1839,11 @@ typedef struct
     linenr_T   jo_in_top;
     linenr_T   jo_in_bot;
 
-    char_u     *jo_callback;   /* not allocated! */
-    partial_T  *jo_partial;    /* not referenced! */
-    char_u     *jo_out_cb;     /* not allocated! */
-    partial_T  *jo_out_partial; /* not referenced! */
-    char_u     *jo_err_cb;     /* not allocated! */
-    partial_T  *jo_err_partial; /* not referenced! */
-    char_u     *jo_close_cb;   /* not allocated! */
-    partial_T  *jo_close_partial; /* not referenced! */
-    char_u     *jo_exit_cb;    /* not allocated! */
-    partial_T  *jo_exit_partial; /* not referenced! */
+    callback_T jo_callback;
+    callback_T jo_out_cb;
+    callback_T jo_err_cb;
+    callback_T jo_close_cb;
+    callback_T jo_exit_cb;
     int                jo_drop_never;
     int                jo_waittime;
     int                jo_timeout;
@@ -1886,8 +1887,7 @@ struct listener_S
 {
     listener_T *lr_next;
     int                lr_id;
-    char_u     *lr_callback;
-    partial_T  *lr_partial;
+    callback_T lr_callback;
 };
 #endif
 
@@ -1950,13 +1950,12 @@ struct timer_S
 #ifdef FEAT_TIMERS
     timer_T    *tr_next;
     timer_T    *tr_prev;
-    proftime_T tr_due;             /* when the callback is to be invoked */
-    char       tr_firing;          /* when TRUE callback is being called */
-    char       tr_paused;          /* when TRUE callback is not invoked */
-    int                tr_repeat;          /* number of times to repeat, -1 forever */
-    long       tr_interval;        /* msec */
-    char_u     *tr_callback;       /* allocated */
-    partial_T  *tr_partial;
+    proftime_T tr_due;             // when the callback is to be invoked
+    char       tr_firing;          // when TRUE callback is being called
+    char       tr_paused;          // when TRUE callback is not invoked
+    int                tr_repeat;          // number of times to repeat, -1 forever
+    long       tr_interval;        // msec
+    callback_T tr_callback;
     int                tr_emsg_count;
 #endif
 };
@@ -2509,13 +2508,11 @@ struct file_buffer
     int                b_shortname;    /* this file has an 8.3 file name */
 
 #ifdef FEAT_JOB_CHANNEL
-    char_u     *b_prompt_text;      // set by prompt_setprompt()
-    char_u     *b_prompt_callback;  // set by prompt_setcallback()
-    partial_T  *b_prompt_partial;   // set by prompt_setcallback()
-    char_u     *b_prompt_interrupt;   // set by prompt_setinterrupt()
-    partial_T  *b_prompt_int_partial; // set by prompt_setinterrupt()
-    int                b_prompt_insert;     // value for restart_edit when entering
-                                    // a prompt buffer window.
+    char_u     *b_prompt_text;         // set by prompt_setprompt()
+    callback_T b_prompt_callback;      // set by prompt_setcallback()
+    callback_T b_prompt_interrupt;     // set by prompt_setinterrupt()
+    int                b_prompt_insert;        // value for restart_edit when entering
+                                       // a prompt buffer window.
 #endif
 #ifdef FEAT_MZSCHEME
     void       *b_mzscheme_ref; /* The MzScheme reference to this buffer */
index 06d2ecff654e2e23755daad754a8e414d09d090d..7abde07e354c9f1a1f739811dd6da55de015177b 100644 (file)
@@ -1446,6 +1446,30 @@ func_call(
     return r;
 }
 
+/*
+ * Invoke call_func() with a callback.
+ */
+    int
+call_callback(
+    callback_T *callback,
+    int                len,            // length of "name" or -1 to use strlen()
+    typval_T   *rettv,         // return value goes here
+    int                argcount,       // number of "argvars"
+    typval_T   *argvars,       // vars for arguments, must have "argcount"
+                               // PLUS ONE elements!
+    int                (* argv_func)(int, typval_T *, int),
+                               // function to fill in argvars
+    linenr_T   firstline,      // first line of range
+    linenr_T   lastline,       // last line of range
+    int                *doesrange,     // return: function handled range
+    int                evaluate,
+    dict_T     *selfdict)      // Dictionary for "self"
+{
+    return call_func(callback->cb_name, len, rettv, argcount, argvars,
+           argv_func, firstline, lastline, doesrange, evaluate,
+           callback->cb_partial, selfdict);
+}
+
 /*
  * Call a function with its resolved parameters
  *
index 352969fd889807045776e1bcc57d6bdeaab80e27..c7c19f3984ac4beb746b23941f6303e987f0120b 100644 (file)
@@ -767,6 +767,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1437,
 /**/
     1436,
 /**/