patch 8.2.3725: cannot use a lambda for 'completefunc' and 'omnifunc'

Problem:    Cannot use a lambda for 'completefunc' and 'omnifunc'.
Solution:   Implement lambda support. (Yegappan Lakshmanan, closes #9257)
diff --git a/src/insexpand.c b/src/insexpand.c
index 630548b..92f0731 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -2237,6 +2237,113 @@
 }
 
 #ifdef FEAT_COMPL_FUNC
+
+# ifdef FEAT_EVAL
+static callback_T cfu_cb;	    // 'completefunc' callback function
+static callback_T ofu_cb;	    // 'omnifunc' callback function
+static callback_T tsrfu_cb;	    // 'thesaurusfunc' callback function
+# endif
+
+/*
+ * Copy a global callback function to a buffer local callback.
+ */
+    static void
+copy_global_to_buflocal_cb(callback_T *globcb, callback_T *bufcb)
+{
+    free_callback(bufcb);
+    if (globcb->cb_name != NULL && *globcb->cb_name != NUL)
+	copy_callback(bufcb, globcb);
+}
+
+/*
+ * Parse the 'completefunc' option value and set the callback function.
+ * Invoked when the 'completefunc' option is set. The option value can be a
+ * name of a function (string), or function(<name>) or funcref(<name>) or a
+ * lambda expression.
+ */
+    int
+set_completefunc_option(void)
+{
+    int	retval;
+
+    retval = option_set_callback_func(curbuf->b_p_cfu, &cfu_cb);
+    if (retval == OK)
+	set_buflocal_cfu_callback(curbuf);
+
+    return retval;
+}
+
+/*
+ * Copy the global 'completefunc' callback function to the buffer-local
+ * 'completefunc' callback for 'buf'.
+ */
+    void
+set_buflocal_cfu_callback(buf_T *buf UNUSED)
+{
+# ifdef FEAT_EVAL
+    copy_global_to_buflocal_cb(&cfu_cb, &buf->b_cfu_cb);
+# endif
+}
+
+/*
+ * Parse the 'omnifunc' option value and set the callback function.
+ * Invoked when the 'omnifunc' option is set. The option value can be a
+ * name of a function (string), or function(<name>) or funcref(<name>) or a
+ * lambda expression.
+ */
+    int
+set_omnifunc_option(void)
+{
+    int	retval;
+
+    retval = option_set_callback_func(curbuf->b_p_ofu, &ofu_cb);
+    if (retval == OK)
+	set_buflocal_ofu_callback(curbuf);
+
+    return retval;
+}
+
+/*
+ * Copy the global 'omnifunc' callback function to the buffer-local 'omnifunc'
+ * callback for 'buf'.
+ */
+    void
+set_buflocal_ofu_callback(buf_T *buf UNUSED)
+{
+# ifdef FEAT_EVAL
+    copy_global_to_buflocal_cb(&ofu_cb, &buf->b_ofu_cb);
+# endif
+}
+
+/*
+ * Parse the 'thesaurusfunc' option value and set the callback function.
+ * Invoked when the 'thesaurusfunc' option is set. The option value can be a
+ * name of a function (string), or function(<name>) or funcref(<name>) or a
+ * lambda expression.
+ */
+    int
+set_thesaurusfunc_option(void)
+{
+    int	retval;
+
+    if (*curbuf->b_p_tsrfu != NUL)
+    {
+	// buffer-local option set
+	free_callback(&curbuf->b_tsrfu_cb);
+	retval = option_set_callback_func(curbuf->b_p_tsrfu,
+							&curbuf->b_tsrfu_cb);
+    }
+    else
+    {
+	// global option set
+	free_callback(&tsrfu_cb);
+	retval = option_set_callback_func(p_tsrfu, &tsrfu_cb);
+    }
+
+    return retval;
+}
+
+
 /*
  * Get the user-defined completion function name for completion 'type'
  */
@@ -2257,6 +2364,20 @@
 }
 
 /*
+ * Get the callback to use for insert mode completion.
+ */
+    callback_T *
+get_insert_callback(int type)
+{
+    if (type == CTRL_X_FUNCTION)
+	return &curbuf->b_cfu_cb;
+    if (type == CTRL_X_OMNI)
+	return &curbuf->b_ofu_cb;
+    // CTRL_X_THESAURUS
+    return (*curbuf->b_p_tsrfu != NUL) ? &curbuf->b_tsrfu_cb : &tsrfu_cb;
+}
+
+/*
  * Execute user defined complete function 'completefunc', 'omnifunc' or
  * 'thesaurusfunc', and get matches in "matches".
  * "type" is either CTRL_X_OMNI or CTRL_X_FUNCTION or CTRL_X_THESAURUS.
@@ -2269,8 +2390,10 @@
     typval_T	args[3];
     char_u	*funcname;
     pos_T	pos;
+    callback_T	*cb;
     typval_T	rettv;
     int		save_State = State;
+    int		retval;
 
     funcname = get_complete_funcname(type);
     if (*funcname == NUL)
@@ -2289,8 +2412,11 @@
     // Insert mode in another buffer.
     ++textwinlock;
 
+    cb = get_insert_callback(type);
+    retval = call_callback(cb, 0, &rettv, 2, args);
+
     // Call a function, which returns a list or dict.
-    if (call_vim_function(funcname, 2, args, &rettv) == OK)
+    if (retval == OK)
     {
 	switch (rettv.v_type)
 	{
@@ -3971,6 +4097,7 @@
 	    char_u	*funcname;
 	    pos_T	pos;
 	    int		save_State = State;
+	    callback_T	*cb;
 
 	    // Call 'completefunc' or 'omnifunc' and get pattern length as a
 	    // string
@@ -3991,7 +4118,8 @@
 	    args[2].v_type = VAR_UNKNOWN;
 	    pos = curwin->w_cursor;
 	    ++textwinlock;
-	    col = call_func_retnr(funcname, 2, args);
+	    cb = get_insert_callback(ctrl_x_mode);
+	    col = call_callback_retnr(cb, 2, args);
 	    --textwinlock;
 
 	    State = save_State;
@@ -4339,6 +4467,11 @@
 free_insexpand_stuff(void)
 {
     VIM_CLEAR(compl_orig_text);
+# ifdef FEAT_EVAL
+    free_callback(&cfu_cb);
+    free_callback(&ofu_cb);
+    free_callback(&tsrfu_cb);
+# endif
 }
 #endif