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

Attachment: InsertCharPre_autoindent_3.patch
Description: Binary data

Raspunde prin e-mail lui