trigger: add support for one-time triggers (closes #399)
This commit is contained in:
parent
0513800cb6
commit
1d3a75333e
@ -3006,6 +3006,11 @@ A trigger has the following options (names are
|
||||
| return_code | `ok`, `ok_eat`, `error` |
|
||||
The return code of callback (default is `ok`, which should be used in almost
|
||||
all triggers, the other values are rarely used).
|
||||
|
||||
| once_action | `none`, `disable`, `delete` |
|
||||
Action to take with the trigger after the trigger executes once (default is
|
||||
`none` which should be used in almost all triggers, the other values are
|
||||
rarely used).
|
||||
|===
|
||||
|
||||
For example, the default 'beep' trigger has following options:
|
||||
@ -3018,6 +3023,7 @@ trigger.trigger.beep.conditions = "${tg_highlight} || ${tg_msg_pv}"
|
||||
trigger.trigger.beep.regex = ""
|
||||
trigger.trigger.beep.command = "/print -beep"
|
||||
trigger.trigger.beep.return_code = ok
|
||||
trigger.trigger.beep.once_action = none
|
||||
----
|
||||
|
||||
[[trigger_execution]]
|
||||
@ -3030,6 +3036,8 @@ order, if triggers are globally enabled and if the trigger itself is enabled:
|
||||
. replace text in trigger using regular expression(s)
|
||||
. execute command(s)
|
||||
. exit with a return code (except for hooks 'modifier' and 'focus').
|
||||
. perform once action (when not `none`)
|
||||
|
||||
|
||||
[[trigger_hook_arguments]]
|
||||
==== Hook arguments
|
||||
|
@ -64,6 +64,18 @@
|
||||
if (extra_vars) \
|
||||
weechat_hashtable_free (extra_vars); \
|
||||
trigger->hook_running = 0; \
|
||||
switch (weechat_config_integer ( \
|
||||
trigger->options[TRIGGER_OPTION_ONCE_ACTION])) \
|
||||
{ \
|
||||
case TRIGGER_ONCE_DISABLE: \
|
||||
weechat_config_option_set ( \
|
||||
trigger->options[TRIGGER_OPTION_ENABLED], \
|
||||
"off", 1); \
|
||||
break; \
|
||||
case TRIGGER_ONCE_DELETE: \
|
||||
trigger_free (trigger); \
|
||||
break; \
|
||||
} \
|
||||
return __rc;
|
||||
|
||||
extern int trigger_callback_signal_cb (void *data, const char *signal,
|
||||
|
@ -59,9 +59,10 @@ trigger_command_display_trigger_internal (const char *name,
|
||||
int commands_count,
|
||||
char **commands,
|
||||
int return_code,
|
||||
int once_action,
|
||||
int verbose)
|
||||
{
|
||||
char str_conditions[64], str_regex[64], str_command[64], str_rc[64];
|
||||
char str_conditions[64], str_regex[64], str_command[64], str_rc[64], str_once[64];
|
||||
char spaces[256];
|
||||
int i, length;
|
||||
|
||||
@ -153,6 +154,15 @@ trigger_command_display_trigger_internal (const char *name,
|
||||
weechat_color ("reset"),
|
||||
trigger_return_code_string[return_code]);
|
||||
}
|
||||
if ((once_action >= 0) && (once_action != TRIGGER_ONCE_NONE))
|
||||
{
|
||||
weechat_printf_tags (NULL, "no_trigger",
|
||||
"%s %s=1 %s%s",
|
||||
spaces,
|
||||
weechat_color (weechat_config_string (trigger_config_color_flag_once_action)),
|
||||
weechat_color ("reset"),
|
||||
trigger_once_action_string[once_action]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -160,6 +170,7 @@ trigger_command_display_trigger_internal (const char *name,
|
||||
str_regex[0] = '\0';
|
||||
str_command[0] = '\0';
|
||||
str_rc[0] = '\0';
|
||||
str_once[0] = '\0';
|
||||
if (conditions && conditions[0])
|
||||
{
|
||||
snprintf (str_conditions, sizeof (str_conditions),
|
||||
@ -190,9 +201,16 @@ trigger_command_display_trigger_internal (const char *name,
|
||||
weechat_color (weechat_config_string (trigger_config_color_flag_return_code)),
|
||||
weechat_color ("reset"));
|
||||
}
|
||||
if ((once_action >= 0) && (once_action != TRIGGER_ONCE_NONE))
|
||||
{
|
||||
snprintf (str_once, sizeof (str_once),
|
||||
" %s=1%s",
|
||||
weechat_color (weechat_config_string (trigger_config_color_flag_once_action)),
|
||||
weechat_color ("reset"));
|
||||
}
|
||||
weechat_printf_tags (
|
||||
NULL, "no_trigger",
|
||||
" %s%s%s: %s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
" %s%s%s: %s%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
(enabled) ?
|
||||
weechat_color (weechat_config_string (trigger_config_color_trigger)) :
|
||||
weechat_color (weechat_config_string (trigger_config_color_trigger_disabled)),
|
||||
@ -209,7 +227,8 @@ trigger_command_display_trigger_internal (const char *name,
|
||||
str_conditions,
|
||||
str_regex,
|
||||
str_command,
|
||||
str_rc);
|
||||
str_rc,
|
||||
str_once);
|
||||
}
|
||||
}
|
||||
|
||||
@ -234,6 +253,7 @@ trigger_command_display_trigger (struct t_trigger *trigger, int verbose)
|
||||
trigger->commands_count,
|
||||
trigger->commands,
|
||||
weechat_config_integer (trigger->options[TRIGGER_OPTION_RETURN_CODE]),
|
||||
weechat_config_integer (trigger->options[TRIGGER_OPTION_ONCE_ACTION]),
|
||||
verbose);
|
||||
}
|
||||
|
||||
@ -306,6 +326,7 @@ trigger_command_list_default (int verbose)
|
||||
commands_count,
|
||||
commands,
|
||||
trigger_search_return_code (trigger_config_default_list[i][7]),
|
||||
trigger_search_once_action (trigger_config_default_list[i][8]),
|
||||
verbose);
|
||||
}
|
||||
|
||||
@ -553,6 +574,15 @@ trigger_command_trigger (void *data, struct t_gui_buffer *buffer, int argc,
|
||||
sargv[6]);
|
||||
goto end;
|
||||
}
|
||||
if ((sargc > 7) && sargv[7][0]
|
||||
&& (trigger_search_once_action (sargv[7]) < 0))
|
||||
{
|
||||
weechat_printf_tags (NULL, "no_trigger",
|
||||
_("%s%s: invalid once action \"%s\""),
|
||||
weechat_prefix ("error"), TRIGGER_PLUGIN_NAME,
|
||||
sargv[7]);
|
||||
goto end;
|
||||
}
|
||||
ptr_trigger = trigger_search (sargv[0]);
|
||||
if (ptr_trigger)
|
||||
{
|
||||
@ -596,7 +626,8 @@ trigger_command_trigger (void *data, struct t_gui_buffer *buffer, int argc,
|
||||
(sargc > 3) ? sargv[3] : "", /* conditions */
|
||||
(sargc > 4) ? sargv[4] : "", /* regex */
|
||||
(sargc > 5) ? sargv[5] : "", /* command */
|
||||
(sargc > 6) ? sargv[6] : ""); /* return code */
|
||||
(sargc > 6) ? sargv[6] : "", /* return code */
|
||||
(sargc > 7) ? sargv[7] : ""); /* once action */
|
||||
if (ptr_trigger)
|
||||
{
|
||||
weechat_printf_tags (NULL, "no_trigger",
|
||||
@ -983,7 +1014,8 @@ trigger_command_trigger (void *data, struct t_gui_buffer *buffer, int argc,
|
||||
trigger_config_default_list[j][4], /* conditions */
|
||||
trigger_config_default_list[j][5], /* regex */
|
||||
trigger_config_default_list[j][6], /* command */
|
||||
trigger_config_default_list[j][7]); /* return code */
|
||||
trigger_config_default_list[j][7], /* return code */
|
||||
trigger_config_default_list[j][8]); /* once action */
|
||||
weechat_printf_tags (NULL, "no_trigger",
|
||||
_("Trigger \"%s\" restored"),
|
||||
argv[i]);
|
||||
@ -1067,7 +1099,7 @@ trigger_command_init ()
|
||||
N_("list|listfull|listdefault"
|
||||
" || add|addoff|addreplace <name> <hook> [\"<arguments>\" "
|
||||
"[\"<conditions>\" [\"<regex>\" [\"<command>\" "
|
||||
"[\"<return_code>\"]]]]]"
|
||||
"[\"<return_code>\" [\"<once_action>\"]]]]]]"
|
||||
" || addinput [<hook>]"
|
||||
" || input|output|recreate <name>"
|
||||
" || set <name> <option> <value>"
|
||||
@ -1106,6 +1138,8 @@ trigger_command_init ()
|
||||
" command: command to execute (many commands can be separated by "
|
||||
"\";\"\n"
|
||||
"return_code: return code in callback (ok (default), ok_eat, error)\n"
|
||||
"once_action: action to take after execution (none (default), "
|
||||
"disable, delete)\n"
|
||||
" addinput: set input with default arguments to create a trigger\n"
|
||||
" input: set input with the command used to create the trigger\n"
|
||||
" output: send the command to create the trigger on the buffer\n"
|
||||
@ -1166,7 +1200,7 @@ trigger_command_init ()
|
||||
"list|listfull|listdefault"
|
||||
" || add|addoff|addreplace %(trigger_names) %(trigger_hooks) "
|
||||
"%(trigger_hook_arguments) %(trigger_hook_conditions) "
|
||||
"%(trigger_hook_regex) %(trigger_hook_command) %(trigger_hook_rc)"
|
||||
"%(trigger_hook_regex) %(trigger_hook_command) %(trigger_hook_rc) %(trigger_once)"
|
||||
" || addinput %(trigger_hooks)"
|
||||
" || input|output|recreate %(trigger_names)"
|
||||
" || set %(trigger_names) %(trigger_options)|name %(trigger_option_value)"
|
||||
|
@ -411,6 +411,32 @@ trigger_completion_hook_rc_cb (void *data, const char *completion_item,
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds default once actions to completion list.
|
||||
*/
|
||||
|
||||
int
|
||||
trigger_completion_once_cb (void *data, const char *completion_item,
|
||||
struct t_gui_buffer *buffer,
|
||||
struct t_gui_completion *completion)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* make C compiler happy */
|
||||
(void) data;
|
||||
(void) completion_item;
|
||||
(void) buffer;
|
||||
|
||||
for (i = 0; i < TRIGGER_NUM_ONCE_ACTIONS; i++)
|
||||
{
|
||||
weechat_hook_completion_list_add (completion,
|
||||
trigger_once_action_string[i], 0, WEECHAT_LIST_POS_END);
|
||||
}
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Hooks completions.
|
||||
*/
|
||||
@ -451,4 +477,7 @@ trigger_completion_init ()
|
||||
weechat_hook_completion ("trigger_hook_rc",
|
||||
N_("default return codes for hook callback"),
|
||||
&trigger_completion_hook_rc_cb, NULL);
|
||||
weechat_hook_completion ("trigger_once",
|
||||
N_("trigger once actions"),
|
||||
&trigger_completion_once_cb, NULL);
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ struct t_config_option *trigger_config_color_flag_command;
|
||||
struct t_config_option *trigger_config_color_flag_conditions;
|
||||
struct t_config_option *trigger_config_color_flag_regex;
|
||||
struct t_config_option *trigger_config_color_flag_return_code;
|
||||
struct t_config_option *trigger_config_color_flag_once_action;
|
||||
struct t_config_option *trigger_config_color_regex;
|
||||
struct t_config_option *trigger_config_color_replace;
|
||||
struct t_config_option *trigger_config_color_trigger;
|
||||
@ -56,7 +57,8 @@ char *trigger_config_default_list[][1 + TRIGGER_NUM_OPTIONS] =
|
||||
"${tg_displayed} && (${tg_highlight} || ${tg_msg_pv})",
|
||||
"",
|
||||
"/print -beep",
|
||||
"ok" },
|
||||
"ok",
|
||||
"" },
|
||||
/* hide passwords in commands */
|
||||
{ "cmd_pass", "on",
|
||||
"modifier",
|
||||
@ -72,6 +74,7 @@ char *trigger_config_default_list[][1 + TRIGGER_NUM_OPTIONS] =
|
||||
"(.*)"
|
||||
"==${re:1}${hide:*,${re:+}}",
|
||||
"",
|
||||
"",
|
||||
"" },
|
||||
/* hide password in IRC auth message displayed */
|
||||
{ "msg_auth", "on",
|
||||
@ -81,6 +84,7 @@ char *trigger_config_default_list[][1 + TRIGGER_NUM_OPTIONS] =
|
||||
"==^(.*(id|identify|register|ghost +[^ ]+|release +[^ ]+) +)(.*)"
|
||||
"==${re:1}${hide:*,${re:+}}",
|
||||
"",
|
||||
"",
|
||||
"" },
|
||||
/* hide server password in commands /server and /connect */
|
||||
{ "server_pass", "on",
|
||||
@ -90,8 +94,9 @@ char *trigger_config_default_list[][1 + TRIGGER_NUM_OPTIONS] =
|
||||
"==^(/(server|connect) .*-(sasl_)?password=)([^ ]+)(.*)"
|
||||
"==${re:1}${hide:*,${re:4}}${re:5}"
|
||||
"",
|
||||
"",
|
||||
"" },
|
||||
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
|
||||
};
|
||||
|
||||
|
||||
@ -340,6 +345,14 @@ trigger_config_create_trigger_option (const char *trigger_name, int index_option
|
||||
"ok|ok_eat|error", 0, 0, value, NULL, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
break;
|
||||
case TRIGGER_OPTION_ONCE_ACTION:
|
||||
ptr_option = weechat_config_new_option (
|
||||
trigger_config_file, trigger_config_section_trigger,
|
||||
option_name, "integer",
|
||||
N_("action to take after execution"),
|
||||
"none|disable|delete", 0, 0, value, NULL, 0, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL);
|
||||
break;
|
||||
case TRIGGER_NUM_OPTIONS:
|
||||
break;
|
||||
}
|
||||
@ -638,6 +651,12 @@ trigger_config_init ()
|
||||
N_("text color for return code flag (in /trigger list)"),
|
||||
NULL, 0, 0, "lightmagenta", NULL, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
trigger_config_color_flag_once_action = weechat_config_new_option (
|
||||
trigger_config_file, ptr_section,
|
||||
"flag_once_action", "color",
|
||||
N_("text color for once action flag (in /trigger list)"),
|
||||
NULL, 0, 0, "lightblue", NULL, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
trigger_config_color_regex = weechat_config_new_option (
|
||||
trigger_config_file, ptr_section,
|
||||
"regex", "color",
|
||||
|
@ -33,6 +33,7 @@ extern struct t_config_option *trigger_config_color_flag_command;
|
||||
extern struct t_config_option *trigger_config_color_flag_conditions;
|
||||
extern struct t_config_option *trigger_config_color_flag_regex;
|
||||
extern struct t_config_option *trigger_config_color_flag_return_code;
|
||||
extern struct t_config_option *trigger_config_color_flag_once_action;
|
||||
extern struct t_config_option *trigger_config_color_regex;
|
||||
extern struct t_config_option *trigger_config_color_replace;
|
||||
extern struct t_config_option *trigger_config_color_trigger;
|
||||
|
@ -44,9 +44,9 @@ struct t_weechat_plugin *weechat_trigger_plugin = NULL;
|
||||
|
||||
char *trigger_option_string[TRIGGER_NUM_OPTIONS] =
|
||||
{ "enabled", "hook", "arguments", "conditions", "regex", "command",
|
||||
"return_code" };
|
||||
"return_code", "once_action" };
|
||||
char *trigger_option_default[TRIGGER_NUM_OPTIONS] =
|
||||
{ "on", "signal", "", "", "", "", "ok" };
|
||||
{ "on", "signal", "", "", "", "", "ok", "none" };
|
||||
|
||||
char *trigger_hook_type_string[TRIGGER_NUM_HOOK_TYPES] =
|
||||
{ "signal", "hsignal", "modifier", "print", "command", "command_run", "timer",
|
||||
@ -64,6 +64,9 @@ char *trigger_hook_regex_default_var[TRIGGER_NUM_HOOK_TYPES] =
|
||||
{ "tg_signal_data", "", "tg_string", "tg_message", "tg_argv_eol1", "tg_command",
|
||||
"tg_remaining_calls", "tg_value", "" };
|
||||
|
||||
char *trigger_once_action_string[TRIGGER_NUM_ONCE_ACTIONS] =
|
||||
{ "none", "disable", "delete" };
|
||||
|
||||
char *trigger_return_code_string[TRIGGER_NUM_RETURN_CODES] =
|
||||
{ "ok", "ok_eat", "error" };
|
||||
int trigger_return_code[TRIGGER_NUM_RETURN_CODES] =
|
||||
@ -145,6 +148,27 @@ trigger_search_return_code (const char *return_code)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Searches for trigger once action.
|
||||
*
|
||||
* Returns index of once action in enum t_trigger_once_action, -1 if not found.
|
||||
*/
|
||||
|
||||
int
|
||||
trigger_search_once_action (const char *once_action)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < TRIGGER_NUM_ONCE_ACTIONS; i++)
|
||||
{
|
||||
if (weechat_strcasecmp (trigger_once_action_string[i], once_action) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
/* return code not found */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Searches for a trigger by name.
|
||||
*
|
||||
@ -872,7 +896,8 @@ trigger_new_with_options (const char *name, struct t_config_option **options)
|
||||
struct t_trigger *
|
||||
trigger_new (const char *name, const char *enabled, const char *hook,
|
||||
const char *arguments, const char *conditions, const char *regex,
|
||||
const char *command, const char *return_code)
|
||||
const char *command, const char *return_code,
|
||||
const char *once_action)
|
||||
{
|
||||
struct t_config_option *option[TRIGGER_NUM_OPTIONS];
|
||||
const char *value[TRIGGER_NUM_OPTIONS];
|
||||
@ -897,6 +922,7 @@ trigger_new (const char *name, const char *enabled, const char *hook,
|
||||
value[TRIGGER_OPTION_REGEX] = regex;
|
||||
value[TRIGGER_OPTION_COMMAND] = command;
|
||||
value[TRIGGER_OPTION_RETURN_CODE] = return_code;
|
||||
value[TRIGGER_OPTION_ONCE_ACTION] = once_action;
|
||||
|
||||
for (i = 0; i < TRIGGER_NUM_OPTIONS; i++)
|
||||
{
|
||||
@ -933,7 +959,8 @@ trigger_create_default ()
|
||||
trigger_config_default_list[i][4], /* conditions */
|
||||
trigger_config_default_list[i][5], /* regex */
|
||||
trigger_config_default_list[i][6], /* command */
|
||||
trigger_config_default_list[i][7]); /* return code */
|
||||
trigger_config_default_list[i][7], /* return code */
|
||||
trigger_config_default_list[i][8]); /* once action */
|
||||
}
|
||||
}
|
||||
|
||||
@ -1017,7 +1044,8 @@ trigger_copy (struct t_trigger *trigger, const char *name)
|
||||
weechat_config_string (trigger->options[TRIGGER_OPTION_CONDITIONS]),
|
||||
weechat_config_string (trigger->options[TRIGGER_OPTION_REGEX]),
|
||||
weechat_config_string (trigger->options[TRIGGER_OPTION_COMMAND]),
|
||||
weechat_config_string (trigger->options[TRIGGER_OPTION_RETURN_CODE]));
|
||||
weechat_config_string (trigger->options[TRIGGER_OPTION_RETURN_CODE]),
|
||||
weechat_config_string (trigger->options[TRIGGER_OPTION_ONCE_ACTION]));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1105,6 +1133,9 @@ trigger_print_log ()
|
||||
weechat_log_printf (" return_code . . . . . . : %d ('%s')",
|
||||
weechat_config_integer (ptr_trigger->options[TRIGGER_OPTION_RETURN_CODE]),
|
||||
trigger_return_code_string[weechat_config_integer (ptr_trigger->options[TRIGGER_OPTION_RETURN_CODE])]);
|
||||
weechat_log_printf (" once_action . . . . . . : %d ('%s')",
|
||||
weechat_config_integer (ptr_trigger->options[TRIGGER_OPTION_ONCE_ACTION]),
|
||||
trigger_once_action_string[weechat_config_integer (ptr_trigger->options[TRIGGER_OPTION_ONCE_ACTION])]);
|
||||
weechat_log_printf (" hooks_count . . . . . . : %d", ptr_trigger->hooks_count);
|
||||
weechat_log_printf (" hooks . . . . . . . . . : 0x%lx", ptr_trigger->hooks);
|
||||
for (i = 0; i < ptr_trigger->hooks_count; i++)
|
||||
|
@ -38,6 +38,7 @@ enum t_trigger_option
|
||||
TRIGGER_OPTION_REGEX, /* replace text with 1 or more regex */
|
||||
TRIGGER_OPTION_COMMAND, /* command run if conditions are OK */
|
||||
TRIGGER_OPTION_RETURN_CODE, /* return code for hook callback */
|
||||
TRIGGER_OPTION_ONCE_ACTION, /* action to take after execution */
|
||||
/* number of trigger options */
|
||||
TRIGGER_NUM_OPTIONS,
|
||||
};
|
||||
@ -57,6 +58,15 @@ enum t_trigger_hook_type
|
||||
TRIGGER_NUM_HOOK_TYPES,
|
||||
};
|
||||
|
||||
enum t_trigger_once_action
|
||||
{
|
||||
TRIGGER_ONCE_NONE = 0,
|
||||
TRIGGER_ONCE_DISABLE,
|
||||
TRIGGER_ONCE_DELETE,
|
||||
/* number of once actions */
|
||||
TRIGGER_NUM_ONCE_ACTIONS,
|
||||
};
|
||||
|
||||
enum t_trigger_return_code
|
||||
{
|
||||
TRIGGER_RC_OK = 0,
|
||||
@ -112,6 +122,7 @@ extern char *trigger_hook_option_values;
|
||||
extern char *trigger_hook_default_arguments[];
|
||||
extern char *trigger_hook_default_rc[];
|
||||
extern char *trigger_hook_regex_default_var[];
|
||||
extern char *trigger_once_action_string[];
|
||||
extern char *trigger_return_code_string[];
|
||||
extern int trigger_return_code[];
|
||||
extern struct t_trigger *triggers;
|
||||
@ -124,6 +135,7 @@ extern int trigger_enabled;
|
||||
extern int trigger_search_option (const char *option_name);
|
||||
extern int trigger_search_hook_type (const char *type);
|
||||
extern int trigger_search_return_code (const char *return_code);
|
||||
extern int trigger_search_once_action (const char *once_action);
|
||||
extern struct t_trigger *trigger_search (const char *name);
|
||||
extern struct t_trigger *trigger_search_with_option (struct t_config_option *option);
|
||||
extern void trigger_regex_free (int *regex_count,
|
||||
@ -149,7 +161,8 @@ extern struct t_trigger *trigger_new (const char *name,
|
||||
const char *conditions,
|
||||
const char *replace,
|
||||
const char *command,
|
||||
const char *return_code);
|
||||
const char *return_code,
|
||||
const char *once_action);
|
||||
extern void trigger_create_default ();
|
||||
extern int trigger_rename (struct t_trigger *trigger, const char *name);
|
||||
extern struct t_trigger *trigger_copy (struct t_trigger *trigger,
|
||||
|
Loading…
x
Reference in New Issue
Block a user