forked from aniani/vim
patch 8.0.1394: cannot intercept a yank command
Problem: Cannot intercept a yank command. Solution: Add the TextYankPost autocommand event. (Philippe Vaucher et al., closes #2333)
This commit is contained in:
@@ -330,6 +330,7 @@ Name triggered by ~
|
|||||||
|
|
||||||
|TextChanged| after a change was made to the text in Normal mode
|
|TextChanged| after a change was made to the text in Normal mode
|
||||||
|TextChangedI| after a change was made to the text in Insert mode
|
|TextChangedI| after a change was made to the text in Insert mode
|
||||||
|
|TextYankPost| after text is yanked or deleted
|
||||||
|
|
||||||
|ColorScheme| after loading a color scheme
|
|ColorScheme| after loading a color scheme
|
||||||
|
|
||||||
@@ -956,6 +957,26 @@ TextChangedI After a change was made to the text in the
|
|||||||
current buffer in Insert mode.
|
current buffer in Insert mode.
|
||||||
Not triggered when the popup menu is visible.
|
Not triggered when the popup menu is visible.
|
||||||
Otherwise the same as TextChanged.
|
Otherwise the same as TextChanged.
|
||||||
|
|TextYankPost|
|
||||||
|
TextYankPost After text has been yanked or deleted in the
|
||||||
|
current buffer. The following values of
|
||||||
|
|v:event| can be used to determine the operation
|
||||||
|
that triggered this autocmd:
|
||||||
|
operator The operation performed.
|
||||||
|
regcontents Text that was stored in the
|
||||||
|
register, as a list of lines,
|
||||||
|
like with: >
|
||||||
|
getreg(r, 1, 1)
|
||||||
|
< regname Name of the |register| or
|
||||||
|
empty string for the unnamed
|
||||||
|
register.
|
||||||
|
regtype Type of the register, see
|
||||||
|
|getregtype()|.
|
||||||
|
Not triggered when |quote_| is used nor when
|
||||||
|
called recursively.
|
||||||
|
It is not allowed to change the buffer text,
|
||||||
|
see |textlock|.
|
||||||
|
|
||||||
*User*
|
*User*
|
||||||
User Never executed automatically. To be used for
|
User Never executed automatically. To be used for
|
||||||
autocommands that are only executed with
|
autocommands that are only executed with
|
||||||
|
@@ -1554,6 +1554,12 @@ v:errors Errors found by assert functions, such as |assert_true()|.
|
|||||||
< If v:errors is set to anything but a list it is made an empty
|
< If v:errors is set to anything but a list it is made an empty
|
||||||
list by the assert function.
|
list by the assert function.
|
||||||
|
|
||||||
|
*v:event* *event-variable*
|
||||||
|
v:event Dictionary containing information about the current
|
||||||
|
|autocommand|. The dictionary is emptied when the |autocommand|
|
||||||
|
finishes, please refer to |dict-identity| for how to get an
|
||||||
|
independent copy of it.
|
||||||
|
|
||||||
*v:exception* *exception-variable*
|
*v:exception* *exception-variable*
|
||||||
v:exception The value of the exception most recently caught and not
|
v:exception The value of the exception most recently caught and not
|
||||||
finished. See also |v:throwpoint| and |throw-variables|.
|
finished. See also |v:throwpoint| and |throw-variables|.
|
||||||
|
36
src/dict.c
36
src/dict.c
@@ -47,6 +47,16 @@ dict_alloc(void)
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dict_T *
|
||||||
|
dict_alloc_lock(int lock)
|
||||||
|
{
|
||||||
|
dict_T *d = dict_alloc();
|
||||||
|
|
||||||
|
if (d != NULL)
|
||||||
|
d->dv_lock = lock;
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate an empty dict for a return value.
|
* Allocate an empty dict for a return value.
|
||||||
* Returns OK or FAIL.
|
* Returns OK or FAIL.
|
||||||
@@ -54,13 +64,12 @@ dict_alloc(void)
|
|||||||
int
|
int
|
||||||
rettv_dict_alloc(typval_T *rettv)
|
rettv_dict_alloc(typval_T *rettv)
|
||||||
{
|
{
|
||||||
dict_T *d = dict_alloc();
|
dict_T *d = dict_alloc_lock(0);
|
||||||
|
|
||||||
if (d == NULL)
|
if (d == NULL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
rettv_dict_set(rettv, d);
|
rettv_dict_set(rettv, d);
|
||||||
rettv->v_lock = 0;
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +89,7 @@ rettv_dict_set(typval_T *rettv, dict_T *d)
|
|||||||
* Free a Dictionary, including all non-container items it contains.
|
* Free a Dictionary, including all non-container items it contains.
|
||||||
* Ignores the reference count.
|
* Ignores the reference count.
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
dict_free_contents(dict_T *d)
|
dict_free_contents(dict_T *d)
|
||||||
{
|
{
|
||||||
int todo;
|
int todo;
|
||||||
@@ -102,6 +111,8 @@ dict_free_contents(dict_T *d)
|
|||||||
--todo;
|
--todo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The hashtab is still locked, it has to be re-initialized anyway */
|
||||||
hash_clear(&d->dv_hashtab);
|
hash_clear(&d->dv_hashtab);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -846,4 +857,23 @@ dict_list(typval_T *argvars, typval_T *rettv, int what)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make each item in the dict readonly (not the value of the item).
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
dict_set_items_ro(dict_T *di)
|
||||||
|
{
|
||||||
|
int todo = (int)di->dv_hashtab.ht_used;
|
||||||
|
hashitem_T *hi;
|
||||||
|
|
||||||
|
/* Set readonly */
|
||||||
|
for (hi = di->dv_hashtab.ht_array; todo > 0 ; ++hi)
|
||||||
|
{
|
||||||
|
if (HASHITEM_EMPTY(hi))
|
||||||
|
continue;
|
||||||
|
--todo;
|
||||||
|
HI2DI(hi)->di_flags |= DI_FLAGS_RO | DI_FLAGS_FIX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* defined(FEAT_EVAL) */
|
#endif /* defined(FEAT_EVAL) */
|
||||||
|
28
src/eval.c
28
src/eval.c
@@ -192,6 +192,7 @@ static struct vimvar
|
|||||||
{VV_NAME("termu7resp", VAR_STRING), VV_RO},
|
{VV_NAME("termu7resp", VAR_STRING), VV_RO},
|
||||||
{VV_NAME("termstyleresp", VAR_STRING), VV_RO},
|
{VV_NAME("termstyleresp", VAR_STRING), VV_RO},
|
||||||
{VV_NAME("termblinkresp", VAR_STRING), VV_RO},
|
{VV_NAME("termblinkresp", VAR_STRING), VV_RO},
|
||||||
|
{VV_NAME("event", VAR_DICT), VV_RO},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* shorthand */
|
/* shorthand */
|
||||||
@@ -319,8 +320,9 @@ eval_init(void)
|
|||||||
|
|
||||||
set_vim_var_nr(VV_SEARCHFORWARD, 1L);
|
set_vim_var_nr(VV_SEARCHFORWARD, 1L);
|
||||||
set_vim_var_nr(VV_HLSEARCH, 1L);
|
set_vim_var_nr(VV_HLSEARCH, 1L);
|
||||||
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
|
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED));
|
||||||
set_vim_var_list(VV_ERRORS, list_alloc());
|
set_vim_var_list(VV_ERRORS, list_alloc());
|
||||||
|
set_vim_var_dict(VV_EVENT, dict_alloc_lock(VAR_FIXED));
|
||||||
|
|
||||||
set_vim_var_nr(VV_FALSE, VVAL_FALSE);
|
set_vim_var_nr(VV_FALSE, VVAL_FALSE);
|
||||||
set_vim_var_nr(VV_TRUE, VVAL_TRUE);
|
set_vim_var_nr(VV_TRUE, VVAL_TRUE);
|
||||||
@@ -6632,6 +6634,16 @@ get_vim_var_list(int idx)
|
|||||||
return vimvars[idx].vv_list;
|
return vimvars[idx].vv_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get Dict v: variable value. Caller must take care of reference count when
|
||||||
|
* needed.
|
||||||
|
*/
|
||||||
|
dict_T *
|
||||||
|
get_vim_var_dict(int idx)
|
||||||
|
{
|
||||||
|
return vimvars[idx].vv_dict;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set v:char to character "c".
|
* Set v:char to character "c".
|
||||||
*/
|
*/
|
||||||
@@ -6706,25 +6718,13 @@ set_vim_var_list(int idx, list_T *val)
|
|||||||
void
|
void
|
||||||
set_vim_var_dict(int idx, dict_T *val)
|
set_vim_var_dict(int idx, dict_T *val)
|
||||||
{
|
{
|
||||||
int todo;
|
|
||||||
hashitem_T *hi;
|
|
||||||
|
|
||||||
clear_tv(&vimvars[idx].vv_di.di_tv);
|
clear_tv(&vimvars[idx].vv_di.di_tv);
|
||||||
vimvars[idx].vv_type = VAR_DICT;
|
vimvars[idx].vv_type = VAR_DICT;
|
||||||
vimvars[idx].vv_dict = val;
|
vimvars[idx].vv_dict = val;
|
||||||
if (val != NULL)
|
if (val != NULL)
|
||||||
{
|
{
|
||||||
++val->dv_refcount;
|
++val->dv_refcount;
|
||||||
|
dict_set_items_ro(val);
|
||||||
/* Set readonly */
|
|
||||||
todo = (int)val->dv_hashtab.ht_used;
|
|
||||||
for (hi = val->dv_hashtab.ht_array; todo > 0 ; ++hi)
|
|
||||||
{
|
|
||||||
if (HASHITEM_EMPTY(hi))
|
|
||||||
continue;
|
|
||||||
--todo;
|
|
||||||
HI2DI(hi)->di_flags |= DI_FLAGS_RO | DI_FLAGS_FIX;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
src/fileio.c
11
src/fileio.c
@@ -6478,6 +6478,7 @@ buf_modname(
|
|||||||
/*
|
/*
|
||||||
* Like fgets(), but if the file line is too long, it is truncated and the
|
* Like fgets(), but if the file line is too long, it is truncated and the
|
||||||
* rest of the line is thrown away. Returns TRUE for end-of-file.
|
* rest of the line is thrown away. Returns TRUE for end-of-file.
|
||||||
|
* If the line is truncated then buf[size - 2] will not be NUL.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
vim_fgets(char_u *buf, int size, FILE *fp)
|
vim_fgets(char_u *buf, int size, FILE *fp)
|
||||||
@@ -7856,6 +7857,7 @@ static struct event_name
|
|||||||
{"WinEnter", EVENT_WINENTER},
|
{"WinEnter", EVENT_WINENTER},
|
||||||
{"WinLeave", EVENT_WINLEAVE},
|
{"WinLeave", EVENT_WINLEAVE},
|
||||||
{"VimResized", EVENT_VIMRESIZED},
|
{"VimResized", EVENT_VIMRESIZED},
|
||||||
|
{"TextYankPost", EVENT_TEXTYANKPOST},
|
||||||
{NULL, (event_T)0}
|
{NULL, (event_T)0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -9399,6 +9401,15 @@ has_funcundefined(void)
|
|||||||
return (first_autopat[(int)EVENT_FUNCUNDEFINED] != NULL);
|
return (first_autopat[(int)EVENT_FUNCUNDEFINED] != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return TRUE when there is a TextYankPost autocommand defined.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
has_textyankpost(void)
|
||||||
|
{
|
||||||
|
return (first_autopat[(int)EVENT_TEXTYANKPOST] != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Execute autocommands for "event" and file name "fname".
|
* Execute autocommands for "event" and file name "fname".
|
||||||
* Return TRUE if some commands were executed.
|
* Return TRUE if some commands were executed.
|
||||||
|
67
src/ops.c
67
src/ops.c
@@ -1645,6 +1645,63 @@ shift_delete_registers()
|
|||||||
y_regs[1].y_array = NULL; /* set register one to empty */
|
y_regs[1].y_array = NULL; /* set register one to empty */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
yank_do_autocmd(oparg_T *oap, yankreg_T *reg)
|
||||||
|
{
|
||||||
|
static int recursive = FALSE;
|
||||||
|
dict_T *v_event;
|
||||||
|
list_T *list;
|
||||||
|
int n;
|
||||||
|
char_u buf[NUMBUFLEN + 2];
|
||||||
|
long reglen = 0;
|
||||||
|
|
||||||
|
if (recursive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
v_event = get_vim_var_dict(VV_EVENT);
|
||||||
|
|
||||||
|
list = list_alloc();
|
||||||
|
for (n = 0; n < reg->y_size; n++)
|
||||||
|
list_append_string(list, reg->y_array[n], -1);
|
||||||
|
list->lv_lock = VAR_FIXED;
|
||||||
|
dict_add_list(v_event, "regcontents", list);
|
||||||
|
|
||||||
|
buf[0] = (char_u)oap->regname;
|
||||||
|
buf[1] = NUL;
|
||||||
|
dict_add_nr_str(v_event, "regname", 0, buf);
|
||||||
|
|
||||||
|
buf[0] = get_op_char(oap->op_type);
|
||||||
|
buf[1] = get_extra_op_char(oap->op_type);
|
||||||
|
buf[2] = NUL;
|
||||||
|
dict_add_nr_str(v_event, "operator", 0, buf);
|
||||||
|
|
||||||
|
buf[0] = NUL;
|
||||||
|
buf[1] = NUL;
|
||||||
|
switch (get_reg_type(oap->regname, ®len))
|
||||||
|
{
|
||||||
|
case MLINE: buf[0] = 'V'; break;
|
||||||
|
case MCHAR: buf[0] = 'v'; break;
|
||||||
|
case MBLOCK:
|
||||||
|
vim_snprintf((char *)buf, sizeof(buf), "%c%ld", Ctrl_V,
|
||||||
|
reglen + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dict_add_nr_str(v_event, "regtype", 0, buf);
|
||||||
|
|
||||||
|
/* Lock the dictionary and its keys */
|
||||||
|
dict_set_items_ro(v_event);
|
||||||
|
|
||||||
|
recursive = TRUE;
|
||||||
|
textlock++;
|
||||||
|
apply_autocmds(EVENT_TEXTYANKPOST, NULL, NULL, FALSE, curbuf);
|
||||||
|
textlock--;
|
||||||
|
recursive = FALSE;
|
||||||
|
|
||||||
|
/* Empty the dictionary, v:event is still valid */
|
||||||
|
dict_free_contents(v_event);
|
||||||
|
hash_init(&v_event->dv_hashtab);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle a delete operation.
|
* Handle a delete operation.
|
||||||
*
|
*
|
||||||
@@ -1798,6 +1855,11 @@ op_delete(oparg_T *oap)
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FEAT_AUTOCMD
|
||||||
|
if (did_yank && has_textyankpost())
|
||||||
|
yank_do_autocmd(oap, y_current);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3270,6 +3332,11 @@ op_yank(oparg_T *oap, int deleting, int mess)
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef FEAT_AUTOCMD
|
||||||
|
if (!deleting && has_textyankpost())
|
||||||
|
yank_do_autocmd(oap, y_current);
|
||||||
|
#endif
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
fail: /* free the allocated lines */
|
fail: /* free the allocated lines */
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
/* dict.c */
|
/* dict.c */
|
||||||
dict_T *dict_alloc(void);
|
dict_T *dict_alloc(void);
|
||||||
|
dict_T *dict_alloc_lock(int lock);
|
||||||
int rettv_dict_alloc(typval_T *rettv);
|
int rettv_dict_alloc(typval_T *rettv);
|
||||||
void rettv_dict_set(typval_T *rettv, dict_T *d);
|
void rettv_dict_set(typval_T *rettv, dict_T *d);
|
||||||
|
void dict_free_contents(dict_T *d);
|
||||||
void dict_unref(dict_T *d);
|
void dict_unref(dict_T *d);
|
||||||
int dict_free_nonref(int copyID);
|
int dict_free_nonref(int copyID);
|
||||||
void dict_free_items(int copyID);
|
void dict_free_items(int copyID);
|
||||||
@@ -23,4 +25,5 @@ void dict_extend(dict_T *d1, dict_T *d2, char_u *action);
|
|||||||
dictitem_T *dict_lookup(hashitem_T *hi);
|
dictitem_T *dict_lookup(hashitem_T *hi);
|
||||||
int dict_equal(dict_T *d1, dict_T *d2, int ic, int recursive);
|
int dict_equal(dict_T *d1, dict_T *d2, int ic, int recursive);
|
||||||
void dict_list(typval_T *argvars, typval_T *rettv, int what);
|
void dict_list(typval_T *argvars, typval_T *rettv, int what);
|
||||||
|
void dict_set_items_ro(dict_T *di);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@@ -64,6 +64,7 @@ void set_vim_var_nr(int idx, varnumber_T val);
|
|||||||
varnumber_T get_vim_var_nr(int idx);
|
varnumber_T get_vim_var_nr(int idx);
|
||||||
char_u *get_vim_var_str(int idx);
|
char_u *get_vim_var_str(int idx);
|
||||||
list_T *get_vim_var_list(int idx);
|
list_T *get_vim_var_list(int idx);
|
||||||
|
dict_T * get_vim_var_dict(int idx);
|
||||||
void set_vim_var_char(int c);
|
void set_vim_var_char(int c);
|
||||||
void set_vcount(long count, long count1, int set_prevcount);
|
void set_vcount(long count, long count1, int set_prevcount);
|
||||||
void set_vim_var_string(int idx, char_u *val, int len);
|
void set_vim_var_string(int idx, char_u *val, int len);
|
||||||
|
@@ -51,6 +51,7 @@ int has_textchangedI(void);
|
|||||||
int has_insertcharpre(void);
|
int has_insertcharpre(void);
|
||||||
int has_cmdundefined(void);
|
int has_cmdundefined(void);
|
||||||
int has_funcundefined(void);
|
int has_funcundefined(void);
|
||||||
|
int has_textyankpost(void);
|
||||||
void block_autocmds(void);
|
void block_autocmds(void);
|
||||||
void unblock_autocmds(void);
|
void unblock_autocmds(void);
|
||||||
int is_autocmd_blocked(void);
|
int is_autocmd_blocked(void);
|
||||||
|
@@ -1124,3 +1124,42 @@ func Test_Filter_noshelltemp()
|
|||||||
let &shelltemp = shelltemp
|
let &shelltemp = shelltemp
|
||||||
bwipe!
|
bwipe!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_TextYankPost()
|
||||||
|
enew!
|
||||||
|
call setline(1, ['foo'])
|
||||||
|
|
||||||
|
let g:event = []
|
||||||
|
au TextYankPost * let g:event = copy(v:event)
|
||||||
|
|
||||||
|
call assert_equal({}, v:event)
|
||||||
|
call assert_fails('let v:event = {}', 'E46:')
|
||||||
|
call assert_fails('let v:event.mykey = 0', 'E742:')
|
||||||
|
|
||||||
|
norm "ayiw
|
||||||
|
call assert_equal(
|
||||||
|
\{'regcontents': ['foo'], 'regname': 'a', 'operator': 'y', 'regtype': 'v'},
|
||||||
|
\g:event)
|
||||||
|
norm y_
|
||||||
|
call assert_equal(
|
||||||
|
\{'regcontents': ['foo'], 'regname': '', 'operator': 'y', 'regtype': 'V'},
|
||||||
|
\g:event)
|
||||||
|
call feedkeys("\<C-V>y", 'x')
|
||||||
|
call assert_equal(
|
||||||
|
\{'regcontents': ['f'], 'regname': '', 'operator': 'y', 'regtype': "\x161"},
|
||||||
|
\g:event)
|
||||||
|
norm "xciwbar
|
||||||
|
call assert_equal(
|
||||||
|
\{'regcontents': ['foo'], 'regname': 'x', 'operator': 'c', 'regtype': 'v'},
|
||||||
|
\g:event)
|
||||||
|
norm "bdiw
|
||||||
|
call assert_equal(
|
||||||
|
\{'regcontents': ['bar'], 'regname': 'b', 'operator': 'd', 'regtype': 'v'},
|
||||||
|
\g:event)
|
||||||
|
|
||||||
|
call assert_equal({}, v:event)
|
||||||
|
|
||||||
|
au! TextYankPost
|
||||||
|
unlet g:event
|
||||||
|
bwipe!
|
||||||
|
endfunc
|
||||||
|
@@ -771,6 +771,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1394,
|
||||||
/**/
|
/**/
|
||||||
1393,
|
1393,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -1339,6 +1339,7 @@ enum auto_event
|
|||||||
EVENT_TEXTCHANGEDI, /* text was modified in Insert mode*/
|
EVENT_TEXTCHANGEDI, /* text was modified in Insert mode*/
|
||||||
EVENT_CMDUNDEFINED, /* command undefined */
|
EVENT_CMDUNDEFINED, /* command undefined */
|
||||||
EVENT_OPTIONSET, /* option was set */
|
EVENT_OPTIONSET, /* option was set */
|
||||||
|
EVENT_TEXTYANKPOST, /* after some text was yanked */
|
||||||
NUM_EVENTS /* MUST be the last one */
|
NUM_EVENTS /* MUST be the last one */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1988,7 +1989,8 @@ typedef int sock_T;
|
|||||||
#define VV_TERMU7RESP 83
|
#define VV_TERMU7RESP 83
|
||||||
#define VV_TERMSTYLERESP 84
|
#define VV_TERMSTYLERESP 84
|
||||||
#define VV_TERMBLINKRESP 85
|
#define VV_TERMBLINKRESP 85
|
||||||
#define VV_LEN 86 /* number of v: vars */
|
#define VV_EVENT 86
|
||||||
|
#define VV_LEN 87 /* number of v: vars */
|
||||||
|
|
||||||
/* used for v_number in VAR_SPECIAL */
|
/* used for v_number in VAR_SPECIAL */
|
||||||
#define VVAL_FALSE 0L
|
#define VVAL_FALSE 0L
|
||||||
|
Reference in New Issue
Block a user