Here is variant with buffer allocated on stack (patch attached):
static char_u *
do_insert_char_pre(c)
int c;
{
char_u *res = NULL;
#ifdef FEAT_MBYTE
char_u buf[MB_MAXBYTES];
#else
char_u buf[2];
#endif
/* Return quickly when there is nothing to do. */
if (!has_insertcharpre())
return NULL;
#ifdef FEAT_MBYTE
if (has_mbyte)
buf[(*mb_char2bytes)(c, buf)] = NUL;
else
#endif
{
buf[0] = c;
buf[1] = NUL;
}
/* Lock the text to avoid weird things from happening. */
++textlock;
set_vim_var_string(VV_CHAR, buf, -1); /* set v:char */
if (apply_autocmds(EVENT_INSERTCHARPRE, NULL, NULL, FALSE, curbuf))
/* Get the new value of v:char. It may be empty or more than one
* character. */
if (strcmp(buf, get_vim_var_str(VV_CHAR)))
res = vim_strsave(get_vim_var_str(VV_CHAR));
set_vim_var_string(VV_CHAR, NULL, -1); /* clear v:char */
--textlock;
return res;
}
2012/5/29 Alexey Radkov <[email protected]>
> Btw it is expensive to allocate memory for 'char_u* old' in the latest
> patch. Instead it makes sense to do something like in eval.c in function
> set_vim_var_char() where a buffer is allocated on stack.
>
>
> 2012/5/28 Alexey Radkov <[email protected]>
>
>> I found a better solution.
>>
>> The problematic piece in edit() is
>>
>> if (!p_paste)
>> {
>> /* Trigger InsertCharPre. */
>> char_u *str = do_insert_char_pre(c);
>> char_u *p;
>>
>> if (str != NULL)
>> {
>> if (*str != NUL && stop_arrow() != FAIL)
>> {
>> /* Insert the new value of v:char literally. */
>> for (p = str; *p != NUL; mb_ptr_adv(p))
>> {
>> c = PTR2CHAR(p);
>> if (c == CAR || c == K_KENTER || c == NL)
>> ins_eol(c);
>> else
>> ins_char(c);
>> }
>> AppendToRedobuffLit(str, -1);
>> }
>> vim_free(str);
>> c = NUL;
>> }
>>
>> /* If the new value is already inserted or an empty string
>> * then don't insert any character. */
>> if (c == NUL)
>> break;
>> }
>>
>> (i removed lines i inserted in previous patch). do_insert_char_pre()
>> always returns not null so we go into block 'if (str != NULL)' and
>> eventually break out of the wrapping for-loop skipping indentation,
>> textwidth processing etc. Better solution is to make do_insert_char_pre()
>> return NULL if VV_CHAR has not been changed: it will ensure that we do not
>> break the for-loop in case of autocmds which do not change VV_CHAR like
>>
>>
>> autocmd InsertCharPre * let a = 1
>>
>> I changed do_insert_char_pre() to make it return NULL if VV_CHAR is not
>> changed:
>>
>> static char_u *
>> do_insert_char_pre(c)
>> int c;
>> {
>> char_u *res = NULL, *old;
>>
>> /* Return quickly when there is nothing to do. */
>> if (!has_insertcharpre())
>> return NULL;
>>
>> /* Lock the text to avoid weird things from happening. */
>> ++textlock;
>> set_vim_var_char(c); /* set v:char */
>>
>> old = vim_strsave(get_vim_var_str(VV_CHAR));
>>
>> if (apply_autocmds(EVENT_INSERTCHARPRE, NULL, NULL, FALSE, curbuf))
>> /* Get the new value of v:char. It may be empty or more than one
>> * character. */
>> if (old && strcmp(old, get_vim_var_str(VV_CHAR)))
>> res = vim_strsave(get_vim_var_str(VV_CHAR));
>>
>> vim_free(old);
>> set_vim_var_string(VV_CHAR, NULL, -1); /* clear v:char */
>> --textlock;
>>
>> return res;
>> }
>>
>> Now it works fine for autoindenting and textwidth. New patch is (also
>> attached):
>>
>>
>> diff -r 1c6b099ead89 src/edit.c
>> --- a/src/edit.c Sun May 27 00:37:51 2012 +0200
>> +++ b/src/edit.c Mon May 28 23:36:12 2012 +0400
>> @@ -10108,7 +10108,7 @@
>> do_insert_char_pre(c)
>> int c;
>> {
>> - char_u *res;
>> + char_u *res = NULL, *old;
>>
>> /* Return quickly when there is nothing to do. */
>> if (!has_insertcharpre())
>> @@ -10118,13 +10118,15 @@
>> ++textlock;
>> set_vim_var_char(c); /* set v:char */
>>
>> + old = vim_strsave(get_vim_var_str(VV_CHAR));
>> +
>> if (apply_autocmds(EVENT_INSERTCHARPRE, NULL, NULL, FALSE, curbuf))
>> /* Get the new value of v:char. It may be empty or more than one
>> * character. */
>> - res = vim_strsave(get_vim_var_str(VV_CHAR));
>> - else
>> - res = NULL;
>> -
>> + if (old && strcmp(old, get_vim_var_str(VV_CHAR)))
>> + res = vim_strsave(get_vim_var_str(VV_CHAR));
>> +
>> + vim_free(old);
>> set_vim_var_string(VV_CHAR, NULL, -1); /* clear v:char */
>> --textlock;
>>
>>
>> Cheers, Alexey.
>>
>>
>>
>>
>> 2012/5/28 Alexey Radkov <[email protected]>
>>
>>> Just found that automatic line break when textwidth is set is also
>>> broken.
>>>
>>>
>>> 2012/5/28 Bram Moolenaar <[email protected]>
>>>
>>>>
>>>> Alexey Radkov wrote:
>>>>
>>>> > It is simple.
>>>> >
>>>> > Open some C/C++ code in vim (after patch 461), then
>>>> >
>>>> > :set cinoptions=:0(0+2s "this does not really matter, just my
>>>> settings
>>>> > :set cindent
>>>> > :autocmd InsertCharPre * let a = 1
>>>> >
>>>> > write something like
>>>> >
>>>> > int a()
>>>> > {
>>>> >
>>>> > Now after you insert <CR> '{' must move to the left as you use
>>>> cindent.
>>>> > After patch 461 it will stay.
>>>> > Further, if you use cvim, a closing brace after <CR> will be inserted.
>>>> > After patch 461 this will look this way:
>>>> >
>>>> > int a()
>>>> > {
>>>> > <CURSOR>
>>>> > }
>>>> >
>>>> > <<< MUST BE
>>>> >
>>>> > int a()
>>>> > {
>>>> > <CURSOR>
>>>> > }
>>>> >
>>>> > >>>
>>>> >
>>>> > The problem is that in case if InsertCharPre is defined for '*' it
>>>> will
>>>> > always trigger and prevent autoindent of cindent! I am not sure that
>>>> the
>>>> > patch that i sent is completely correct: it just fixes the problem
>>>> for me.
>>>> >
>>>> > Cheers, Alexey.
>>>>
>>>> Yasuhiro, can you reproduce this?
>>>>
>>>> --
>>>> login: yes
>>>> password: I don't know, please tell me
>>>> password is incorrect
>>>> login: yes
>>>> password: incorrect
>>>>
>>>> /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
>>>> /// sponsor Vim, vote for features --
>>>> http://www.Vim.org/sponsor/ \\\
>>>> \\\ an exciting new programming language -- http://www.Zimbu.org
>>>> ///
>>>> \\\ help me help AIDS victims -- http://ICCF-Holland.org
>>>> ///
>>>>
>>>
>>>
>>
>
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
InsertCharPre_autoindent_3.patch
Description: Binary data
